Upgrading to v1.5

This release introduces centralized, mandatory migrations along with clearer module-based composition for workers.

Before Upgrading

The index-backed uniqueness in Pro v1.5 requires uniq_key and uniq_bmp values to be present in the meta for all unique jobs. Without those values on existing jobs, new unique jobs won't be correctly detected as duplicates.

If uniqueness is essential to your system, upgrade to Pro v1.4.13+ and let it run as long as your longest unique period before upgrading to v1.5. For example, if your longest unique period is 1 day, let it run for at least a day. That will ensure the correct unique values are present for index-backed uniqueness when you upgrade.

Bump Your Deps

Update Oban and Pro to the latest versions:

{:oban, "~> 2.18"},
{:oban_pro, "~> 1.5.0-rc.5", repo: "oban"}

Run Oban.Pro.Migration

Pro now has centralized, versioned migrations like Oban (but a little better). The versioned migrations replace all of the piecemeal migrations for additional tables and indexes. Now it's all handled automatically and you'll see a warning at runtime if migrations aren't up-to-date.

Generate a new migration:

$ mix ecto.gen.migration upgrade_oban_pro

Within the generated migration module:

use Ecto.Migration

def up, do: Oban.Pro.Migration.up(version: "1.5.0")

def down, do: Oban.Pro.Migration.down()

See the Oban.Pro.Migration module docs for additional options.

Update Chains (Optional)

Chaining is now possible for any Pro worker and the Oban.Pro.Workers.Chain module is deprecated.

Existing chains will still function as before, but old chains and new chains are incompatible because the old chain mechanism was subject to conflicts that could block chains erroneously.

Switch by replacing the Chain worker for the :chain option

 defmodule MyApp.SomeChain do
-  use Oban.Pro.Workers.Chain, by: :worker
+  use Oban.Pro.Worker, chain: [by: :worker]
 end

The new chain system is preemptive and much faster than before. It no longer uses polling or snoozing for concurrency controls, and you can remove any global partitioning add for chain optimization:

 queues: [
-  chained: [local_limit: 10, global_limit: [allowed: 10, partition: :worker]]
+  chained: [local_limit: 10]
 ]

Before Changing

To have a seamless transition between old and new chains, allow old chains to run for a little while. That will ensure the new chain id is injected into legacy chains and the new chains can pick up without any overlap.

Update Workflows (Optional)

Workflows may be comprised of any Pro worker and the Oban.Pro.Workers.Workflow module is deprecated. The change is backward compatible and old workflows will still function, but the mechanism is deprecated.

Start the switch by replacing all usage of Oban.Pro.Workers.Workflow to Oban.Pro.Worker:

-use Oban.Pro.Workers.Workflow
+use Oban.Pro.Worker

Now those workers don't define new_workflow/1, add/3, or other workflow functions. Replace any calls to new_workflow with Oban.Pro.Workflow.new/1:

- MyApp.SomeWorkflow.new_workflow()
+ Oban.Pro.Workflow.new()

Likewise, switch all other workflow function calls to call Oban.Pro.Workflow instead. For example, to switch over to Oban.Pro.Workflow.add/3:

- MyApp.SomeWorkflow.add(:dep_a, MyApp.SomeWorkflow.new(%{}))
- MyApp.SomeWorkflow.add(:dep_b, MyApp.SomeWorkflow.new(%{}))
+ Oban.Pro.Workflow.add(:dep_a, MyApp.SomeWorkflow.new(%{}))
+ Oban.Pro.Workflow.add(:dep_b, MyApp.SomeWorkflow.new(%{}))

Finally, there is no longer a gen_id callback, so you must explicitly pass any custom workflow ids into Oban.Pro.Workflow.new/1:

Workflow.new(workflow_id: "custom-workflow-id-123")

Update Batches (Optional)

Like workflows, batches may now be comprised of any Pro worker. The change is backward compatible and old Oban.Pro.Workers.Batch workers will still function, but that mechanism is deprecated.

Switching should be entirely mechanical for most applications. Start by replacing all instances of Oban.Pro.Workers.Batch with Oban.Pro.Batch:

-use Oban.Pro.Workers.Batch
+use Oban.Pro.Worker

Those workers no longer have any of the old batch callback functions injected. Instead of using new_batch, you'll call Oban.Pro.Batch.new/2:

-MyApp.BatchWorker.new_batch(jobs)
+Oban.Pro.Batch.new(jobs)

Batch callback jobs now support most standard job opts, not just queue and args. Those opts are now declared with callback_opts:

-MyApp.BatchWorker.new_batch(jobs, batch_callback_args: %{some: :args})
+Oban.Pro.Batch.new(jobs, callback_opts: [args: %{some: :args}])

Batch callbacks are all renamed from having a generic handle_ prefix, to a more explicit batch_ prefix. To use the new callbacks declare the Oban.Pro.Batch behaviour and rename each callback function. For example, to rename handle_attempted:

+@behaviour Oban.Pro.Batch

-@impl Oban.Pro.Workers.Batch
+@impl Oban.Pro.Batch
-def handle_attempted(job) do
+def batch_attempted(job) do
   ...
 end