# Upgrading to v2.24

This release unifies configuration for queues, repos, and services, and renames the maintenance
plugins to top-level modules. No migration is required, and all configuration changes are
backward compatible—you can adopt them incrementally.

## Bump Your Deps

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

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

## Move Plugins to Service Configuration (Optional)

Maintenance plugins are now services with first-class configuration keys: `cron`, `lifeline`,
`pruner`, and `reindexer`. Move entries out of the `:plugins` list and onto dedicated keys:

```diff
 config :my_app, Oban,
-  plugins: [
-    {Oban.Plugins.Cron, crontab: [{"0 2 * * *", MyApp.Nightly}]},
-    Oban.Plugins.Lifeline,
-    {Oban.Plugins.Pruner, max_age: 60 * 60 * 24 * 7}
-  ]
+  cron: [crontab: [{"0 2 * * *", MyApp.Nightly}]],
+  lifeline: Oban.Lifeline,
+  pruner: [max_age: {7, :days}]
```

A keyword list configures the default service, a `module` or `{module, opts}` tuple configures an
alternative, and `false` disables it. The `:plugins` list still works and remains available for
custom plugins.

## Update Telemetry Handlers (Optional)

The maintenance plugins now live directly in the Oban namespace:

- `Oban.Plugins.Cron` becomes `Oban.Cron`
- `Oban.Plugins.Lifeline` becomes `Oban.Lifeline`
- `Oban.Plugins.Pruner` becomes `Oban.Pruner`
- `Oban.Plugins.Reindexer` becomes `Oban.Reindexer`

The old modules are deprecated shims that delegate to the new ones, and legacy names in
configuration are translated automatically. However, because the renamed module is what runs,
plugin telemetry metadata and registry keys report the new names. Update any telemetry handlers,
log filters, or alerts that match on the old module names:

```diff
-def handle_event([:oban, :plugin, :stop], _, %{plugin: Oban.Plugins.Pruner} = meta, _) do
+def handle_event([:oban, :plugin, :stop], _, %{plugin: Oban.Pruner} = meta, _) do
```

## Group Repo Options (Optional)

The top-level `log` and `get_dynamic_repo` options are soft-deprecated in favor of passing them
through a `:repo` tuple:

```diff
 config :my_app, Oban,
-  repo: MyApp.Repo,
-  log: false,
-  get_dynamic_repo: fn -> MyApp.Repo end
+  repo: {MyApp.Repo, log: false, dynamic_repo: fn -> MyApp.Repo end}
```

## Configure the Stager as a Service (Optional)

The `stage_interval` option is soft-deprecated in favor of the `stager` service key, which
accepts the same forms as other services:

```diff
 config :my_app, Oban,
-  stage_interval: 5_000
+  stager: [interval: {5, :seconds}]
```

## Switch to scheduled_in (Optional)

The `schedule_in` job option is soft-deprecated in favor of `scheduled_in`, which pairs naturally
with `scheduled_at`. Testing helpers accept a matching `scheduled_in` option as well:

```diff
-MyApp.Worker.new(%{id: 1}, schedule_in: 3600)
+MyApp.Worker.new(%{id: 1}, scheduled_in: 3600)
```

All soft-deprecated options continue to work and are rewritten transparently, without deprecation
warnings.
