From 1836bd63e0102137a68a6e272feeb4fca41262fd Mon Sep 17 00:00:00 2001 From: James Cook Date: Wed, 11 Dec 2024 17:24:13 -0600 Subject: [PATCH] Fix GoodJob queue size/latency query for discarded jobs Fixes https://github.com/hirefire/hirefire-resource-ruby/issues/70 Ensure compatibility with GoodJob 3 and prevent errors in GoodJob 2 GoodJob 2 does not support error_event, and will therefore not take discarded jobs into account. --- lib/hirefire/macro/good_job.rb | 2 ++ lib/hirefire/macro/helpers/good_job.rb | 15 ++++++++ test/hirefire/macro/test_good_job.rb | 50 ++++++++++++++++++++++++++ 3 files changed, 67 insertions(+) diff --git a/lib/hirefire/macro/good_job.rb b/lib/hirefire/macro/good_job.rb index bf3fe82..ef2743a 100644 --- a/lib/hirefire/macro/good_job.rb +++ b/lib/hirefire/macro/good_job.rb @@ -28,6 +28,7 @@ def job_queue_latency(*queues) query = good_job_class query = query.where(queue_name: queues) if queues.any? query = query.where(performed_at: nil) + query = query.where.not(error_event: discarded_enum).or(query.where(error_event: nil)) if error_event_supported? query = query.where(scheduled_at: ..Time.now).or(query.where(scheduled_at: nil)) query = query.order(scheduled_at: :asc, created_at: :asc) @@ -55,6 +56,7 @@ def job_queue_size(*queues) query = good_job_class query = query.where(queue_name: queues) if queues.any? query = query.where(performed_at: nil) + query = query.where.not(error_event: discarded_enum).or(query.where(error_event: nil)) if error_event_supported? query = query.where(scheduled_at: ..Time.now).or(query.where(scheduled_at: nil)) query.count end diff --git a/lib/hirefire/macro/helpers/good_job.rb b/lib/hirefire/macro/helpers/good_job.rb index 64f2815..0b1787f 100644 --- a/lib/hirefire/macro/helpers/good_job.rb +++ b/lib/hirefire/macro/helpers/good_job.rb @@ -13,6 +13,21 @@ def good_job_class ::GoodJob::Execution end end + + def error_event_supported? + Gem::Version.new(::GoodJob::VERSION) >= Gem::Version.new("3.0.0") + end + + [ + :interrupted, + :unhandled, + :handled, + :retried, + :retry_stopped, + :discarded + ].each_with_index do |event, index| + define_method(:"#{event}_enum") { index } + end end end end diff --git a/test/hirefire/macro/test_good_job.rb b/test/hirefire/macro/test_good_job.rb index 9f16355..a1ba050 100644 --- a/test/hirefire/macro/test_good_job.rb +++ b/test/hirefire/macro/test_good_job.rb @@ -42,6 +42,31 @@ def test_job_queue_latency_with_unfinished_jobs assert_equal 0, HireFire::Macro::GoodJob.job_queue_latency end + def test_job_queue_latency_with_discarded_jobs + skip "GoodJob #{::GoodJob::VERSION} does not support error events" unless error_event_supported? + job_id = Timecop.freeze(1.minute.ago) { BasicJob.perform_later.job_id } + good_job_class.where(active_job_id: job_id).update_all( + performed_at: nil, + scheduled_at: 1.minute.ago, + finished_at: 1.minute.ago, + error_event: discarded_enum + ) + assert_equal 0, HireFire::Macro::GoodJob.job_queue_latency + end + + def test_job_queue_latency_with_retried_jobs + skip "GoodJob #{::GoodJob::VERSION} does not support error events" unless error_event_supported? + job_id = Timecop.freeze(1.minute.ago) { BasicJob.perform_later.job_id } + good_job_class.where(active_job_id: job_id).update_all( + performed_at: nil, + scheduled_at: 1.minute.ago, + error_event: retried_enum + ) + assert_in_delta 60, HireFire::Macro::GoodJob.job_queue_latency, LATENCY_DELTA + good_job_class.where(active_job_id: job_id).update_all(performed_at: Time.now) + assert_equal 0, HireFire::Macro::GoodJob.job_queue_latency + end + def test_job_queue_size_without_jobs assert_equal 0, HireFire::Macro::GoodJob.job_queue_size end @@ -66,6 +91,31 @@ def test_job_queue_size_with_unfinished_jobs assert_equal 0, HireFire::Macro::GoodJob.job_queue_size end + def test_job_queue_size_with_discarded_jobs + skip "GoodJob #{::GoodJob::VERSION} does not support error events" unless error_event_supported? + job_id = Timecop.freeze(1.minute.ago) { BasicJob.perform_later.job_id } + good_job_class.where(active_job_id: job_id).update_all( + performed_at: nil, + scheduled_at: 1.minute.ago, + finished_at: 1.minute.ago, + error_event: discarded_enum + ) + assert_equal 0, HireFire::Macro::GoodJob.job_queue_size + end + + def test_job_queue_size_with_retried_jobs + skip "GoodJob #{::GoodJob::VERSION} does not support error events" unless error_event_supported? + job_id = Timecop.freeze(1.minute.ago) { BasicJob.perform_later.job_id } + good_job_class.where(active_job_id: job_id).update_all( + performed_at: nil, + scheduled_at: 1.minute.ago, + error_event: retried_enum + ) + assert_equal 1, HireFire::Macro::GoodJob.job_queue_size + good_job_class.where(active_job_id: job_id).update_all(performed_at: Time.now) + assert_equal 0, HireFire::Macro::GoodJob.job_queue_size + end + def test_deprecated_queue_method BasicJob.perform_later assert_equal 1, HireFire::Macro::GoodJob.queue(:default)