# Upgrading to v2.11

This Oban release includes a required migration and a couple of optional, but
recommended, changes.

## Bump Your Deps

Update Oban, Web, and Pro to the latest versions:

```elixir
[
  {:oban, "~> 2.11"},
  {:oban_pro, "~> 0.10", repo: "oban"},
  {:oban_web, "~> 2.9", repo: "oban"}
]
```

## Run Oban.Migrations for v11

Oban's new leadership mechanism uses an unlogged table to track state globally.
The v11 migration creates a new `oban_peers` table, and is required for
leadership—without it many plugins won't run.

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

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

Within the generated migration module:

```elixir
use Ecto.Migration

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

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

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

The `Oban.Peer` module will safely handle a missing `oban_peers` table and log a
warning.

## Update Notifier Names

Now that we've pulled the `PG` notifier in from Oban Pro there are a few
naming changes you should make.

1. If your config explicitly declares `Oban.PostgresNotifier`, change it to the
   new namespaced version: `Oban.Notifiers.Postgres`:

```diff
-notifier: Oban.PostgresNotifier
+notifier: Oban.Notifiers.Postgres
```

2. If you are using Pro's `PG` notifier, change it to the new namespaced version
   from Oban:

```diff
-notifier: Oban.Pro.Notifiers.PG
+notifier: Oban.Notifiers.PG
```

## Check Configuration for Multi-Node Setups

This release introduces centralized leadership through the `Oban.Peer`
behaviour. To prevent duplicate plugin work across nodes, only one Oban instance
within a cluster may be the leader. Unfortunately, if a node that doesn't run
plugins becomes the leader then jobs may get stuck as `available` and plugins
like `Cron` or `Pruner` won't run.

The simplest solution is avoid `plugins: false` altogether:

```diff
-plugins: false
+plugins: []
```

See the [Troubleshooting guide](./troubleshooting.md) for more context.

## Swap the Compound Index (Optional, but Recommended)

Oban uses a single compound index for most queries. The index is comprised of
job `state`, `queue`, `priority`, `scheduled_at`, and `id`. That single index is
flexible enough to power most of Oban's queries. However, the column order is
important, and the order created by Oban's migrations isn't optimal in all
situations.

If you're experiencing slow plugin queries, e.g. the `Stager`, then you may
benefit from swapping the indexes. To do so, create a migration:

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

Within the generated migration module:

```elixir
@disable_ddl_transaction true
@disable_migration_lock true

def change do
  create_if_not_exists index(
    :oban_jobs,
    [:state, :queue, :priority, :scheduled_at, :id],
    concurrently: true,
    prefix: "public"
  )

  drop_if_exists index(
    :oban_jobs,
    [:queue, :state, :priority, :scheduled_at, :id],
    concurrently: true,
    prefix: "public"
  )
end
```

Be sure to reference the correct prefix if your `oban_jobs` table uses a prefix
other than `public`.
