Changelog for Oban v2.20
View Sourceπ Looking for changes to Oban Pro? Check the Oban.Pro Changelog π
This release brings a fantastic new helper function, an optional migration to aid pruning, some stability improvements, and a bevy of documentation updates.
See the Upgrade Guide for optional upgrade instructions.
π¦ Update Job
This introduces the Oban.update_job/2,3 function to simplify updating existing jobs while
ensuring data consistency and safety. Previously, updating jobs required manually constructing
change operations or complex queries that could lead to race conditions or invalid state changes.
Only a curated subset of job fields, e.g. :args, :max_attempts, :meta, etc. may be updated
and they use the same validation rules as insertion to prevent invalid data. Updates are also
wrapped in a transaction with locking clauses to prevent concurrent modifications.
The function supports direct map changes:
Oban.update_job(job, %{priority: 0, tags: ["urgent"]})It also has a convenient function-based mode for dynamic changes:
Oban.update_job(job, fn job ->
%{meta: Map.put(job.meta, "processed_by", current_node())}
end)βοΈ Unique State Groups
There are now named unique state groups to replace custom state lists for unique jobs, promoting better uniqueness design and reducing configuration errors.
Previously, developers had to manually specify lists of job states for uniqueness, which was error-prone and could lead to subtle bugs when states were omitted or incorrectly combined. The new predefined groups ensure correctness and consistency across applications.
The new state groups are:
:all- All job states:incomplete- Jobs that haven't finished (~w(available scheduled executing retryable)a):scheduled- Only scheduled jobs ([:scheduled]):successful- Jobs that completed successfully (~w(available scheduled executing retryable completed)a)
These groups eliminate the risk of accidentally creating incomplete or incorrect state lists that could allow duplicate jobs to be created when they shouldn't be, or prevent valid job creation when duplicates should be allowed.
πͺΊ Nested Plugin Supervision
Plugins and the internal Stager are now nested within a secondary supervision tree to improve system resilience and stability.
Previously, plugins were supervised directly under the main Oban supervisor alongside core process. This meant that plugin failures could potentially impact the entire Oban system, and frequent plugin restarts could trigger cascading failures in the primary supervision tree.
The new supervisor has more lenient restart limits to allow for more plugin restart attempts before giving up. This change makes Oban more robust in production environments where plugins may experience transient failures due to database or connectivity issues.
v2.20.2 β 2025-12-04
Enhancements
[Telemetry] Add domain to
attach_default_loggermetadataAlthough this information is present in the source attribute, itβs not part of the metadata, itβs part of the attributes. And when
encode = true, itβs generated as a string, which makes it less convenient to work with.[Cron] Add unique cron entry identifiers to job meta
A id value is generated for each cron entry and stored in the job's meta to distinguish between different cron jobs with the same expression.
Bug Fixes
[Stager] Order staging query to maximize compound index usage
The core compound index couldn't be utilized by staging queries when the planner estimated a large number of hits. Changing the query to order by
scheduled_atandid, it becomes an index scan.It would still be more efficient to use a dedicated index, but OSS doesn't have any mechanisms for automatic concurrent index creation and we have to save it for later.
[Executor] Take measurements from the executing process
When Producer starts jobs, it calls
Executor.newin its own process, before handing it off toTask.Supervisor.async_nolinkto callExecutor.call. That means it used the Producerpid, and took measurements from that process.[Oban] Set
scheduledstate correctly when updating withupdate_job/3When the
scheduled_attimestamp is set duringupdate_job, the state is automatically set toscheduled. This mirrors the functionality ofinsert_job.Note that the value of the timestamp isn't considered. Setting a timestamp in the past will set the job as
scheduled. This isn't a problem in practice because the stager will change the state toavailableon the next cycle anyhow.[Repo] Include
:deadlock_detectedin expected errorsDeadlocks are automatically resolved by Postgres because it aborts one transaction. At that point, the retry should succeed quickly since the blocking transaction is gone.
v2.20.1 β 2025-08-15
Bug Fixes
[Worker] Handle missing fields in unique Worker validation.
Workers that specified
keyswithoutfieldswould fail validation at compile time. Now default values are considered foruse Oban.Workeras well asJob.new/2.
v2.20.0 β 2025-08-13
Enhancements
MigrationAdd V13 migration for indexing cancelled and discarded states.A new V13 migration adds compound indexes to significantly improve
Oban.Plugins.Prunerperformance when cleaning updiscardedandcancelledjobs. This is especially beneficial for applications that process large volumes of jobs and retain them for extended periods.RepoExpose dynamic repo switching aswith_dynamic_repo/2The function was previously internal, which made impossible to use in external modules or extend upon. Now custom plugins and extensions can use
Repo.with_dynamic_repo/2to use the configured dynamic repo options.
Bug Fixes
[Oban] Allow
insert_all/1,3via Oban facadeThe
insert_all/1andinsert_all/3function variants were missing from the generated Oban facade functions when using a named instance.[Testing] Generate correct
perform_job/1,2,3clauses.The
perform_job/2,3clauses generated byuse Oban.Testingdidn't handle theperform_job/2variant designed to run jobs created withbuild_job/3. This caused test failures when trying to execute jobs built using thebuild_job/3helper function.The fix generates the missing
perform_job/2clause along with a convenientperform_job/1variant, ensuring all testing scenarios work seamlessly regardless of how jobs are constructed.[Testing] Restrict inline execution to
availableandscheduledstates.Jobs in the
completedstate or other non-runnable states were incorrectly attempted by the inline engine, potentially causing errors or unexpected behavior during testing.[Worker] Disallow
:keyswhen:fieldsdoesn't contain:argsor:metaUnique job configurations using
:keyswere allowed even when:fieldsdidn't include:argsor:meta, which would result in runtime errors since keys can only extract values from these keyable fields.[Cron] Fix error message when the crontab has an invalid range.
Cron validation errors for invalid ranges were returning exception structs instead of readable error messages, making it difficult to understand and fix crontab configuration issues.