1.0.0
- First stable release, the public API is expected to remain compatible within a given major version.
- Configurable dequeue lock strategy (
:advisory,:skiplocked,:hybrid) via:lock_strategy/GOOD_JOB_LOCK_STRATEGY, with claiming implemented inGoodJob.Job.Claimand alock_typecolumn ongood_jobs(see migrationadd_lock_type_to_good_jobs). - Optional idle shutdown via
:idle_timeout/GOOD_JOB_IDLE_TIMEOUT, usingGoodJob.IdleTrackerandGoodJob.IdleShutdownso the supervision tree can stop after sustained idle; the scheduler reports activity to the tracker. - Batch improvements:
Batchacceptsproperties(stored asserialized_properties);Batch.enqueue_all/1enqueues members throughGoodJob.Bulkso PostgreSQLNOTIFYruns once for the batch; empty batches trigger completion;Batch.check_completion/2takes a transaction-level advisory lock on the batch id;JobExecutorcallscheck_completionfor bothbatch_idandbatch_callback_idso parent batches finish after callback jobs;GoodJob.ModuleResolverresolves callback module name strings safely. GoodJob.enqueue/3is split intoprepare_enqueue/3andcommit_enqueue/1for reuse; job attributes includebatch_callback_idwhen set; enqueue options passlisten_notifythrough toJob.enqueue/2.- Expose
GoodJob.Bulk.notify_after_bulk_flush/1for custom bulk insert paths that suppress per-row NOTIFY and emit a single notification afterward. - README and COMPATIBILITY copy updates (shared schema and retry wording).
- Respect
enable_pausesduring dequeue by excluding paused queues and job classes stored ingood_job_settings, replacing the previous no-opexclude_paused/1behavior. - On worker task exit (
:DOWN),GoodJob.JobRecoveryclears the job lock and finalizes open execution rows so work is not left blocked until stale-lock or lifeline recovery runs. - Maintain
executions_countonly in the executor path;JobPerformerno longer increments it when claiming jobs, aligning attempt counts with retries andmax_attempts. - Throttle stale-lock cleanup in production while performing a sweep on each attempt in the test environment for deterministic tests.
- Resolve the process lock identifier once per scheduler at startup via
ProcessTracker.id_for_lock/0and reuse it for claims; simplify process-tracker state by removing the prior per-poll lock counter. - Concurrency-gated enqueue retries on advisory lock contention:
GoodJob.enqueue/3matches{:ok, {:error, :lock_failed}}from EctoRepo.transaction/1(arity 0), with bounded retries and a short delay between attempts. stale_lock_release_after_seconds/GOOD_JOB_STALE_LOCK_RELEASE_AFTER_SECONDS(default 60) configures how old a row lock may be before the periodic stale-lock sweep clearslocked_by_id(raise for jobs that run longer than a minute without updating lock state).- Support
listen_notify: falseonJob.enqueue/2for bulk inserts and emit a single PostgreSQLNOTIFYafter the batch transaction commits. - Parse concurrency limits from
serialized_params(includinggood_job_*fields andgood_job_concurrency_config) for jobs enqueued from other runtimes using the same serialization. - Implement
GoodJob.RepoPool.configure_repo/1to return{:ok, after_connect: &GoodJob.RepoPool.set_timeouts/1}for optional per-connection statement and lock timeouts.
0.3.0
- Introduce configurable advisory lock key derivation (lock function and hash strategy)
- Add preserved-job cleanup by max-count limits
- Implement
GoodJob.BulkAPI for buffered/atomic bulk enqueue workflows - Refine execution mode handling and application startup behavior
- Update core and example dependencies to latest compatible versions
0.2.0
- Update dependencies to the latest supported versions
0.1.1
- Align Elixir execution semantics with Ruby GoodJob protocol handling
- Improve concurrency limits, throttling, and perform-limit behaviors
- Expand ActiveJob serialization/deserialization coverage and compatibility
- Harden job execution result handling and error propagation
- Improve scheduler and process tracking behavior and test coverage
- Add telemetry formatter coverage and cleanup/batch handling improvements
- Update monorepo example with cross-language concurrency and GlobalID jobs
0.1.0
- Initial public release of
good_job.ex - PostgreSQL backend with advisory locks for run-once safety
- LISTEN/NOTIFY integration for low-latency job dispatch
- Worker behavior and macro (
use GoodJob.Job) - Job state machine with explicit states and transitions
- Execution modes:
:inline,:async,:async_all,:async_server,:external - Retry backoff strategy with exponential backoff and jitter
- Executor pattern for structured job execution
- Engine pattern (Basic and Inline engines)
- Job timeouts (per-job timeout configuration)
- Testing helpers (
GoodJob.Testingmodule) - Test infrastructure (test/support/repo_case.ex, test/support/job_case.ex)
- Job callbacks (before_enqueue, after_enqueue, before_perform, after_perform, on_error)
- Cleanup functionality
- Setting management (pause/unpause)
- Mix task for installation (
mix good_job.install) - Mix aliases (test.ci, test.setup, test.reset, release, analyze)
- Queue management with ordered queues, queue-specific concurrency, and semicolon-separated pools
- Cron job manager implementation
- Batch job operations
- Concurrency controls (per-key limits and throttling)
- ActiveJob API compatibility (
perform_now,perform_later,set,new().perform())