All notable changes to this project are documented here. The format follows Keep a Changelog and the project uses Semantic Versioning.

Unreleased

0.2.1 - 2026-10-22

First release published to Hex.

Changed

  • :retry_storm now honours its window for retryable jobs too: a retryable job counts only if its last failed attempt started within the window (attempted_at >= now - window, with a redundant scheduled_at >= now - window bound so the query is an index range scan on Oban's (state, queue, priority, scheduled_at, id) index). Up to v0.2.0 every retryable job counted regardless of the window, so a worker with many jobs waiting out long backoffs from failures hours ago could fire a "retry storm in the last 300s". Expect fewer :retry_storm findings after upgrading.
  • :orphaned findings and docs now say what is measured: execution age only. The message reads "executing for up to N s (limit L s), far beyond any expected runtime; possibly orphaned by a node crash or shutdown, or genuinely still running" instead of implying the node died. The check name is unchanged.

Documentation

  • README: "Piloting safely" (report-only rollout, what to measure, tuning, retention for history-based checks); :stalled also fires for queues whose slots are all held by long-running jobs.
  • docs/OBAN_PRO_COMPATIBILITY.md and an Oban Pro row under "Engine support": likely compatible, unverified and untested, with the Pro features known to skew results.
  • docs/SECURITY_REVIEW.md: updated :retry_storm SQL listing.

0.2.0 - 2026-10-22

First public release, tagged on GitHub. (An earlier version of this entry said it was published to Hex; it has not been published to Hex yet.) 0.1.0 (below) was an internal milestone: it was never tagged, released or published, and it had the production-safety problems listed under "Fixed" (see the findings QK-01 to QK-11 in docs/SECURITY_REVIEW.md). If you pinned a pre-release commit from GitHub, read "Changed" before upgrading.

Fixed

  • mix queue_keeper.check no longer starts the host application (and therefore Oban, its queues and plugins); it loads config and starts only the repo (QK-01).
  • Queries that could take minutes on large tables: sample queries no longer ORDER BY id; :orphaned/:hanging aggregate in SQL; :stalled probes only late queues with index-bounded LIMIT 1 queries; sample queries capped at 100 per run (QK-02, QK-07).
  • Text output replaces control/bidi characters; Slack payloads escape &, < and > (QK-05).
  • sample_ids no longer render as a charlist (QK-08).

Added

  • QueueKeeperCheck.Guard: on Postgres every check runs in a rolled-back transaction with transaction_read_only, statement_timeout, lock_timeout and idle_in_transaction_session_timeout; on MySQL max_execution_time (QK-03).
  • Options :statement_timeout (5000), :lock_timeout (1000), :check_timeout (30000), :read_only (true); stalled: [lookback: 3600]; retry_storm: [include_completed: false].
  • report.errors, status :error and exit code 3; per-check error isolation; remaining checks are skipped after a connection error (QK-04).
  • Strict option validation, including an identifier allow-list for :prefix (QK-06).
  • SECURITY.md, docs/SECURITY_REVIEW.md, benchmark and verification scripts.
  • CI on PostgreSQL 17, SQLite and MySQL 8.4, with actions pinned to commit SHAs and mix hex.audit (QK-09).

Changed

  • :retry_storm counts completed retried jobs only with include_completed: true (that part needs a full table scan).
  • Release.check/2 never raises, starts the repo with a pool of 1 and stops it afterwards.
  • Running QueueKeeperCheck.run/2 inside an open transaction on Postgres is refused.
  • Errors (bad options, database unreachable, timeouts) now exit with 3 instead of 1, so "could not check" is no longer reported as "warning" (QK-04).
  • Unknown or invalid options raise ArgumentError instead of being ignored (QK-06).

Known limitations

  • :cron_missing (opt-in) needs a sequential scan; it is bounded by :statement_timeout (QK-10).
  • On MySQL and SQLite, read-only enforcement depends on a SELECT-only database user or a read-only connection; the library only issues SELECTs (QK-11).

0.1.0 - 2026-10-22 (never published)

Initial implementation. Not tagged, released or published; superseded by 0.2.0.

Added