From e5089e9fb08198bc15df1d8ffbace694dbd235aa Mon Sep 17 00:00:00 2001 From: smudge Date: Mon, 2 Feb 2026 14:34:54 -0500 Subject: [PATCH] test: Rework monitor coverage to avoid dups This is a test-only change that improves the way that query snapshotting is done for the monitor process. Previously, each metric was given its own example context, testing its queries in isolation. However, in practice, the monitor does not run this way, and it intentionally memoizes query results in a way that was not receiving sufficient test coverage! With this PR, monitor queries are dumped out into a single snapshot, delineated by a few text dividers for readability by humans (& better hinting for the git differ). /no-platform stack-info: PR: https://github.com/Betterment/delayed/pull/91, branch: smudge/stack/2 --- .../__snapshots__/monitor_spec.rb.snap | 1073 +++++++++-------- spec/delayed/monitor_spec.rb | 36 +- spec/helper.rb | 4 + 3 files changed, 572 insertions(+), 541 deletions(-) diff --git a/spec/delayed/__snapshots__/monitor_spec.rb.snap b/spec/delayed/__snapshots__/monitor_spec.rb.snap index 5ee5ff1f..63065bf1 100644 --- a/spec/delayed/__snapshots__/monitor_spec.rb.snap +++ b/spec/delayed/__snapshots__/monitor_spec.rb.snap @@ -1,4 +1,6 @@ -snapshots["runs the expected postgresql query for count 1"] = <<-SNAP +snapshots["runs the expected postgresql queries with the expected plans 1"] = <<-SNAP +-- QUERIES FOR `count`: +--------------------------------- SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 @@ -11,21 +13,7 @@ SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, \"queue\" -SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 - AND priority < 10 THEN 0 WHEN priority >= 10 - AND priority < 20 THEN 10 WHEN priority >= 20 - AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END AS case_when_priority_0_and_priority_10_then_0_when_priority_10_an, \"queue\" AS queue - FROM (SELECT priority, queue, COUNT(*) AS count - FROM \"delayed_jobs\" - WHERE \"delayed_jobs\".\"failed_at\" IS NULL - GROUP BY \"delayed_jobs\".\"priority\", \"delayed_jobs\".\"queue\") subquery - GROUP BY CASE WHEN priority >= 0 - AND priority < 10 THEN 0 WHEN priority >= 10 - AND priority < 20 THEN 10 WHEN priority >= 20 - AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, \"queue\" -SNAP -snapshots["produces the expected postgresql query plan for count 1"] = <<-SNAP GroupAggregate (cost=...) Output: sum(subquery.count), (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue Group Key: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue @@ -39,6 +27,20 @@ GroupAggregate (cost=...) Group Key: delayed_jobs.priority, delayed_jobs.queue -> Index Only Scan using idx_delayed_jobs_failed on public.delayed_jobs (cost=...) Output: delayed_jobs.priority, delayed_jobs.queue +--- +SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 + AND priority < 10 THEN 0 WHEN priority >= 10 + AND priority < 20 THEN 10 WHEN priority >= 20 + AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END AS case_when_priority_0_and_priority_10_then_0_when_priority_10_an, \"queue\" AS queue + FROM (SELECT priority, queue, COUNT(*) AS count + FROM \"delayed_jobs\" + WHERE \"delayed_jobs\".\"failed_at\" IS NULL + GROUP BY \"delayed_jobs\".\"priority\", \"delayed_jobs\".\"queue\") subquery + GROUP BY CASE WHEN priority >= 0 + AND priority < 10 THEN 0 WHEN priority >= 10 + AND priority < 20 THEN 10 WHEN priority >= 20 + AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, \"queue\" + GroupAggregate (cost=...) Output: sum(subquery.count), (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue Group Key: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue @@ -55,9 +57,23 @@ GroupAggregate (cost=...) Sort Key: delayed_jobs.priority, delayed_jobs.queue -> Index Only Scan using idx_delayed_jobs_live on public.delayed_jobs (cost=...) Output: delayed_jobs.priority, delayed_jobs.queue -SNAP +--- +-- QUERIES FOR `future_count`: +--------------------------------- +SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 + AND priority < 10 THEN 0 WHEN priority >= 10 + AND priority < 20 THEN 10 WHEN priority >= 20 + AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END AS case_when_priority_0_and_priority_10_then_0_when_priority_10_an, \"queue\" AS queue + FROM (SELECT priority, queue, COUNT(*) AS count + FROM \"delayed_jobs\" + WHERE \"delayed_jobs\".\"failed_at\" IS NULL + AND \"delayed_jobs\".\"run_at\" > '2025-11-10 17:20:13' + GROUP BY \"delayed_jobs\".\"priority\", \"delayed_jobs\".\"queue\") subquery + GROUP BY CASE WHEN priority >= 0 + AND priority < 10 THEN 0 WHEN priority >= 10 + AND priority < 20 THEN 10 WHEN priority >= 20 + AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, \"queue\" -snapshots["[legacy index] produces the expected postgresql query plan for count 1"] = <<-SNAP GroupAggregate (cost=...) Output: sum(subquery.count), (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue Group Key: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue @@ -72,9 +88,27 @@ GroupAggregate (cost=...) -> Sort (cost=...) Output: delayed_jobs.priority, delayed_jobs.queue Sort Key: delayed_jobs.priority, delayed_jobs.queue - -> Index Scan using delayed_jobs_priority on public.delayed_jobs (cost=...) + -> Index Only Scan using idx_delayed_jobs_live on public.delayed_jobs (cost=...) Output: delayed_jobs.priority, delayed_jobs.queue - Filter: (delayed_jobs.failed_at IS NOT NULL) + Index Cond: (delayed_jobs.run_at > '2025-11-10 17:20:13'::timestamp without time zone) +--- +-- QUERIES FOR `locked_count`: +--------------------------------- +SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 + AND priority < 10 THEN 0 WHEN priority >= 10 + AND priority < 20 THEN 10 WHEN priority >= 20 + AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END AS case_when_priority_0_and_priority_10_then_0_when_priority_10_an, \"queue\" AS queue + FROM (SELECT priority, queue, COUNT(*) AS count + FROM \"delayed_jobs\" + WHERE \"delayed_jobs\".\"locked_at\" >= '2025-11-10 16:59:43' + AND \"delayed_jobs\".\"failed_at\" IS NULL + AND \"delayed_jobs\".\"run_at\" <= '2025-11-10 17:20:13' + GROUP BY \"delayed_jobs\".\"priority\", \"delayed_jobs\".\"queue\") subquery + GROUP BY CASE WHEN priority >= 0 + AND priority < 10 THEN 0 WHEN priority >= 10 + AND priority < 20 THEN 10 WHEN priority >= 20 + AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, \"queue\" + GroupAggregate (cost=...) Output: sum(subquery.count), (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue Group Key: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue @@ -89,28 +123,27 @@ GroupAggregate (cost=...) -> Sort (cost=...) Output: delayed_jobs.priority, delayed_jobs.queue Sort Key: delayed_jobs.priority, delayed_jobs.queue - -> Index Scan using delayed_jobs_priority on public.delayed_jobs (cost=...) + -> Index Scan using idx_delayed_jobs_live on public.delayed_jobs (cost=...) Output: delayed_jobs.priority, delayed_jobs.queue - Filter: (delayed_jobs.failed_at IS NULL) -SNAP - -snapshots["runs the expected postgresql query for future_count 1"] = <<-SNAP + Index Cond: (delayed_jobs.run_at <= '2025-11-10 17:20:13'::timestamp without time zone) + Filter: (delayed_jobs.locked_at >= '2025-11-10 16:59:43'::timestamp without time zone) +--- +-- QUERIES FOR `erroring_count`: +--------------------------------- SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END AS case_when_priority_0_and_priority_10_then_0_when_priority_10_an, \"queue\" AS queue FROM (SELECT priority, queue, COUNT(*) AS count FROM \"delayed_jobs\" - WHERE \"delayed_jobs\".\"failed_at\" IS NULL - AND \"delayed_jobs\".\"run_at\" > '2025-11-10 17:20:13' + WHERE \"delayed_jobs\".\"attempts\" > 0 + AND \"delayed_jobs\".\"failed_at\" IS NULL GROUP BY \"delayed_jobs\".\"priority\", \"delayed_jobs\".\"queue\") subquery GROUP BY CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, \"queue\" -SNAP -snapshots["produces the expected postgresql query plan for future_count 1"] = <<-SNAP GroupAggregate (cost=...) Output: sum(subquery.count), (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue Group Key: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue @@ -127,38 +160,97 @@ GroupAggregate (cost=...) Sort Key: delayed_jobs.priority, delayed_jobs.queue -> Index Only Scan using idx_delayed_jobs_live on public.delayed_jobs (cost=...) Output: delayed_jobs.priority, delayed_jobs.queue - Index Cond: (delayed_jobs.run_at > '2025-11-10 17:20:13'::timestamp without time zone) -SNAP + Index Cond: (delayed_jobs.attempts > 0) +--- +-- QUERIES FOR `failed_count`: +--------------------------------- +-- (no new queries) +-- QUERIES FOR `max_lock_age`: +--------------------------------- +SELECT (CASE WHEN priority >= 0 + AND priority < 10 THEN 0 WHEN priority >= 10 + AND priority < 20 THEN 10 WHEN priority >= 20 + AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END) AS priority, queue, MIN(locked_at) AS locked_at, TIMEZONE('UTC', NOW()) AS db_now_utc + FROM (SELECT priority, queue, MIN(locked_at) AS locked_at + FROM \"delayed_jobs\" + WHERE \"delayed_jobs\".\"locked_at\" >= '2025-11-10 16:59:43' + AND \"delayed_jobs\".\"failed_at\" IS NULL + AND \"delayed_jobs\".\"run_at\" <= '2025-11-10 17:20:13' + GROUP BY \"delayed_jobs\".\"priority\", \"delayed_jobs\".\"queue\") subquery + GROUP BY CASE WHEN priority >= 0 + AND priority < 10 THEN 0 WHEN priority >= 10 + AND priority < 20 THEN 10 WHEN priority >= 20 + AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, \"queue\" -snapshots["[legacy index] produces the expected postgresql query plan for future_count 1"] = <<-SNAP GroupAggregate (cost=...) - Output: sum(subquery.count), (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue + Output: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue, min(subquery.locked_at), timezone('UTC'::text, now()) Group Key: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue -> Sort (cost=...) - Output: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue, subquery.count + Output: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue, subquery.locked_at Sort Key: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue -> Subquery Scan on subquery (cost=...) - Output: CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END, subquery.queue, subquery.count + Output: CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END, subquery.queue, subquery.locked_at -> GroupAggregate (cost=...) - Output: delayed_jobs.priority, delayed_jobs.queue, count(*) + Output: delayed_jobs.priority, delayed_jobs.queue, min(delayed_jobs.locked_at) Group Key: delayed_jobs.priority, delayed_jobs.queue -> Sort (cost=...) - Output: delayed_jobs.priority, delayed_jobs.queue + Output: delayed_jobs.priority, delayed_jobs.queue, delayed_jobs.locked_at Sort Key: delayed_jobs.priority, delayed_jobs.queue - -> Index Scan using delayed_jobs_priority on public.delayed_jobs (cost=...) - Output: delayed_jobs.priority, delayed_jobs.queue - Index Cond: (delayed_jobs.run_at > '2025-11-10 17:20:13'::timestamp without time zone) - Filter: (delayed_jobs.failed_at IS NULL) -SNAP + -> Index Scan using idx_delayed_jobs_live on public.delayed_jobs (cost=...) + Output: delayed_jobs.priority, delayed_jobs.queue, delayed_jobs.locked_at + Index Cond: (delayed_jobs.run_at <= '2025-11-10 17:20:13'::timestamp without time zone) + Filter: (delayed_jobs.locked_at >= '2025-11-10 16:59:43'::timestamp without time zone) +--- +-- QUERIES FOR `max_age`: +--------------------------------- +SELECT (CASE WHEN priority >= 0 + AND priority < 10 THEN 0 WHEN priority >= 10 + AND priority < 20 THEN 10 WHEN priority >= 20 + AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END) AS priority, queue, MIN(run_at) AS run_at, TIMEZONE('UTC', NOW()) AS db_now_utc + FROM (SELECT priority, queue, MIN(run_at) AS run_at + FROM \"delayed_jobs\" + WHERE (\"delayed_jobs\".\"locked_at\" IS NULL + OR \"delayed_jobs\".\"locked_at\" < '2025-11-10 16:59:43') + AND \"delayed_jobs\".\"failed_at\" IS NULL + AND \"delayed_jobs\".\"run_at\" <= '2025-11-10 17:20:13' + GROUP BY \"delayed_jobs\".\"priority\", \"delayed_jobs\".\"queue\") subquery + GROUP BY CASE WHEN priority >= 0 + AND priority < 10 THEN 0 WHEN priority >= 10 + AND priority < 20 THEN 10 WHEN priority >= 20 + AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, \"queue\" -snapshots["runs the expected postgresql query for locked_count 1"] = <<-SNAP +GroupAggregate (cost=...) + Output: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue, min(subquery.run_at), timezone('UTC'::text, now()) + Group Key: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue + -> Sort (cost=...) + Output: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue, subquery.run_at + Sort Key: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue + -> Subquery Scan on subquery (cost=...) + Output: CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END, subquery.queue, subquery.run_at + -> GroupAggregate (cost=...) + Output: delayed_jobs.priority, delayed_jobs.queue, min(delayed_jobs.run_at) + Group Key: delayed_jobs.priority, delayed_jobs.queue + -> Sort (cost=...) + Output: delayed_jobs.priority, delayed_jobs.queue, delayed_jobs.run_at + Sort Key: delayed_jobs.priority, delayed_jobs.queue + -> Index Scan using idx_delayed_jobs_live on public.delayed_jobs (cost=...) + Output: delayed_jobs.priority, delayed_jobs.queue, delayed_jobs.run_at + Index Cond: (delayed_jobs.run_at <= '2025-11-10 17:20:13'::timestamp without time zone) + Filter: ((delayed_jobs.locked_at IS NULL) OR (delayed_jobs.locked_at < '2025-11-10 16:59:43'::timestamp without time zone)) +--- +-- QUERIES FOR `working_count`: +--------------------------------- +-- (no new queries) +-- QUERIES FOR `workable_count`: +--------------------------------- SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END AS case_when_priority_0_and_priority_10_then_0_when_priority_10_an, \"queue\" AS queue FROM (SELECT priority, queue, COUNT(*) AS count FROM \"delayed_jobs\" - WHERE \"delayed_jobs\".\"locked_at\" >= '2025-11-10 16:59:43' + WHERE (\"delayed_jobs\".\"locked_at\" IS NULL + OR \"delayed_jobs\".\"locked_at\" < '2025-11-10 16:59:43') AND \"delayed_jobs\".\"failed_at\" IS NULL AND \"delayed_jobs\".\"run_at\" <= '2025-11-10 17:20:13' GROUP BY \"delayed_jobs\".\"priority\", \"delayed_jobs\".\"queue\") subquery @@ -166,9 +258,7 @@ SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, \"queue\" -SNAP -snapshots["produces the expected postgresql query plan for locked_count 1"] = <<-SNAP GroupAggregate (cost=...) Output: sum(subquery.count), (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue Group Key: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue @@ -186,10 +276,29 @@ GroupAggregate (cost=...) -> Index Scan using idx_delayed_jobs_live on public.delayed_jobs (cost=...) Output: delayed_jobs.priority, delayed_jobs.queue Index Cond: (delayed_jobs.run_at <= '2025-11-10 17:20:13'::timestamp without time zone) - Filter: (delayed_jobs.locked_at >= '2025-11-10 16:59:43'::timestamp without time zone) + Filter: ((delayed_jobs.locked_at IS NULL) OR (delayed_jobs.locked_at < '2025-11-10 16:59:43'::timestamp without time zone)) +--- +-- QUERIES FOR `alert_age_percent`: +--------------------------------- +-- (no new queries) SNAP -snapshots["[legacy index] produces the expected postgresql query plan for locked_count 1"] = <<-SNAP +snapshots["[legacy index] runs the expected postgresql queries with the expected plans 1"] = <<-SNAP +-- QUERIES FOR `count`: +--------------------------------- +SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 + AND priority < 10 THEN 0 WHEN priority >= 10 + AND priority < 20 THEN 10 WHEN priority >= 20 + AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END AS case_when_priority_0_and_priority_10_then_0_when_priority_10_an, \"queue\" AS queue + FROM (SELECT priority, queue, COUNT(*) AS count + FROM \"delayed_jobs\" + WHERE \"delayed_jobs\".\"failed_at\" IS NOT NULL + GROUP BY \"delayed_jobs\".\"priority\", \"delayed_jobs\".\"queue\") subquery + GROUP BY CASE WHEN priority >= 0 + AND priority < 10 THEN 0 WHEN priority >= 10 + AND priority < 20 THEN 10 WHEN priority >= 20 + AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, \"queue\" + GroupAggregate (cost=...) Output: sum(subquery.count), (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue Group Key: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue @@ -206,27 +315,21 @@ GroupAggregate (cost=...) Sort Key: delayed_jobs.priority, delayed_jobs.queue -> Index Scan using delayed_jobs_priority on public.delayed_jobs (cost=...) Output: delayed_jobs.priority, delayed_jobs.queue - Index Cond: (delayed_jobs.run_at <= '2025-11-10 17:20:13'::timestamp without time zone) - Filter: ((delayed_jobs.failed_at IS NULL) AND (delayed_jobs.locked_at >= '2025-11-10 16:59:43'::timestamp without time zone)) -SNAP - -snapshots["runs the expected postgresql query for erroring_count 1"] = <<-SNAP + Filter: (delayed_jobs.failed_at IS NOT NULL) +--- SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END AS case_when_priority_0_and_priority_10_then_0_when_priority_10_an, \"queue\" AS queue FROM (SELECT priority, queue, COUNT(*) AS count FROM \"delayed_jobs\" - WHERE \"delayed_jobs\".\"attempts\" > 0 - AND \"delayed_jobs\".\"failed_at\" IS NULL + WHERE \"delayed_jobs\".\"failed_at\" IS NULL GROUP BY \"delayed_jobs\".\"priority\", \"delayed_jobs\".\"queue\") subquery GROUP BY CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, \"queue\" -SNAP -snapshots["produces the expected postgresql query plan for erroring_count 1"] = <<-SNAP GroupAggregate (cost=...) Output: sum(subquery.count), (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue Group Key: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue @@ -241,12 +344,26 @@ GroupAggregate (cost=...) -> Sort (cost=...) Output: delayed_jobs.priority, delayed_jobs.queue Sort Key: delayed_jobs.priority, delayed_jobs.queue - -> Index Only Scan using idx_delayed_jobs_live on public.delayed_jobs (cost=...) + -> Index Scan using delayed_jobs_priority on public.delayed_jobs (cost=...) Output: delayed_jobs.priority, delayed_jobs.queue - Index Cond: (delayed_jobs.attempts > 0) -SNAP + Filter: (delayed_jobs.failed_at IS NULL) +--- +-- QUERIES FOR `future_count`: +--------------------------------- +SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 + AND priority < 10 THEN 0 WHEN priority >= 10 + AND priority < 20 THEN 10 WHEN priority >= 20 + AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END AS case_when_priority_0_and_priority_10_then_0_when_priority_10_an, \"queue\" AS queue + FROM (SELECT priority, queue, COUNT(*) AS count + FROM \"delayed_jobs\" + WHERE \"delayed_jobs\".\"failed_at\" IS NULL + AND \"delayed_jobs\".\"run_at\" > '2025-11-10 17:20:13' + GROUP BY \"delayed_jobs\".\"priority\", \"delayed_jobs\".\"queue\") subquery + GROUP BY CASE WHEN priority >= 0 + AND priority < 10 THEN 0 WHEN priority >= 10 + AND priority < 20 THEN 10 WHEN priority >= 20 + AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, \"queue\" -snapshots["[legacy index] produces the expected postgresql query plan for erroring_count 1"] = <<-SNAP GroupAggregate (cost=...) Output: sum(subquery.count), (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue Group Key: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue @@ -263,25 +380,26 @@ GroupAggregate (cost=...) Sort Key: delayed_jobs.priority, delayed_jobs.queue -> Index Scan using delayed_jobs_priority on public.delayed_jobs (cost=...) Output: delayed_jobs.priority, delayed_jobs.queue - Filter: ((delayed_jobs.failed_at IS NULL) AND (delayed_jobs.attempts > 0)) -SNAP - -snapshots["runs the expected postgresql query for failed_count 1"] = <<-SNAP + Index Cond: (delayed_jobs.run_at > '2025-11-10 17:20:13'::timestamp without time zone) + Filter: (delayed_jobs.failed_at IS NULL) +--- +-- QUERIES FOR `locked_count`: +--------------------------------- SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END AS case_when_priority_0_and_priority_10_then_0_when_priority_10_an, \"queue\" AS queue FROM (SELECT priority, queue, COUNT(*) AS count FROM \"delayed_jobs\" - WHERE \"delayed_jobs\".\"failed_at\" IS NOT NULL + WHERE \"delayed_jobs\".\"locked_at\" >= '2025-11-10 16:59:43' + AND \"delayed_jobs\".\"failed_at\" IS NULL + AND \"delayed_jobs\".\"run_at\" <= '2025-11-10 17:20:13' GROUP BY \"delayed_jobs\".\"priority\", \"delayed_jobs\".\"queue\") subquery GROUP BY CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, \"queue\" -SNAP -snapshots["produces the expected postgresql query plan for failed_count 1"] = <<-SNAP GroupAggregate (cost=...) Output: sum(subquery.count), (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue Group Key: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue @@ -293,11 +411,30 @@ GroupAggregate (cost=...) -> GroupAggregate (cost=...) Output: delayed_jobs.priority, delayed_jobs.queue, count(*) Group Key: delayed_jobs.priority, delayed_jobs.queue - -> Index Only Scan using idx_delayed_jobs_failed on public.delayed_jobs (cost=...) + -> Sort (cost=...) Output: delayed_jobs.priority, delayed_jobs.queue -SNAP + Sort Key: delayed_jobs.priority, delayed_jobs.queue + -> Index Scan using delayed_jobs_priority on public.delayed_jobs (cost=...) + Output: delayed_jobs.priority, delayed_jobs.queue + Index Cond: (delayed_jobs.run_at <= '2025-11-10 17:20:13'::timestamp without time zone) + Filter: ((delayed_jobs.failed_at IS NULL) AND (delayed_jobs.locked_at >= '2025-11-10 16:59:43'::timestamp without time zone)) +--- +-- QUERIES FOR `erroring_count`: +--------------------------------- +SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 + AND priority < 10 THEN 0 WHEN priority >= 10 + AND priority < 20 THEN 10 WHEN priority >= 20 + AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END AS case_when_priority_0_and_priority_10_then_0_when_priority_10_an, \"queue\" AS queue + FROM (SELECT priority, queue, COUNT(*) AS count + FROM \"delayed_jobs\" + WHERE \"delayed_jobs\".\"attempts\" > 0 + AND \"delayed_jobs\".\"failed_at\" IS NULL + GROUP BY \"delayed_jobs\".\"priority\", \"delayed_jobs\".\"queue\") subquery + GROUP BY CASE WHEN priority >= 0 + AND priority < 10 THEN 0 WHEN priority >= 10 + AND priority < 20 THEN 10 WHEN priority >= 20 + AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, \"queue\" -snapshots["[legacy index] produces the expected postgresql query plan for failed_count 1"] = <<-SNAP GroupAggregate (cost=...) Output: sum(subquery.count), (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue Group Key: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue @@ -314,10 +451,13 @@ GroupAggregate (cost=...) Sort Key: delayed_jobs.priority, delayed_jobs.queue -> Index Scan using delayed_jobs_priority on public.delayed_jobs (cost=...) Output: delayed_jobs.priority, delayed_jobs.queue - Filter: (delayed_jobs.failed_at IS NOT NULL) -SNAP - -snapshots["runs the expected postgresql query for max_lock_age 1"] = <<-SNAP + Filter: ((delayed_jobs.failed_at IS NULL) AND (delayed_jobs.attempts > 0)) +--- +-- QUERIES FOR `failed_count`: +--------------------------------- +-- (no new queries) +-- QUERIES FOR `max_lock_age`: +--------------------------------- SELECT (CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 @@ -332,30 +472,7 @@ SELECT (CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, \"queue\" -SNAP - -snapshots["produces the expected postgresql query plan for max_lock_age 1"] = <<-SNAP -GroupAggregate (cost=...) - Output: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue, min(subquery.locked_at), timezone('UTC'::text, now()) - Group Key: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue - -> Sort (cost=...) - Output: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue, subquery.locked_at - Sort Key: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue - -> Subquery Scan on subquery (cost=...) - Output: CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END, subquery.queue, subquery.locked_at - -> GroupAggregate (cost=...) - Output: delayed_jobs.priority, delayed_jobs.queue, min(delayed_jobs.locked_at) - Group Key: delayed_jobs.priority, delayed_jobs.queue - -> Sort (cost=...) - Output: delayed_jobs.priority, delayed_jobs.queue, delayed_jobs.locked_at - Sort Key: delayed_jobs.priority, delayed_jobs.queue - -> Index Scan using idx_delayed_jobs_live on public.delayed_jobs (cost=...) - Output: delayed_jobs.priority, delayed_jobs.queue, delayed_jobs.locked_at - Index Cond: (delayed_jobs.run_at <= '2025-11-10 17:20:13'::timestamp without time zone) - Filter: (delayed_jobs.locked_at >= '2025-11-10 16:59:43'::timestamp without time zone) -SNAP -snapshots["[legacy index] produces the expected postgresql query plan for max_lock_age 1"] = <<-SNAP GroupAggregate (cost=...) Output: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue, min(subquery.locked_at), timezone('UTC'::text, now()) Group Key: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue @@ -374,9 +491,9 @@ GroupAggregate (cost=...) Output: delayed_jobs.priority, delayed_jobs.queue, delayed_jobs.locked_at Index Cond: (delayed_jobs.run_at <= '2025-11-10 17:20:13'::timestamp without time zone) Filter: ((delayed_jobs.failed_at IS NULL) AND (delayed_jobs.locked_at >= '2025-11-10 16:59:43'::timestamp without time zone)) -SNAP - -snapshots["runs the expected postgresql query for max_age 1"] = <<-SNAP +--- +-- QUERIES FOR `max_age`: +--------------------------------- SELECT (CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 @@ -392,9 +509,7 @@ SELECT (CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, \"queue\" -SNAP -snapshots["produces the expected postgresql query plan for max_age 1"] = <<-SNAP GroupAggregate (cost=...) Output: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue, min(subquery.run_at), timezone('UTC'::text, now()) Group Key: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue @@ -409,41 +524,24 @@ GroupAggregate (cost=...) -> Sort (cost=...) Output: delayed_jobs.priority, delayed_jobs.queue, delayed_jobs.run_at Sort Key: delayed_jobs.priority, delayed_jobs.queue - -> Index Scan using idx_delayed_jobs_live on public.delayed_jobs (cost=...) - Output: delayed_jobs.priority, delayed_jobs.queue, delayed_jobs.run_at - Index Cond: (delayed_jobs.run_at <= '2025-11-10 17:20:13'::timestamp without time zone) - Filter: ((delayed_jobs.locked_at IS NULL) OR (delayed_jobs.locked_at < '2025-11-10 16:59:43'::timestamp without time zone)) -SNAP - -snapshots["[legacy index] produces the expected postgresql query plan for max_age 1"] = <<-SNAP -GroupAggregate (cost=...) - Output: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue, min(subquery.run_at), timezone('UTC'::text, now()) - Group Key: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue - -> Sort (cost=...) - Output: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue, subquery.run_at - Sort Key: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue - -> Subquery Scan on subquery (cost=...) - Output: CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END, subquery.queue, subquery.run_at - -> GroupAggregate (cost=...) - Output: delayed_jobs.priority, delayed_jobs.queue, min(delayed_jobs.run_at) - Group Key: delayed_jobs.priority, delayed_jobs.queue - -> Sort (cost=...) - Output: delayed_jobs.priority, delayed_jobs.queue, delayed_jobs.run_at - Sort Key: delayed_jobs.priority, delayed_jobs.queue - -> Index Scan using delayed_jobs_priority on public.delayed_jobs (cost=...) + -> Index Scan using delayed_jobs_priority on public.delayed_jobs (cost=...) Output: delayed_jobs.priority, delayed_jobs.queue, delayed_jobs.run_at Index Cond: (delayed_jobs.run_at <= '2025-11-10 17:20:13'::timestamp without time zone) Filter: ((delayed_jobs.failed_at IS NULL) AND ((delayed_jobs.locked_at IS NULL) OR (delayed_jobs.locked_at < '2025-11-10 16:59:43'::timestamp without time zone))) -SNAP - -snapshots["runs the expected postgresql query for working_count 1"] = <<-SNAP +--- +-- QUERIES FOR `working_count`: +--------------------------------- +-- (no new queries) +-- QUERIES FOR `workable_count`: +--------------------------------- SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END AS case_when_priority_0_and_priority_10_then_0_when_priority_10_an, \"queue\" AS queue FROM (SELECT priority, queue, COUNT(*) AS count FROM \"delayed_jobs\" - WHERE \"delayed_jobs\".\"locked_at\" >= '2025-11-10 16:59:43' + WHERE (\"delayed_jobs\".\"locked_at\" IS NULL + OR \"delayed_jobs\".\"locked_at\" < '2025-11-10 16:59:43') AND \"delayed_jobs\".\"failed_at\" IS NULL AND \"delayed_jobs\".\"run_at\" <= '2025-11-10 17:20:13' GROUP BY \"delayed_jobs\".\"priority\", \"delayed_jobs\".\"queue\") subquery @@ -451,30 +549,7 @@ SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, \"queue\" -SNAP -snapshots["produces the expected postgresql query plan for working_count 1"] = <<-SNAP -GroupAggregate (cost=...) - Output: sum(subquery.count), (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue - Group Key: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue - -> Sort (cost=...) - Output: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue, subquery.count - Sort Key: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue - -> Subquery Scan on subquery (cost=...) - Output: CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END, subquery.queue, subquery.count - -> GroupAggregate (cost=...) - Output: delayed_jobs.priority, delayed_jobs.queue, count(*) - Group Key: delayed_jobs.priority, delayed_jobs.queue - -> Sort (cost=...) - Output: delayed_jobs.priority, delayed_jobs.queue - Sort Key: delayed_jobs.priority, delayed_jobs.queue - -> Index Scan using idx_delayed_jobs_live on public.delayed_jobs (cost=...) - Output: delayed_jobs.priority, delayed_jobs.queue - Index Cond: (delayed_jobs.run_at <= '2025-11-10 17:20:13'::timestamp without time zone) - Filter: (delayed_jobs.locked_at >= '2025-11-10 16:59:43'::timestamp without time zone) -SNAP - -snapshots["[legacy index] produces the expected postgresql query plan for working_count 1"] = <<-SNAP GroupAggregate (cost=...) Output: sum(subquery.count), (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue Group Key: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue @@ -492,219 +567,130 @@ GroupAggregate (cost=...) -> Index Scan using delayed_jobs_priority on public.delayed_jobs (cost=...) Output: delayed_jobs.priority, delayed_jobs.queue Index Cond: (delayed_jobs.run_at <= '2025-11-10 17:20:13'::timestamp without time zone) - Filter: ((delayed_jobs.failed_at IS NULL) AND (delayed_jobs.locked_at >= '2025-11-10 16:59:43'::timestamp without time zone)) + Filter: ((delayed_jobs.failed_at IS NULL) AND ((delayed_jobs.locked_at IS NULL) OR (delayed_jobs.locked_at < '2025-11-10 16:59:43'::timestamp without time zone))) +--- +-- QUERIES FOR `alert_age_percent`: +--------------------------------- +-- (no new queries) SNAP -snapshots["runs the expected postgresql query for workable_count 1"] = <<-SNAP +snapshots["runs the expected sqlite3 queries with the expected plans 1"] = <<-SNAP +-- QUERIES FOR `count`: +--------------------------------- SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END AS case_when_priority_0_and_priority_10_then_0_when_priority_10_an, \"queue\" AS queue FROM (SELECT priority, queue, COUNT(*) AS count FROM \"delayed_jobs\" - WHERE (\"delayed_jobs\".\"locked_at\" IS NULL - OR \"delayed_jobs\".\"locked_at\" < '2025-11-10 16:59:43') - AND \"delayed_jobs\".\"failed_at\" IS NULL - AND \"delayed_jobs\".\"run_at\" <= '2025-11-10 17:20:13' + WHERE \"delayed_jobs\".\"failed_at\" IS NOT NULL GROUP BY \"delayed_jobs\".\"priority\", \"delayed_jobs\".\"queue\") subquery GROUP BY CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, \"queue\" -SNAP -snapshots["produces the expected postgresql query plan for workable_count 1"] = <<-SNAP -GroupAggregate (cost=...) - Output: sum(subquery.count), (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue - Group Key: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue - -> Sort (cost=...) - Output: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue, subquery.count - Sort Key: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue - -> Subquery Scan on subquery (cost=...) - Output: CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END, subquery.queue, subquery.count - -> GroupAggregate (cost=...) - Output: delayed_jobs.priority, delayed_jobs.queue, count(*) - Group Key: delayed_jobs.priority, delayed_jobs.queue - -> Sort (cost=...) - Output: delayed_jobs.priority, delayed_jobs.queue - Sort Key: delayed_jobs.priority, delayed_jobs.queue - -> Index Scan using idx_delayed_jobs_live on public.delayed_jobs (cost=...) - Output: delayed_jobs.priority, delayed_jobs.queue - Index Cond: (delayed_jobs.run_at <= '2025-11-10 17:20:13'::timestamp without time zone) - Filter: ((delayed_jobs.locked_at IS NULL) OR (delayed_jobs.locked_at < '2025-11-10 16:59:43'::timestamp without time zone)) -SNAP - -snapshots["[legacy index] produces the expected postgresql query plan for workable_count 1"] = <<-SNAP -GroupAggregate (cost=...) - Output: sum(subquery.count), (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue - Group Key: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue - -> Sort (cost=...) - Output: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue, subquery.count - Sort Key: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue - -> Subquery Scan on subquery (cost=...) - Output: CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END, subquery.queue, subquery.count - -> GroupAggregate (cost=...) - Output: delayed_jobs.priority, delayed_jobs.queue, count(*) - Group Key: delayed_jobs.priority, delayed_jobs.queue - -> Sort (cost=...) - Output: delayed_jobs.priority, delayed_jobs.queue - Sort Key: delayed_jobs.priority, delayed_jobs.queue - -> Index Scan using delayed_jobs_priority on public.delayed_jobs (cost=...) - Output: delayed_jobs.priority, delayed_jobs.queue - Index Cond: (delayed_jobs.run_at <= '2025-11-10 17:20:13'::timestamp without time zone) - Filter: ((delayed_jobs.failed_at IS NULL) AND ((delayed_jobs.locked_at IS NULL) OR (delayed_jobs.locked_at < '2025-11-10 16:59:43'::timestamp without time zone))) -SNAP - -snapshots["runs the expected postgresql query for alert_age_percent 1"] = <<-SNAP -SELECT (CASE WHEN priority >= 0 +CO-ROUTINE subquery +SCAN delayed_jobs USING INDEX idx_delayed_jobs_failed +SCAN subquery +USE TEMP B-TREE FOR GROUP BY +--- +SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 - AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END) AS priority, queue, MIN(run_at) AS run_at, TIMEZONE('UTC', NOW()) AS db_now_utc - FROM (SELECT priority, queue, MIN(run_at) AS run_at + AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END AS case_when_priority_0_and_priority_10_then_0_when_priority_10_an, \"queue\" AS queue + FROM (SELECT priority, queue, COUNT(*) AS count FROM \"delayed_jobs\" - WHERE (\"delayed_jobs\".\"locked_at\" IS NULL - OR \"delayed_jobs\".\"locked_at\" < '2025-11-10 16:59:43') - AND \"delayed_jobs\".\"failed_at\" IS NULL - AND \"delayed_jobs\".\"run_at\" <= '2025-11-10 17:20:13' + WHERE \"delayed_jobs\".\"failed_at\" IS NULL GROUP BY \"delayed_jobs\".\"priority\", \"delayed_jobs\".\"queue\") subquery GROUP BY CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, \"queue\" -SNAP - -snapshots["produces the expected postgresql query plan for alert_age_percent 1"] = <<-SNAP -GroupAggregate (cost=...) - Output: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue, min(subquery.run_at), timezone('UTC'::text, now()) - Group Key: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue - -> Sort (cost=...) - Output: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue, subquery.run_at - Sort Key: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue - -> Subquery Scan on subquery (cost=...) - Output: CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END, subquery.queue, subquery.run_at - -> GroupAggregate (cost=...) - Output: delayed_jobs.priority, delayed_jobs.queue, min(delayed_jobs.run_at) - Group Key: delayed_jobs.priority, delayed_jobs.queue - -> Sort (cost=...) - Output: delayed_jobs.priority, delayed_jobs.queue, delayed_jobs.run_at - Sort Key: delayed_jobs.priority, delayed_jobs.queue - -> Index Scan using idx_delayed_jobs_live on public.delayed_jobs (cost=...) - Output: delayed_jobs.priority, delayed_jobs.queue, delayed_jobs.run_at - Index Cond: (delayed_jobs.run_at <= '2025-11-10 17:20:13'::timestamp without time zone) - Filter: ((delayed_jobs.locked_at IS NULL) OR (delayed_jobs.locked_at < '2025-11-10 16:59:43'::timestamp without time zone)) -SNAP - -snapshots["[legacy index] produces the expected postgresql query plan for alert_age_percent 1"] = <<-SNAP -GroupAggregate (cost=...) - Output: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue, min(subquery.run_at), timezone('UTC'::text, now()) - Group Key: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue - -> Sort (cost=...) - Output: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue, subquery.run_at - Sort Key: (CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue - -> Subquery Scan on subquery (cost=...) - Output: CASE WHEN ((subquery.priority >= 0) AND (subquery.priority < 10)) THEN 0 WHEN ((subquery.priority >= 10) AND (subquery.priority < 20)) THEN 10 WHEN ((subquery.priority >= 20) AND (subquery.priority < 30)) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END, subquery.queue, subquery.run_at - -> GroupAggregate (cost=...) - Output: delayed_jobs.priority, delayed_jobs.queue, min(delayed_jobs.run_at) - Group Key: delayed_jobs.priority, delayed_jobs.queue - -> Sort (cost=...) - Output: delayed_jobs.priority, delayed_jobs.queue, delayed_jobs.run_at - Sort Key: delayed_jobs.priority, delayed_jobs.queue - -> Index Scan using delayed_jobs_priority on public.delayed_jobs (cost=...) - Output: delayed_jobs.priority, delayed_jobs.queue, delayed_jobs.run_at - Index Cond: (delayed_jobs.run_at <= '2025-11-10 17:20:13'::timestamp without time zone) - Filter: ((delayed_jobs.failed_at IS NULL) AND ((delayed_jobs.locked_at IS NULL) OR (delayed_jobs.locked_at < '2025-11-10 16:59:43'::timestamp without time zone))) -SNAP -snapshots["runs the expected sqlite3 query for count 1"] = <<-SNAP +CO-ROUTINE subquery +SCAN delayed_jobs USING INDEX idx_delayed_jobs_live +USE TEMP B-TREE FOR GROUP BY +SCAN subquery +USE TEMP B-TREE FOR GROUP BY +--- +-- QUERIES FOR `future_count`: +--------------------------------- SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END AS case_when_priority_0_and_priority_10_then_0_when_priority_10_an, \"queue\" AS queue FROM (SELECT priority, queue, COUNT(*) AS count FROM \"delayed_jobs\" - WHERE \"delayed_jobs\".\"failed_at\" IS NOT NULL + WHERE \"delayed_jobs\".\"failed_at\" IS NULL + AND \"delayed_jobs\".\"run_at\" > '2025-11-10 17:20:13' GROUP BY \"delayed_jobs\".\"priority\", \"delayed_jobs\".\"queue\") subquery GROUP BY CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, \"queue\" + +CO-ROUTINE subquery +SCAN delayed_jobs USING INDEX idx_delayed_jobs_live +USE TEMP B-TREE FOR GROUP BY +SCAN subquery +USE TEMP B-TREE FOR GROUP BY +--- +-- QUERIES FOR `locked_count`: +--------------------------------- SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END AS case_when_priority_0_and_priority_10_then_0_when_priority_10_an, \"queue\" AS queue FROM (SELECT priority, queue, COUNT(*) AS count FROM \"delayed_jobs\" - WHERE \"delayed_jobs\".\"failed_at\" IS NULL + WHERE \"delayed_jobs\".\"locked_at\" >= '2025-11-10 16:59:43' + AND \"delayed_jobs\".\"failed_at\" IS NULL + AND \"delayed_jobs\".\"run_at\" <= '2025-11-10 17:20:13' GROUP BY \"delayed_jobs\".\"priority\", \"delayed_jobs\".\"queue\") subquery GROUP BY CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, \"queue\" -SNAP -snapshots["produces the expected sqlite3 query plan for count 1"] = <<-SNAP -CO-ROUTINE subquery -SCAN delayed_jobs USING INDEX idx_delayed_jobs_failed -SCAN subquery -USE TEMP B-TREE FOR GROUP BY CO-ROUTINE subquery SCAN delayed_jobs USING INDEX idx_delayed_jobs_live USE TEMP B-TREE FOR GROUP BY SCAN subquery USE TEMP B-TREE FOR GROUP BY -SNAP - -snapshots["[legacy index] produces the expected sqlite3 query plan for count 1"] = <<-SNAP -CO-ROUTINE subquery -SCAN delayed_jobs USING INDEX delayed_jobs_priority -USE TEMP B-TREE FOR GROUP BY -SCAN subquery -USE TEMP B-TREE FOR GROUP BY -CO-ROUTINE subquery -SCAN delayed_jobs USING INDEX delayed_jobs_priority -USE TEMP B-TREE FOR GROUP BY -SCAN subquery -USE TEMP B-TREE FOR GROUP BY -SNAP - -snapshots["runs the expected sqlite3 query for future_count 1"] = <<-SNAP +--- +-- QUERIES FOR `erroring_count`: +--------------------------------- SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END AS case_when_priority_0_and_priority_10_then_0_when_priority_10_an, \"queue\" AS queue FROM (SELECT priority, queue, COUNT(*) AS count FROM \"delayed_jobs\" - WHERE \"delayed_jobs\".\"failed_at\" IS NULL - AND \"delayed_jobs\".\"run_at\" > '2025-11-10 17:20:13' + WHERE \"delayed_jobs\".\"attempts\" > 0 + AND \"delayed_jobs\".\"failed_at\" IS NULL GROUP BY \"delayed_jobs\".\"priority\", \"delayed_jobs\".\"queue\") subquery GROUP BY CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, \"queue\" -SNAP -snapshots["produces the expected sqlite3 query plan for future_count 1"] = <<-SNAP CO-ROUTINE subquery SCAN delayed_jobs USING INDEX idx_delayed_jobs_live USE TEMP B-TREE FOR GROUP BY SCAN subquery USE TEMP B-TREE FOR GROUP BY -SNAP - -snapshots["[legacy index] produces the expected sqlite3 query plan for future_count 1"] = <<-SNAP -CO-ROUTINE subquery -SCAN delayed_jobs USING INDEX delayed_jobs_priority -USE TEMP B-TREE FOR GROUP BY -SCAN subquery -USE TEMP B-TREE FOR GROUP BY -SNAP - -snapshots["runs the expected sqlite3 query for locked_count 1"] = <<-SNAP -SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 +--- +-- QUERIES FOR `failed_count`: +--------------------------------- +-- (no new queries) +-- QUERIES FOR `max_lock_age`: +--------------------------------- +SELECT (CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 - AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END AS case_when_priority_0_and_priority_10_then_0_when_priority_10_an, \"queue\" AS queue - FROM (SELECT priority, queue, COUNT(*) AS count + AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END) AS priority, queue, MIN(locked_at) AS locked_at, CURRENT_TIMESTAMP AS db_now_utc + FROM (SELECT priority, queue, MIN(locked_at) AS locked_at FROM \"delayed_jobs\" WHERE \"delayed_jobs\".\"locked_at\" >= '2025-11-10 16:59:43' AND \"delayed_jobs\".\"failed_at\" IS NULL @@ -714,57 +700,72 @@ SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, \"queue\" -SNAP -snapshots["produces the expected sqlite3 query plan for locked_count 1"] = <<-SNAP CO-ROUTINE subquery SCAN delayed_jobs USING INDEX idx_delayed_jobs_live USE TEMP B-TREE FOR GROUP BY SCAN subquery USE TEMP B-TREE FOR GROUP BY -SNAP +--- +-- QUERIES FOR `max_age`: +--------------------------------- +SELECT (CASE WHEN priority >= 0 + AND priority < 10 THEN 0 WHEN priority >= 10 + AND priority < 20 THEN 10 WHEN priority >= 20 + AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END) AS priority, queue, MIN(run_at) AS run_at, CURRENT_TIMESTAMP AS db_now_utc + FROM (SELECT priority, queue, MIN(run_at) AS run_at + FROM \"delayed_jobs\" + WHERE (\"delayed_jobs\".\"locked_at\" IS NULL + OR \"delayed_jobs\".\"locked_at\" < '2025-11-10 16:59:43') + AND \"delayed_jobs\".\"failed_at\" IS NULL + AND \"delayed_jobs\".\"run_at\" <= '2025-11-10 17:20:13' + GROUP BY \"delayed_jobs\".\"priority\", \"delayed_jobs\".\"queue\") subquery + GROUP BY CASE WHEN priority >= 0 + AND priority < 10 THEN 0 WHEN priority >= 10 + AND priority < 20 THEN 10 WHEN priority >= 20 + AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, \"queue\" -snapshots["[legacy index] produces the expected sqlite3 query plan for locked_count 1"] = <<-SNAP CO-ROUTINE subquery -SCAN delayed_jobs USING INDEX delayed_jobs_priority +SCAN delayed_jobs USING INDEX idx_delayed_jobs_live USE TEMP B-TREE FOR GROUP BY SCAN subquery USE TEMP B-TREE FOR GROUP BY -SNAP - -snapshots["runs the expected sqlite3 query for erroring_count 1"] = <<-SNAP +--- +-- QUERIES FOR `working_count`: +--------------------------------- +-- (no new queries) +-- QUERIES FOR `workable_count`: +--------------------------------- SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END AS case_when_priority_0_and_priority_10_then_0_when_priority_10_an, \"queue\" AS queue FROM (SELECT priority, queue, COUNT(*) AS count FROM \"delayed_jobs\" - WHERE \"delayed_jobs\".\"attempts\" > 0 + WHERE (\"delayed_jobs\".\"locked_at\" IS NULL + OR \"delayed_jobs\".\"locked_at\" < '2025-11-10 16:59:43') AND \"delayed_jobs\".\"failed_at\" IS NULL + AND \"delayed_jobs\".\"run_at\" <= '2025-11-10 17:20:13' GROUP BY \"delayed_jobs\".\"priority\", \"delayed_jobs\".\"queue\") subquery GROUP BY CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, \"queue\" -SNAP -snapshots["produces the expected sqlite3 query plan for erroring_count 1"] = <<-SNAP CO-ROUTINE subquery SCAN delayed_jobs USING INDEX idx_delayed_jobs_live USE TEMP B-TREE FOR GROUP BY SCAN subquery USE TEMP B-TREE FOR GROUP BY +--- +-- QUERIES FOR `alert_age_percent`: +--------------------------------- +-- (no new queries) SNAP -snapshots["[legacy index] produces the expected sqlite3 query plan for erroring_count 1"] = <<-SNAP -CO-ROUTINE subquery -SCAN delayed_jobs USING INDEX delayed_jobs_priority -USE TEMP B-TREE FOR GROUP BY -SCAN subquery -USE TEMP B-TREE FOR GROUP BY -SNAP - -snapshots["runs the expected sqlite3 query for failed_count 1"] = <<-SNAP +snapshots["[legacy index] runs the expected sqlite3 queries with the expected plans 1"] = <<-SNAP +-- QUERIES FOR `count`: +--------------------------------- SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 @@ -777,91 +778,56 @@ SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, \"queue\" -SNAP - -snapshots["produces the expected sqlite3 query plan for failed_count 1"] = <<-SNAP -CO-ROUTINE subquery -SCAN delayed_jobs USING INDEX idx_delayed_jobs_failed -SCAN subquery -USE TEMP B-TREE FOR GROUP BY -SNAP -snapshots["[legacy index] produces the expected sqlite3 query plan for failed_count 1"] = <<-SNAP CO-ROUTINE subquery SCAN delayed_jobs USING INDEX delayed_jobs_priority USE TEMP B-TREE FOR GROUP BY SCAN subquery USE TEMP B-TREE FOR GROUP BY -SNAP - -snapshots["runs the expected sqlite3 query for max_lock_age 1"] = <<-SNAP -SELECT (CASE WHEN priority >= 0 +--- +SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 - AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END) AS priority, queue, MIN(locked_at) AS locked_at, CURRENT_TIMESTAMP AS db_now_utc - FROM (SELECT priority, queue, MIN(locked_at) AS locked_at + AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END AS case_when_priority_0_and_priority_10_then_0_when_priority_10_an, \"queue\" AS queue + FROM (SELECT priority, queue, COUNT(*) AS count FROM \"delayed_jobs\" - WHERE \"delayed_jobs\".\"locked_at\" >= '2025-11-10 16:59:43' - AND \"delayed_jobs\".\"failed_at\" IS NULL - AND \"delayed_jobs\".\"run_at\" <= '2025-11-10 17:20:13' + WHERE \"delayed_jobs\".\"failed_at\" IS NULL GROUP BY \"delayed_jobs\".\"priority\", \"delayed_jobs\".\"queue\") subquery GROUP BY CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, \"queue\" -SNAP - -snapshots["produces the expected sqlite3 query plan for max_lock_age 1"] = <<-SNAP -CO-ROUTINE subquery -SCAN delayed_jobs USING INDEX idx_delayed_jobs_live -USE TEMP B-TREE FOR GROUP BY -SCAN subquery -USE TEMP B-TREE FOR GROUP BY -SNAP -snapshots["[legacy index] produces the expected sqlite3 query plan for max_lock_age 1"] = <<-SNAP CO-ROUTINE subquery SCAN delayed_jobs USING INDEX delayed_jobs_priority USE TEMP B-TREE FOR GROUP BY SCAN subquery USE TEMP B-TREE FOR GROUP BY -SNAP - -snapshots["runs the expected sqlite3 query for max_age 1"] = <<-SNAP -SELECT (CASE WHEN priority >= 0 +--- +-- QUERIES FOR `future_count`: +--------------------------------- +SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 - AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END) AS priority, queue, MIN(run_at) AS run_at, CURRENT_TIMESTAMP AS db_now_utc - FROM (SELECT priority, queue, MIN(run_at) AS run_at + AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END AS case_when_priority_0_and_priority_10_then_0_when_priority_10_an, \"queue\" AS queue + FROM (SELECT priority, queue, COUNT(*) AS count FROM \"delayed_jobs\" - WHERE (\"delayed_jobs\".\"locked_at\" IS NULL - OR \"delayed_jobs\".\"locked_at\" < '2025-11-10 16:59:43') - AND \"delayed_jobs\".\"failed_at\" IS NULL - AND \"delayed_jobs\".\"run_at\" <= '2025-11-10 17:20:13' + WHERE \"delayed_jobs\".\"failed_at\" IS NULL + AND \"delayed_jobs\".\"run_at\" > '2025-11-10 17:20:13' GROUP BY \"delayed_jobs\".\"priority\", \"delayed_jobs\".\"queue\") subquery GROUP BY CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 - AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, \"queue\" -SNAP - -snapshots["produces the expected sqlite3 query plan for max_age 1"] = <<-SNAP -CO-ROUTINE subquery -SCAN delayed_jobs USING INDEX idx_delayed_jobs_live -USE TEMP B-TREE FOR GROUP BY -SCAN subquery -USE TEMP B-TREE FOR GROUP BY -SNAP + AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, \"queue\" -snapshots["[legacy index] produces the expected sqlite3 query plan for max_age 1"] = <<-SNAP CO-ROUTINE subquery SCAN delayed_jobs USING INDEX delayed_jobs_priority USE TEMP B-TREE FOR GROUP BY SCAN subquery USE TEMP B-TREE FOR GROUP BY -SNAP - -snapshots["runs the expected sqlite3 query for working_count 1"] = <<-SNAP +--- +-- QUERIES FOR `locked_count`: +--------------------------------- SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 @@ -876,59 +842,63 @@ SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, \"queue\" -SNAP - -snapshots["produces the expected sqlite3 query plan for working_count 1"] = <<-SNAP -CO-ROUTINE subquery -SCAN delayed_jobs USING INDEX idx_delayed_jobs_live -USE TEMP B-TREE FOR GROUP BY -SCAN subquery -USE TEMP B-TREE FOR GROUP BY -SNAP -snapshots["[legacy index] produces the expected sqlite3 query plan for working_count 1"] = <<-SNAP CO-ROUTINE subquery SCAN delayed_jobs USING INDEX delayed_jobs_priority USE TEMP B-TREE FOR GROUP BY SCAN subquery USE TEMP B-TREE FOR GROUP BY -SNAP - -snapshots["runs the expected sqlite3 query for workable_count 1"] = <<-SNAP +--- +-- QUERIES FOR `erroring_count`: +--------------------------------- SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END AS case_when_priority_0_and_priority_10_then_0_when_priority_10_an, \"queue\" AS queue FROM (SELECT priority, queue, COUNT(*) AS count FROM \"delayed_jobs\" - WHERE (\"delayed_jobs\".\"locked_at\" IS NULL - OR \"delayed_jobs\".\"locked_at\" < '2025-11-10 16:59:43') + WHERE \"delayed_jobs\".\"attempts\" > 0 AND \"delayed_jobs\".\"failed_at\" IS NULL - AND \"delayed_jobs\".\"run_at\" <= '2025-11-10 17:20:13' GROUP BY \"delayed_jobs\".\"priority\", \"delayed_jobs\".\"queue\") subquery GROUP BY CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, \"queue\" -SNAP -snapshots["produces the expected sqlite3 query plan for workable_count 1"] = <<-SNAP CO-ROUTINE subquery -SCAN delayed_jobs USING INDEX idx_delayed_jobs_live +SCAN delayed_jobs USING INDEX delayed_jobs_priority USE TEMP B-TREE FOR GROUP BY SCAN subquery USE TEMP B-TREE FOR GROUP BY -SNAP +--- +-- QUERIES FOR `failed_count`: +--------------------------------- +-- (no new queries) +-- QUERIES FOR `max_lock_age`: +--------------------------------- +SELECT (CASE WHEN priority >= 0 + AND priority < 10 THEN 0 WHEN priority >= 10 + AND priority < 20 THEN 10 WHEN priority >= 20 + AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END) AS priority, queue, MIN(locked_at) AS locked_at, CURRENT_TIMESTAMP AS db_now_utc + FROM (SELECT priority, queue, MIN(locked_at) AS locked_at + FROM \"delayed_jobs\" + WHERE \"delayed_jobs\".\"locked_at\" >= '2025-11-10 16:59:43' + AND \"delayed_jobs\".\"failed_at\" IS NULL + AND \"delayed_jobs\".\"run_at\" <= '2025-11-10 17:20:13' + GROUP BY \"delayed_jobs\".\"priority\", \"delayed_jobs\".\"queue\") subquery + GROUP BY CASE WHEN priority >= 0 + AND priority < 10 THEN 0 WHEN priority >= 10 + AND priority < 20 THEN 10 WHEN priority >= 20 + AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, \"queue\" -snapshots["[legacy index] produces the expected sqlite3 query plan for workable_count 1"] = <<-SNAP CO-ROUTINE subquery SCAN delayed_jobs USING INDEX delayed_jobs_priority USE TEMP B-TREE FOR GROUP BY SCAN subquery USE TEMP B-TREE FOR GROUP BY -SNAP - -snapshots["runs the expected sqlite3 query for alert_age_percent 1"] = <<-SNAP +--- +-- QUERIES FOR `max_age`: +--------------------------------- SELECT (CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 @@ -944,25 +914,48 @@ SELECT (CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, \"queue\" -SNAP -snapshots["produces the expected sqlite3 query plan for alert_age_percent 1"] = <<-SNAP CO-ROUTINE subquery -SCAN delayed_jobs USING INDEX idx_delayed_jobs_live +SCAN delayed_jobs USING INDEX delayed_jobs_priority USE TEMP B-TREE FOR GROUP BY SCAN subquery USE TEMP B-TREE FOR GROUP BY -SNAP +--- +-- QUERIES FOR `working_count`: +--------------------------------- +-- (no new queries) +-- QUERIES FOR `workable_count`: +--------------------------------- +SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 + AND priority < 10 THEN 0 WHEN priority >= 10 + AND priority < 20 THEN 10 WHEN priority >= 20 + AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END AS case_when_priority_0_and_priority_10_then_0_when_priority_10_an, \"queue\" AS queue + FROM (SELECT priority, queue, COUNT(*) AS count + FROM \"delayed_jobs\" + WHERE (\"delayed_jobs\".\"locked_at\" IS NULL + OR \"delayed_jobs\".\"locked_at\" < '2025-11-10 16:59:43') + AND \"delayed_jobs\".\"failed_at\" IS NULL + AND \"delayed_jobs\".\"run_at\" <= '2025-11-10 17:20:13' + GROUP BY \"delayed_jobs\".\"priority\", \"delayed_jobs\".\"queue\") subquery + GROUP BY CASE WHEN priority >= 0 + AND priority < 10 THEN 0 WHEN priority >= 10 + AND priority < 20 THEN 10 WHEN priority >= 20 + AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, \"queue\" -snapshots["[legacy index] produces the expected sqlite3 query plan for alert_age_percent 1"] = <<-SNAP CO-ROUTINE subquery SCAN delayed_jobs USING INDEX delayed_jobs_priority USE TEMP B-TREE FOR GROUP BY SCAN subquery USE TEMP B-TREE FOR GROUP BY +--- +-- QUERIES FOR `alert_age_percent`: +--------------------------------- +-- (no new queries) SNAP -snapshots["runs the expected mysql2 query for count 1"] = <<-SNAP +snapshots["runs the expected mysql2 queries with the expected plans 1"] = <<-SNAP +-- QUERIES FOR `count`: +--------------------------------- SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 @@ -974,9 +967,7 @@ SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, `queue` -SNAP -snapshots["produces the expected mysql2 query plan for count 1"] = <<-SNAP -> Table scan on -> Aggregate using temporary table -> Table scan on subquery (cost=...) @@ -984,19 +975,9 @@ snapshots["produces the expected mysql2 query plan for count 1"] = <<-SNAP -> Table scan on -> Aggregate using temporary table -> Covering index scan on delayed_jobs using idx_delayed_jobs_live (cost=...) -SNAP - -snapshots["[legacy index] produces the expected mysql2 query plan for count 1"] = <<-SNAP --> Table scan on - -> Aggregate using temporary table - -> Table scan on subquery (cost=...) - -> Materialize (cost=...) - -> Table scan on - -> Aggregate using temporary table - -> Table scan on delayed_jobs (cost=...) -SNAP - -snapshots["runs the expected mysql2 query for future_count 1"] = <<-SNAP +--- +-- QUERIES FOR `future_count`: +--------------------------------- SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 @@ -1010,9 +991,7 @@ SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, `queue` -SNAP -snapshots["produces the expected mysql2 query plan for future_count 1"] = <<-SNAP -> Table scan on -> Aggregate using temporary table -> Table scan on subquery (cost=...) @@ -1021,20 +1000,9 @@ snapshots["produces the expected mysql2 query plan for future_count 1"] = <<-SNA -> Aggregate using temporary table -> Filter: ((delayed_jobs.failed_at is null) and (delayed_jobs.run_at > TIMESTAMP'2025-11-10 17:20:13')) (cost=...) -> Covering index lookup on delayed_jobs using idx_delayed_jobs_live (failed_at = NULL) (cost=...) -SNAP - -snapshots["[legacy index] produces the expected mysql2 query plan for future_count 1"] = <<-SNAP --> Table scan on - -> Aggregate using temporary table - -> Table scan on subquery (cost=...) - -> Materialize (cost=...) - -> Table scan on - -> Aggregate using temporary table - -> Filter: ((delayed_jobs.failed_at is null) and (delayed_jobs.run_at > TIMESTAMP'2025-11-10 17:20:13')) (cost=...) - -> Table scan on delayed_jobs (cost=...) -SNAP - -snapshots["runs the expected mysql2 query for locked_count 1"] = <<-SNAP +--- +-- QUERIES FOR `locked_count`: +--------------------------------- SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 @@ -1049,9 +1017,7 @@ SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, `queue` -SNAP -snapshots["produces the expected mysql2 query plan for locked_count 1"] = <<-SNAP -> Table scan on -> Aggregate using temporary table -> Table scan on subquery (cost=...) @@ -1060,20 +1026,9 @@ snapshots["produces the expected mysql2 query plan for locked_count 1"] = <<-SNA -> Aggregate using temporary table -> Filter: ((delayed_jobs.locked_at >= TIMESTAMP'2025-11-10 16:59:43') and (delayed_jobs.failed_at is null) and (delayed_jobs.run_at <= TIMESTAMP'2025-11-10 17:20:13')) (cost=...) -> Covering index lookup on delayed_jobs using idx_delayed_jobs_live (failed_at = NULL) (cost=...) -SNAP - -snapshots["[legacy index] produces the expected mysql2 query plan for locked_count 1"] = <<-SNAP --> Table scan on - -> Aggregate using temporary table - -> Table scan on subquery (cost=...) - -> Materialize (cost=...) - -> Table scan on - -> Aggregate using temporary table - -> Filter: ((delayed_jobs.locked_at >= TIMESTAMP'2025-11-10 16:59:43') and (delayed_jobs.failed_at is null) and (delayed_jobs.run_at <= TIMESTAMP'2025-11-10 17:20:13')) (cost=...) - -> Table scan on delayed_jobs (cost=...) -SNAP - -snapshots["runs the expected mysql2 query for erroring_count 1"] = <<-SNAP +--- +-- QUERIES FOR `erroring_count`: +--------------------------------- SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 @@ -1087,9 +1042,7 @@ SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, `queue` -SNAP -snapshots["produces the expected mysql2 query plan for erroring_count 1"] = <<-SNAP -> Table scan on -> Aggregate using temporary table -> Table scan on subquery (cost=...) @@ -1098,20 +1051,9 @@ snapshots["produces the expected mysql2 query plan for erroring_count 1"] = <<-S -> Aggregate using temporary table -> Filter: ((delayed_jobs.attempts > 0) and (delayed_jobs.failed_at is null)) (cost=...) -> Covering index lookup on delayed_jobs using idx_delayed_jobs_live (failed_at = NULL) (cost=...) -SNAP - -snapshots["[legacy index] produces the expected mysql2 query plan for erroring_count 1"] = <<-SNAP --> Table scan on - -> Aggregate using temporary table - -> Table scan on subquery (cost=...) - -> Materialize (cost=...) - -> Table scan on - -> Aggregate using temporary table - -> Filter: ((delayed_jobs.attempts > 0) and (delayed_jobs.failed_at is null)) (cost=...) - -> Table scan on delayed_jobs (cost=...) -SNAP - -snapshots["runs the expected mysql2 query for failed_count 1"] = <<-SNAP +--- +-- QUERIES FOR `failed_count`: +--------------------------------- SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 @@ -1124,9 +1066,7 @@ SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, `queue` -SNAP -snapshots["produces the expected mysql2 query plan for failed_count 1"] = <<-SNAP -> Table scan on -> Aggregate using temporary table -> Table scan on subquery (cost=...) @@ -1135,20 +1075,9 @@ snapshots["produces the expected mysql2 query plan for failed_count 1"] = <<-SNA -> Aggregate using temporary table -> Filter: (delayed_jobs.failed_at is not null) (cost=...) -> Covering index range scan on delayed_jobs using idx_delayed_jobs_live over (NULL < failed_at) (cost=...) -SNAP - -snapshots["[legacy index] produces the expected mysql2 query plan for failed_count 1"] = <<-SNAP --> Table scan on - -> Aggregate using temporary table - -> Table scan on subquery (cost=...) - -> Materialize (cost=...) - -> Table scan on - -> Aggregate using temporary table - -> Filter: (delayed_jobs.failed_at is not null) (cost=...) - -> Table scan on delayed_jobs (cost=...) -SNAP - -snapshots["runs the expected mysql2 query for max_lock_age 1"] = <<-SNAP +--- +-- QUERIES FOR `max_lock_age`: +--------------------------------- SELECT (CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 @@ -1163,9 +1092,7 @@ SELECT (CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, `queue` -SNAP -snapshots["produces the expected mysql2 query plan for max_lock_age 1"] = <<-SNAP -> Table scan on -> Aggregate using temporary table -> Table scan on subquery (cost=...) @@ -1174,25 +1101,44 @@ snapshots["produces the expected mysql2 query plan for max_lock_age 1"] = <<-SNA -> Aggregate using temporary table -> Filter: ((delayed_jobs.locked_at >= TIMESTAMP'2025-11-10 16:59:43') and (delayed_jobs.failed_at is null) and (delayed_jobs.run_at <= TIMESTAMP'2025-11-10 17:20:13')) (cost=...) -> Covering index lookup on delayed_jobs using idx_delayed_jobs_live (failed_at = NULL) (cost=...) -SNAP +--- +-- QUERIES FOR `max_age`: +--------------------------------- +SELECT (CASE WHEN priority >= 0 + AND priority < 10 THEN 0 WHEN priority >= 10 + AND priority < 20 THEN 10 WHEN priority >= 20 + AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END) AS priority, queue, MIN(run_at) AS run_at, UTC_TIMESTAMP() AS db_now_utc + FROM (SELECT priority, queue, MIN(run_at) AS run_at + FROM `delayed_jobs` + WHERE (`delayed_jobs`.`locked_at` IS NULL + OR `delayed_jobs`.`locked_at` < '2025-11-10 16:59:43') + AND `delayed_jobs`.`failed_at` IS NULL + AND `delayed_jobs`.`run_at` <= '2025-11-10 17:20:13' + GROUP BY `delayed_jobs`.`priority`, `delayed_jobs`.`queue`) subquery + GROUP BY CASE WHEN priority >= 0 + AND priority < 10 THEN 0 WHEN priority >= 10 + AND priority < 20 THEN 10 WHEN priority >= 20 + AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, `queue` -snapshots["[legacy index] produces the expected mysql2 query plan for max_lock_age 1"] = <<-SNAP -> Table scan on -> Aggregate using temporary table -> Table scan on subquery (cost=...) -> Materialize (cost=...) -> Table scan on -> Aggregate using temporary table - -> Filter: ((delayed_jobs.locked_at >= TIMESTAMP'2025-11-10 16:59:43') and (delayed_jobs.failed_at is null) and (delayed_jobs.run_at <= TIMESTAMP'2025-11-10 17:20:13')) (cost=...) - -> Table scan on delayed_jobs (cost=...) -SNAP - -snapshots["runs the expected mysql2 query for max_age 1"] = <<-SNAP -SELECT (CASE WHEN priority >= 0 + -> Filter: (((delayed_jobs.locked_at is null) or (delayed_jobs.locked_at < TIMESTAMP'2025-11-10 16:59:43')) and (delayed_jobs.failed_at is null) and (delayed_jobs.run_at <= TIMESTAMP'2025-11-10 17:20:13')) (cost=...) + -> Covering index lookup on delayed_jobs using idx_delayed_jobs_live (failed_at = NULL) (cost=...) +--- +-- QUERIES FOR `working_count`: +--------------------------------- +-- (no new queries) +-- QUERIES FOR `workable_count`: +--------------------------------- +SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 - AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END) AS priority, queue, MIN(run_at) AS run_at, UTC_TIMESTAMP() AS db_now_utc - FROM (SELECT priority, queue, MIN(run_at) AS run_at + AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END AS case_when_priority_0_and_priority_10_then_0_when_priority_10_an, `queue` AS queue + FROM (SELECT priority, queue, COUNT(*) AS count FROM `delayed_jobs` WHERE (`delayed_jobs`.`locked_at` IS NULL OR `delayed_jobs`.`locked_at` < '2025-11-10 16:59:43') @@ -1203,9 +1149,7 @@ SELECT (CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, `queue` -SNAP -snapshots["produces the expected mysql2 query plan for max_age 1"] = <<-SNAP -> Table scan on -> Aggregate using temporary table -> Table scan on subquery (cost=...) @@ -1214,20 +1158,62 @@ snapshots["produces the expected mysql2 query plan for max_age 1"] = <<-SNAP -> Aggregate using temporary table -> Filter: (((delayed_jobs.locked_at is null) or (delayed_jobs.locked_at < TIMESTAMP'2025-11-10 16:59:43')) and (delayed_jobs.failed_at is null) and (delayed_jobs.run_at <= TIMESTAMP'2025-11-10 17:20:13')) (cost=...) -> Covering index lookup on delayed_jobs using idx_delayed_jobs_live (failed_at = NULL) (cost=...) +--- +-- QUERIES FOR `alert_age_percent`: +--------------------------------- +-- (no new queries) SNAP -snapshots["[legacy index] produces the expected mysql2 query plan for max_age 1"] = <<-SNAP +snapshots["[legacy index] runs the expected mysql2 queries with the expected plans 1"] = <<-SNAP +-- QUERIES FOR `count`: +--------------------------------- +SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 + AND priority < 10 THEN 0 WHEN priority >= 10 + AND priority < 20 THEN 10 WHEN priority >= 20 + AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END AS case_when_priority_0_and_priority_10_then_0_when_priority_10_an, `queue` AS queue + FROM (SELECT priority, queue, COUNT(*) AS count + FROM `delayed_jobs` + GROUP BY `delayed_jobs`.`priority`, `delayed_jobs`.`queue`) subquery + GROUP BY CASE WHEN priority >= 0 + AND priority < 10 THEN 0 WHEN priority >= 10 + AND priority < 20 THEN 10 WHEN priority >= 20 + AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, `queue` + -> Table scan on -> Aggregate using temporary table -> Table scan on subquery (cost=...) -> Materialize (cost=...) -> Table scan on -> Aggregate using temporary table - -> Filter: (((delayed_jobs.locked_at is null) or (delayed_jobs.locked_at < TIMESTAMP'2025-11-10 16:59:43')) and (delayed_jobs.failed_at is null) and (delayed_jobs.run_at <= TIMESTAMP'2025-11-10 17:20:13')) (cost=...) - -> Table scan on delayed_jobs (cost=...) -SNAP + -> Table scan on delayed_jobs (cost=...) +--- +-- QUERIES FOR `future_count`: +--------------------------------- +SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 + AND priority < 10 THEN 0 WHEN priority >= 10 + AND priority < 20 THEN 10 WHEN priority >= 20 + AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END AS case_when_priority_0_and_priority_10_then_0_when_priority_10_an, `queue` AS queue + FROM (SELECT priority, queue, COUNT(*) AS count + FROM `delayed_jobs` + WHERE `delayed_jobs`.`failed_at` IS NULL + AND `delayed_jobs`.`run_at` > '2025-11-10 17:20:13' + GROUP BY `delayed_jobs`.`priority`, `delayed_jobs`.`queue`) subquery + GROUP BY CASE WHEN priority >= 0 + AND priority < 10 THEN 0 WHEN priority >= 10 + AND priority < 20 THEN 10 WHEN priority >= 20 + AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, `queue` -snapshots["runs the expected mysql2 query for working_count 1"] = <<-SNAP +-> Table scan on + -> Aggregate using temporary table + -> Table scan on subquery (cost=...) + -> Materialize (cost=...) + -> Table scan on + -> Aggregate using temporary table + -> Filter: ((delayed_jobs.failed_at is null) and (delayed_jobs.run_at > TIMESTAMP'2025-11-10 17:20:13')) (cost=...) + -> Table scan on delayed_jobs (cost=...) +--- +-- QUERIES FOR `locked_count`: +--------------------------------- SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 @@ -1242,9 +1228,7 @@ SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, `queue` -SNAP -snapshots["produces the expected mysql2 query plan for working_count 1"] = <<-SNAP -> Table scan on -> Aggregate using temporary table -> Table scan on subquery (cost=...) @@ -1252,61 +1236,85 @@ snapshots["produces the expected mysql2 query plan for working_count 1"] = <<-SN -> Table scan on -> Aggregate using temporary table -> Filter: ((delayed_jobs.locked_at >= TIMESTAMP'2025-11-10 16:59:43') and (delayed_jobs.failed_at is null) and (delayed_jobs.run_at <= TIMESTAMP'2025-11-10 17:20:13')) (cost=...) - -> Covering index lookup on delayed_jobs using idx_delayed_jobs_live (failed_at = NULL) (cost=...) -SNAP + -> Table scan on delayed_jobs (cost=...) +--- +-- QUERIES FOR `erroring_count`: +--------------------------------- +SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 + AND priority < 10 THEN 0 WHEN priority >= 10 + AND priority < 20 THEN 10 WHEN priority >= 20 + AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END AS case_when_priority_0_and_priority_10_then_0_when_priority_10_an, `queue` AS queue + FROM (SELECT priority, queue, COUNT(*) AS count + FROM `delayed_jobs` + WHERE `delayed_jobs`.`attempts` > 0 + AND `delayed_jobs`.`failed_at` IS NULL + GROUP BY `delayed_jobs`.`priority`, `delayed_jobs`.`queue`) subquery + GROUP BY CASE WHEN priority >= 0 + AND priority < 10 THEN 0 WHEN priority >= 10 + AND priority < 20 THEN 10 WHEN priority >= 20 + AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, `queue` -snapshots["[legacy index] produces the expected mysql2 query plan for working_count 1"] = <<-SNAP -> Table scan on -> Aggregate using temporary table -> Table scan on subquery (cost=...) -> Materialize (cost=...) -> Table scan on -> Aggregate using temporary table - -> Filter: ((delayed_jobs.locked_at >= TIMESTAMP'2025-11-10 16:59:43') and (delayed_jobs.failed_at is null) and (delayed_jobs.run_at <= TIMESTAMP'2025-11-10 17:20:13')) (cost=...) + -> Filter: ((delayed_jobs.attempts > 0) and (delayed_jobs.failed_at is null)) (cost=...) -> Table scan on delayed_jobs (cost=...) -SNAP - -snapshots["runs the expected mysql2 query for workable_count 1"] = <<-SNAP +--- +-- QUERIES FOR `failed_count`: +--------------------------------- SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END AS case_when_priority_0_and_priority_10_then_0_when_priority_10_an, `queue` AS queue FROM (SELECT priority, queue, COUNT(*) AS count FROM `delayed_jobs` - WHERE (`delayed_jobs`.`locked_at` IS NULL - OR `delayed_jobs`.`locked_at` < '2025-11-10 16:59:43') - AND `delayed_jobs`.`failed_at` IS NULL - AND `delayed_jobs`.`run_at` <= '2025-11-10 17:20:13' + WHERE `delayed_jobs`.`failed_at` IS NOT NULL GROUP BY `delayed_jobs`.`priority`, `delayed_jobs`.`queue`) subquery GROUP BY CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, `queue` -SNAP -snapshots["produces the expected mysql2 query plan for workable_count 1"] = <<-SNAP -> Table scan on -> Aggregate using temporary table -> Table scan on subquery (cost=...) -> Materialize (cost=...) -> Table scan on -> Aggregate using temporary table - -> Filter: (((delayed_jobs.locked_at is null) or (delayed_jobs.locked_at < TIMESTAMP'2025-11-10 16:59:43')) and (delayed_jobs.failed_at is null) and (delayed_jobs.run_at <= TIMESTAMP'2025-11-10 17:20:13')) (cost=...) - -> Covering index lookup on delayed_jobs using idx_delayed_jobs_live (failed_at = NULL) (cost=...) -SNAP + -> Filter: (delayed_jobs.failed_at is not null) (cost=...) + -> Table scan on delayed_jobs (cost=...) +--- +-- QUERIES FOR `max_lock_age`: +--------------------------------- +SELECT (CASE WHEN priority >= 0 + AND priority < 10 THEN 0 WHEN priority >= 10 + AND priority < 20 THEN 10 WHEN priority >= 20 + AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END) AS priority, queue, MIN(locked_at) AS locked_at, UTC_TIMESTAMP() AS db_now_utc + FROM (SELECT priority, queue, MIN(locked_at) AS locked_at + FROM `delayed_jobs` + WHERE `delayed_jobs`.`locked_at` >= '2025-11-10 16:59:43' + AND `delayed_jobs`.`failed_at` IS NULL + AND `delayed_jobs`.`run_at` <= '2025-11-10 17:20:13' + GROUP BY `delayed_jobs`.`priority`, `delayed_jobs`.`queue`) subquery + GROUP BY CASE WHEN priority >= 0 + AND priority < 10 THEN 0 WHEN priority >= 10 + AND priority < 20 THEN 10 WHEN priority >= 20 + AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, `queue` -snapshots["[legacy index] produces the expected mysql2 query plan for workable_count 1"] = <<-SNAP -> Table scan on -> Aggregate using temporary table -> Table scan on subquery (cost=...) -> Materialize (cost=...) -> Table scan on -> Aggregate using temporary table - -> Filter: (((delayed_jobs.locked_at is null) or (delayed_jobs.locked_at < TIMESTAMP'2025-11-10 16:59:43')) and (delayed_jobs.failed_at is null) and (delayed_jobs.run_at <= TIMESTAMP'2025-11-10 17:20:13')) (cost=...) + -> Filter: ((delayed_jobs.locked_at >= TIMESTAMP'2025-11-10 16:59:43') and (delayed_jobs.failed_at is null) and (delayed_jobs.run_at <= TIMESTAMP'2025-11-10 17:20:13')) (cost=...) -> Table scan on delayed_jobs (cost=...) -SNAP - -snapshots["runs the expected mysql2 query for alert_age_percent 1"] = <<-SNAP +--- +-- QUERIES FOR `max_age`: +--------------------------------- SELECT (CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 @@ -1322,9 +1330,7 @@ SELECT (CASE WHEN priority >= 0 AND priority < 10 THEN 0 WHEN priority >= 10 AND priority < 20 THEN 10 WHEN priority >= 20 AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, `queue` -SNAP -snapshots["produces the expected mysql2 query plan for alert_age_percent 1"] = <<-SNAP -> Table scan on -> Aggregate using temporary table -> Table scan on subquery (cost=...) @@ -1332,10 +1338,29 @@ snapshots["produces the expected mysql2 query plan for alert_age_percent 1"] = < -> Table scan on -> Aggregate using temporary table -> Filter: (((delayed_jobs.locked_at is null) or (delayed_jobs.locked_at < TIMESTAMP'2025-11-10 16:59:43')) and (delayed_jobs.failed_at is null) and (delayed_jobs.run_at <= TIMESTAMP'2025-11-10 17:20:13')) (cost=...) - -> Covering index lookup on delayed_jobs using idx_delayed_jobs_live (failed_at = NULL) (cost=...) -SNAP + -> Table scan on delayed_jobs (cost=...) +--- +-- QUERIES FOR `working_count`: +--------------------------------- +-- (no new queries) +-- QUERIES FOR `workable_count`: +--------------------------------- +SELECT SUM(count) AS sum_count, CASE WHEN priority >= 0 + AND priority < 10 THEN 0 WHEN priority >= 10 + AND priority < 20 THEN 10 WHEN priority >= 20 + AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END AS case_when_priority_0_and_priority_10_then_0_when_priority_10_an, `queue` AS queue + FROM (SELECT priority, queue, COUNT(*) AS count + FROM `delayed_jobs` + WHERE (`delayed_jobs`.`locked_at` IS NULL + OR `delayed_jobs`.`locked_at` < '2025-11-10 16:59:43') + AND `delayed_jobs`.`failed_at` IS NULL + AND `delayed_jobs`.`run_at` <= '2025-11-10 17:20:13' + GROUP BY `delayed_jobs`.`priority`, `delayed_jobs`.`queue`) subquery + GROUP BY CASE WHEN priority >= 0 + AND priority < 10 THEN 0 WHEN priority >= 10 + AND priority < 20 THEN 10 WHEN priority >= 20 + AND priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, `queue` -snapshots["[legacy index] produces the expected mysql2 query plan for alert_age_percent 1"] = <<-SNAP -> Table scan on -> Aggregate using temporary table -> Table scan on subquery (cost=...) @@ -1344,4 +1369,8 @@ snapshots["[legacy index] produces the expected mysql2 query plan for alert_age_ -> Aggregate using temporary table -> Filter: (((delayed_jobs.locked_at is null) or (delayed_jobs.locked_at < TIMESTAMP'2025-11-10 16:59:43')) and (delayed_jobs.failed_at is null) and (delayed_jobs.run_at <= TIMESTAMP'2025-11-10 17:20:13')) (cost=...) -> Table scan on delayed_jobs (cost=...) +--- +-- QUERIES FOR `alert_age_percent`: +--------------------------------- +-- (no new queries) SNAP diff --git a/spec/delayed/monitor_spec.rb b/spec/delayed/monitor_spec.rb index 15160ba3..990bec21 100644 --- a/spec/delayed/monitor_spec.rb +++ b/spec/delayed/monitor_spec.rb @@ -345,7 +345,7 @@ end end - describe '#query_for' do + describe 'SQL' do let(:monitor) { described_class.new } let(:queries) { [] } let(:now) { '2025-11-10 17:20:13 UTC' } @@ -360,30 +360,28 @@ value = value.value if value.is_a?(ActiveModel::Attribute) sql = sql.sub(/(\?|\$\d)/, ActiveRecord::Base.connection.quote(value)) end - queries << sql + queries << QueryUnderTest.for(sql) + queries << "---" end end - def queries_for(metric) - monitor.query_for(metric) - queries.map { |q| QueryUnderTest.for(q) } + def query_descriptions + described_class::METRICS.each do |metric| + queries << "-- QUERIES FOR `#{metric}`:" + queries << "---------------------------------" + monitor.query_for(metric) + queries << "-- (no new queries)" unless queries.last == '---' + end + queries.dup.map { |query| query.try(:full_description) || query } end - described_class::METRICS.each do |metric| - context "('#{metric}')" do - it "runs the expected #{current_adapter} query for #{metric}" do - expect(queries_for(metric).map(&:formatted).join("\n")).to match_snapshot - end - - it "produces the expected #{current_adapter} query plan for #{metric}" do - expect(queries_for(metric).map(&:explain).join("\n")).to match_snapshot - end + it "runs the expected #{current_adapter} queries with the expected plans" do + expect(query_descriptions.join("\n")).to match_snapshot + end - context 'when using the legacy index', :with_legacy_table_index do - it "[legacy index] produces the expected #{current_adapter} query plan for #{metric}" do - expect(queries_for(metric).map(&:explain).join("\n")).to match_snapshot - end - end + context 'when using the legacy index', :with_legacy_table_index do + it "[legacy index] runs the expected #{current_adapter} queries with the expected plans" do + expect(query_descriptions.join("\n")).to match_snapshot end end end diff --git a/spec/helper.rb b/spec/helper.rb index 09a09a9b..89349ef8 100644 --- a/spec/helper.rb +++ b/spec/helper.rb @@ -274,6 +274,10 @@ def self.for(query, connection: ActiveRecord::Base.connection) new(query.respond_to?(:to_sql) ? query.to_sql : query.to_s, connection) end + def full_description + [formatted, explain].join("\n\n") + end + def formatted fmt = sql.squish