diff --git a/lib/delayed/monitor.rb b/lib/delayed/monitor.rb index cbac847..80d1427 100644 --- a/lib/delayed/monitor.rb +++ b/lib/delayed/monitor.rb @@ -38,7 +38,7 @@ def query_for(metric) def self.sql_now_in_utc case ActiveRecord::Base.connection.adapter_name when 'PostgreSQL' - "TIMEZONE('UTC', NOW())" + "TIMEZONE('UTC', STATEMENT_TIMESTAMP())" when 'MySQL', 'Mysql2' "UTC_TIMESTAMP()" else @@ -142,16 +142,16 @@ def failed_count_grouped end def max_lock_age_grouped - oldest_locked_at_query.transform_values { |j| db_now(j) - j.locked_at } + oldest_locked_at_query.transform_values { |j| time_ago(db_now(j), j.locked_at) } end def max_age_grouped - oldest_run_at_query.transform_values { |j| db_now(j) - j.run_at } + oldest_run_at_query.transform_values { |j| time_ago(db_now(j), j.run_at) } end def alert_age_percent_grouped oldest_run_at_query.each_with_object({}) do |((priority, queue), j), metrics| - max_age = db_now(j) - j.run_at + max_age = time_ago(db_now(j), j.run_at) alert_age = Priority.new(priority).alert_age metrics[[priority, queue]] = [max_age / alert_age * 100, 100].min if alert_age end @@ -183,6 +183,10 @@ def db_now(record) self.class.parse_utc_time(record.db_now_utc) end + def time_ago(now, value) + [now - (value || now), 0].max + end + def priority_case_statement [ 'CASE', diff --git a/spec/delayed/__snapshots__/monitor_spec.rb.snap b/spec/delayed/__snapshots__/monitor_spec.rb.snap index 352482c..89cc2de 100644 --- a/spec/delayed/__snapshots__/monitor_spec.rb.snap +++ b/spec/delayed/__snapshots__/monitor_spec.rb.snap @@ -149,7 +149,7 @@ GroupAggregate (cost=...) --------------------------------- SELECT (CASE WHEN priority < 10 THEN 0 WHEN priority < 20 THEN 10 WHEN 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 + TIMEZONE('UTC', STATEMENT_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' @@ -159,7 +159,7 @@ SELECT (CASE WHEN priority < 10 THEN 0 WHEN priority < 20 THEN 10 WHEN priority GROUP BY CASE WHEN priority < 10 THEN 0 WHEN priority < 20 THEN 10 WHEN priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, \"queue\" GroupAggregate (cost=...) - Output: (CASE WHEN (subquery.priority < 10) THEN 0 WHEN (subquery.priority < 20) THEN 10 WHEN (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()) + Output: (CASE WHEN (subquery.priority < 10) THEN 0 WHEN (subquery.priority < 20) THEN 10 WHEN (subquery.priority < 30) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue, min(subquery.locked_at), timezone('UTC'::text, statement_timestamp()) Group Key: (CASE WHEN (subquery.priority < 10) THEN 0 WHEN (subquery.priority < 20) THEN 10 WHEN (subquery.priority < 30) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue -> Sort (cost=...) Output: (CASE WHEN (subquery.priority < 10) THEN 0 WHEN (subquery.priority < 20) THEN 10 WHEN (subquery.priority < 30) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue, subquery.locked_at @@ -181,7 +181,7 @@ GroupAggregate (cost=...) --------------------------------- SELECT (CASE WHEN priority < 10 THEN 0 WHEN priority < 20 THEN 10 WHEN 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 + TIMEZONE('UTC', STATEMENT_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 @@ -192,7 +192,7 @@ SELECT (CASE WHEN priority < 10 THEN 0 WHEN priority < 20 THEN 10 WHEN priority GROUP BY CASE WHEN priority < 10 THEN 0 WHEN priority < 20 THEN 10 WHEN priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, \"queue\" GroupAggregate (cost=...) - Output: (CASE WHEN (subquery.priority < 10) THEN 0 WHEN (subquery.priority < 20) THEN 10 WHEN (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()) + Output: (CASE WHEN (subquery.priority < 10) THEN 0 WHEN (subquery.priority < 20) THEN 10 WHEN (subquery.priority < 30) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue, min(subquery.run_at), timezone('UTC'::text, statement_timestamp()) Group Key: (CASE WHEN (subquery.priority < 10) THEN 0 WHEN (subquery.priority < 20) THEN 10 WHEN (subquery.priority < 30) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue -> Sort (cost=...) Output: (CASE WHEN (subquery.priority < 10) THEN 0 WHEN (subquery.priority < 20) THEN 10 WHEN (subquery.priority < 30) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue, subquery.run_at @@ -408,7 +408,7 @@ GroupAggregate (cost=...) --------------------------------- SELECT (CASE WHEN priority < 10 THEN 0 WHEN priority < 20 THEN 10 WHEN 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 + TIMEZONE('UTC', STATEMENT_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' @@ -418,7 +418,7 @@ SELECT (CASE WHEN priority < 10 THEN 0 WHEN priority < 20 THEN 10 WHEN priority GROUP BY CASE WHEN priority < 10 THEN 0 WHEN priority < 20 THEN 10 WHEN priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, \"queue\" GroupAggregate (cost=...) - Output: (CASE WHEN (subquery.priority < 10) THEN 0 WHEN (subquery.priority < 20) THEN 10 WHEN (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()) + Output: (CASE WHEN (subquery.priority < 10) THEN 0 WHEN (subquery.priority < 20) THEN 10 WHEN (subquery.priority < 30) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue, min(subquery.locked_at), timezone('UTC'::text, statement_timestamp()) Group Key: (CASE WHEN (subquery.priority < 10) THEN 0 WHEN (subquery.priority < 20) THEN 10 WHEN (subquery.priority < 30) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue -> Sort (cost=...) Output: (CASE WHEN (subquery.priority < 10) THEN 0 WHEN (subquery.priority < 20) THEN 10 WHEN (subquery.priority < 30) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue, subquery.locked_at @@ -440,7 +440,7 @@ GroupAggregate (cost=...) --------------------------------- SELECT (CASE WHEN priority < 10 THEN 0 WHEN priority < 20 THEN 10 WHEN 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 + TIMEZONE('UTC', STATEMENT_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 @@ -451,7 +451,7 @@ SELECT (CASE WHEN priority < 10 THEN 0 WHEN priority < 20 THEN 10 WHEN priority GROUP BY CASE WHEN priority < 10 THEN 0 WHEN priority < 20 THEN 10 WHEN priority < 30 THEN 20 WHEN priority >= 30 THEN 30 END, \"queue\" GroupAggregate (cost=...) - Output: (CASE WHEN (subquery.priority < 10) THEN 0 WHEN (subquery.priority < 20) THEN 10 WHEN (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()) + Output: (CASE WHEN (subquery.priority < 10) THEN 0 WHEN (subquery.priority < 20) THEN 10 WHEN (subquery.priority < 30) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue, min(subquery.run_at), timezone('UTC'::text, statement_timestamp()) Group Key: (CASE WHEN (subquery.priority < 10) THEN 0 WHEN (subquery.priority < 20) THEN 10 WHEN (subquery.priority < 30) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue -> Sort (cost=...) Output: (CASE WHEN (subquery.priority < 10) THEN 0 WHEN (subquery.priority < 20) THEN 10 WHEN (subquery.priority < 30) THEN 20 WHEN (subquery.priority >= 30) THEN 30 ELSE NULL::integer END), subquery.queue, subquery.run_at diff --git a/spec/helper.rb b/spec/helper.rb index 0264a07..afb9ae2 100644 --- a/spec/helper.rb +++ b/spec/helper.rb @@ -228,10 +228,7 @@ def supports_block_expectations? diffable match do |block| - if @approximately && current_adapter != 'postgresql' - @expected_value = a_value_within([2, @expected_value.abs * 0.05].max).of(@expected_value) - end - + @expected_value = a_value_within([2, @expected_value.abs * 0.05].max).of(@expected_value) if @approximately @expected = { event_name: expected_event_name, payload: expected_payload, value: @expected_value } @actuals = [] callback = ->(name, _started, _finished, _unique_id, payload) do