# Upgrading to v2.20

This Oban release includes an optional, but recommended migration.

## Bump Your Deps

Update Oban (and optionally Pro) to the latest versions:

```elixir
[
  {:oban, "~> 2.20"},
]
```

## Run Oban.Migrations for v13 (Optional)

The v13 migration adds compound indexes for `cancelled_at` and `discarded_at` columns. This is
done to improve `Oban.Plugins.Pruner` performance for cancelled and discarded jobs.

To get started, create a migration to create the table:

```bash
$ mix ecto.gen.migration upgrade_oban_jobs_to_v13
```

Within the generated migration module:

```elixir
use Ecto.Migration

def up, do: Oban.Migrations.up(version: 13)

def down, do: Oban.Migrations.down(version: 13)
```

If you have multiple Oban instances, or use an alternate prefix, you'll need to run the migration
for each prefix.

## Update Unique States (Optional)

Prior to v2.20, you may have specified unique states as custom lists:

```elixir
use Oban.Worker, unique: [states: [:scheduled, :available, :executing]]
use Oban.Worker, unique: [states: [:available, :scheduled, :executing, :retryable]]
```

Now you can use predefined unique groups that are safer and more standardized. The available
groups are:

- **`:all`** - All job states: `[:scheduled, :available, :executing, :retryable, :completed, :discarded, :cancelled]`
- **`:incomplete`** - Jobs that haven't finished: `[:available, :scheduled, :executing, :retryable]`
- **`:scheduled`** - Only scheduled jobs: `[:scheduled]`
- **`:successful`** - Jobs that can complete successfully: `[:available, :scheduled, :executing, :retryable, :completed]`

### Migration Examples

Replace custom state lists with the appropriate group:

```diff
# For jobs that should be unique while incomplete
-use Oban.Worker, unique: [states: [:scheduled, :available, :executing, :retryable]]
+use Oban.Worker, unique: [states: :incomplete]

# For jobs that should be unique across all states
-use Oban.Worker, unique: [states: [:scheduled, :available, :executing, :retryable, :completed, :discarded, :cancelled]]
+use Oban.Worker, unique: [states: :all]

# For jobs that should be unique only when scheduled
-use Oban.Worker, unique: [states: [:scheduled]]
+use Oban.Worker, unique: [states: :scheduled]

# For jobs that should be unique while they can still complete successfully
-use Oban.Worker, unique: [states: [:available, :scheduled, :executing, :retryable, :completed]]
+use Oban.Worker, unique: [states: :successful]
```

These groups reduce the chance of misconfiguration and make unique constraints more predictable
across your application.
