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