From 195016da72e8d1612651e2b8fbccd61e79bfd88b Mon Sep 17 00:00:00 2001 From: Andrew Markle Date: Fri, 27 Jun 2025 11:24:52 -0400 Subject: [PATCH 1/9] Update README.md --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 076a98a..ae69617 100644 --- a/README.md +++ b/README.md @@ -33,13 +33,12 @@ Sidekiq.configure_server do |_config| end ``` -If using with resque: +If using with solid_queue or resque: ```ruby # config/initializers/yabeda.rb or elsewhere Yabeda::ActiveJob.install! ``` -If using resque you may need to use [yabeda-prometheus-mmap](https://github.com/yabeda-rb/yabeda-prometheus-mmap) or set your storage type to direct file store so that the metrics are available -to your collector. +If using solid_queue or resque you need to use [yabeda-prometheus-mmap](https://github.com/yabeda-rb/yabeda-prometheus-mmap) or set your storage type to direct file store so that the metrics are available to your collector. To set your storage type to direct file store you can do the following in your yabeda initializer: From 180026ffba1312bb52baf242606d92a112dd1b2b Mon Sep 17 00:00:00 2001 From: Andrew Markle Date: Wed, 17 Sep 2025 10:49:56 -0400 Subject: [PATCH 2/9] Fix github workflow --- .github/workflows/test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6c81ced..fc48b33 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -25,8 +25,8 @@ jobs: CI: true BUNDLE_GEMFILE: gemfiles/rails_${{ matrix.rails }}.gemfile steps: - - uses: actions/checkout@v2 - - uses: actions/cache@v2 + - uses: actions/checkout@v4 + - uses: actions/cache@v4 with: path: vendor/bundle key: bundle-${{ matrix.ruby }}-${{ hashFiles('**/*.gemspec') }}-${{ hashFiles(format('**/gemfiles/rails_{0}.gemfile', matrix.rails)) }} From c76e63ec5d2cc0762179ce6c40860ac616c081d7 Mon Sep 17 00:00:00 2001 From: Andrew Markle Date: Wed, 17 Sep 2025 15:01:06 -0400 Subject: [PATCH 3/9] UPdate test runners --- .github/workflows/test.yml | 4 ++-- spec/spec_helper.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index fc48b33..b120b13 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -17,8 +17,8 @@ jobs: strategy: fail-fast: false matrix: - rails: ["6.1", "7.0", "7.1", "7.2"] - ruby: ["3.1", "3.2", "3.3"] + rails: ["7.1", "7.2", "8.0"] + ruby: ["3.1", "3.2", "3.3", "3.4"] container: image: ruby:${{ matrix.ruby }} env: diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 1ae5eb1..065bd1a 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -6,9 +6,9 @@ require "yabeda/activejob" require "yabeda/rspec" require_relative "support/rails_app" +require "active_support" require "rspec/rails" require "simplecov" -require "active_support" SimpleCov.start RSpec.configure do |config| From d689dd4f6f27ab28d3cb3121824fe2f6c1c3d9da Mon Sep 17 00:00:00 2001 From: Andrew Markle Date: Wed, 17 Sep 2025 15:04:06 -0400 Subject: [PATCH 4/9] Update --- spec/spec_helper.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 065bd1a..554f40c 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -6,7 +6,6 @@ require "yabeda/activejob" require "yabeda/rspec" require_relative "support/rails_app" -require "active_support" require "rspec/rails" require "simplecov" SimpleCov.start From 7b7d96cbb56d261577b57fed8fd9b444a822420c Mon Sep 17 00:00:00 2001 From: Andrew Markle Date: Wed, 17 Sep 2025 15:07:27 -0400 Subject: [PATCH 5/9] Update gemfile --- gemfiles/{rails_6.1.gemfile => rails_8.0.gemfile} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename gemfiles/{rails_6.1.gemfile => rails_8.0.gemfile} (86%) diff --git a/gemfiles/rails_6.1.gemfile b/gemfiles/rails_8.0.gemfile similarity index 86% rename from gemfiles/rails_6.1.gemfile rename to gemfiles/rails_8.0.gemfile index ab30978..7ab16e9 100644 --- a/gemfiles/rails_6.1.gemfile +++ b/gemfiles/rails_8.0.gemfile @@ -3,6 +3,6 @@ source "https://rubygems.org" git_source(:github) { |repo| "https://github.com/#{repo}.git" } -gem "rails", "~> 6.1.0" +gem "rails", "~> 8.0.0" eval_gemfile "../Gemfile" From cc6cc3d8ffb63940b672f46f5b2c19bef6b18ce3 Mon Sep 17 00:00:00 2001 From: Andrew Markle Date: Wed, 17 Sep 2025 15:09:15 -0400 Subject: [PATCH 6/9] Add back testing for rails 7 --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b120b13..7218b3b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -17,7 +17,7 @@ jobs: strategy: fail-fast: false matrix: - rails: ["7.1", "7.2", "8.0"] + rails: ["7.0", "7.1", "7.2", "8.0"] ruby: ["3.1", "3.2", "3.3", "3.4"] container: image: ruby:${{ matrix.ruby }} From 5fa5dbae52c5e7f44b89fc0c319862b35e5a3912 Mon Sep 17 00:00:00 2001 From: Andrew Markle Date: Wed, 17 Sep 2025 15:21:19 -0400 Subject: [PATCH 7/9] Try this --- lib/yabeda/activejob.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/yabeda/activejob.rb b/lib/yabeda/activejob.rb index 670f847..5354356 100644 --- a/lib/yabeda/activejob.rb +++ b/lib/yabeda/activejob.rb @@ -1,8 +1,8 @@ # frozen_string_literal: true +require "active_support" require "yabeda" require "yabeda/activejob/version" -require "active_support" module Yabeda # Small set of metrics on activejob jobs From 794c25b301f67d1e500c17ac001b57433e8c65b5 Mon Sep 17 00:00:00 2001 From: Andrew Markle Date: Thu, 4 Dec 2025 08:48:46 -0500 Subject: [PATCH 8/9] Fix rubocop --- lib/yabeda/activejob/event_handler.rb | 151 +++++++++++++------------- spec/yabeda/activejob_spec.rb | 10 +- 2 files changed, 83 insertions(+), 78 deletions(-) diff --git a/lib/yabeda/activejob/event_handler.rb b/lib/yabeda/activejob/event_handler.rb index 059fab5..769c0f5 100644 --- a/lib/yabeda/activejob/event_handler.rb +++ b/lib/yabeda/activejob/event_handler.rb @@ -1,105 +1,110 @@ # frozen_string_literal: true -class Yabeda::ActiveJob::EventHandler - def initialize(*event_args) - @event = ActiveSupport::Notifications::Event.new(*event_args) - end +module Yabeda + module ActiveJob + class EventHandler + def initialize(*event_args) + @event = ActiveSupport::Notifications::Event.new(*event_args) + end - def handle_perform - labels = { - activejob: event.payload[:job].class.to_s, - queue: event.payload[:job].queue_name.to_s, - executions: event.payload[:job].executions.to_s, - } - if event.payload[:exception].present? - Yabeda.activejob_failed_total.increment( - labels.merge(failure_reason: event.payload[:exception].first.to_s), - ) - else - Yabeda.activejob_success_total.increment(labels) - end + def handle_perform + labels = { + activejob: event.payload[:job].class.to_s, + queue: event.payload[:job].queue_name.to_s, + executions: event.payload[:job].executions.to_s, + } + if event.payload[:exception].present? + Yabeda.activejob_failed_total.increment( + labels.merge(failure_reason: event.payload[:exception].first.to_s), + ) + else + Yabeda.activejob_success_total.increment(labels) + end - Yabeda.activejob_executed_total.increment(labels) - Yabeda.activejob_runtime.measure(labels, ms2s(event.duration)) - call_after_event_block - end + Yabeda.activejob_executed_total.increment(labels) + Yabeda.activejob_runtime.measure(labels, ms2s(event.duration)) + call_after_event_block + end - def handle_perform_start - labels = common_labels(event.payload[:job]) + def handle_perform_start + labels = common_labels(event.payload[:job]) - job_latency_value = job_latency - Yabeda.activejob_latency.measure(labels, job_latency_value) if job_latency_value.present? - call_after_event_block - end + job_latency_value = job_latency + Yabeda.activejob_latency.measure(labels, job_latency_value) if job_latency_value.present? + call_after_event_block + end - def handle_enqueue - labels = common_labels(event.payload[:job]) + def handle_enqueue + labels = common_labels(event.payload[:job]) - Yabeda.activejob_enqueued_total.increment(labels) + Yabeda.activejob_enqueued_total.increment(labels) - call_after_event_block - end + call_after_event_block + end - def handle_enqueue_at - labels = common_labels(event.payload[:job]) + def handle_enqueue_at + labels = common_labels(event.payload[:job]) - Yabeda.activejob_scheduled_total.increment(labels) + Yabeda.activejob_scheduled_total.increment(labels) - call_after_event_block - end + call_after_event_block + end - def handle_enqueue_all - event.payload[:jobs].each do |job| - labels = common_labels(job) + def handle_enqueue_all + event.payload[:jobs].each do |job| + labels = common_labels(job) - if job.scheduled_at - Yabeda.activejob_scheduled_total.increment(labels) - else - Yabeda.activejob_enqueued_total.increment(labels) + if job.scheduled_at + Yabeda.activejob_scheduled_total.increment(labels) + else + Yabeda.activejob_enqueued_total.increment(labels) + end + end + + call_after_event_block end - end - call_after_event_block - end + private - private - attr_reader :event + attr_reader :event + + def job_latency + return unless (enqueue_time = event.payload[:job].enqueued_at) - def job_latency - if enqueue_time = event.payload[:job].enqueued_at enqueue_time = parse_event_time(enqueue_time) perform_at_time = parse_event_time(event.end) perform_at_time - enqueue_time end - end - def ms2s(milliseconds) - (milliseconds.to_f / 1000).round(3) - end + def ms2s(milliseconds) + (milliseconds.to_f / 1000).round(3) + end - def parse_event_time(time) - case time - when Time then time - when String then Time.parse(time).utc - else - if time > 1e12 - Time.at(ms2s(time)).utc + def parse_event_time(time) + case time + when Time then time + when String then Time.parse(time).utc else - Time.at(time).utc + if time > 1e12 + Time.at(ms2s(time)).utc + else + Time.at(time).utc + end end end - end - def common_labels(job) - Yabeda.default_tags.reverse_merge( - activejob: job.class.to_s, - queue: job.queue_name, - executions: job.executions.to_s, - ) - end + def common_labels(job) + Yabeda.default_tags.reverse_merge( + activejob: job.class.to_s, + queue: job.queue_name, + executions: job.executions.to_s, + ) + end - def call_after_event_block - Yabeda::ActiveJob.after_event_block.call(event) if Yabeda::ActiveJob.after_event_block.respond_to?(:call) + def call_after_event_block + Yabeda::ActiveJob.after_event_block.call(event) if Yabeda::ActiveJob.after_event_block.respond_to?(:call) + end end + end end diff --git a/spec/yabeda/activejob_spec.rb b/spec/yabeda/activejob_spec.rb index c9a57ec..c41afeb 100644 --- a/spec/yabeda/activejob_spec.rb +++ b/spec/yabeda/activejob_spec.rb @@ -197,7 +197,7 @@ end end - context "when jobs are bulk enqueued", skip: !ActiveJob.respond_to?(:perform_all_later), queue_adapter: :test do + context "when jobs are bulk enqueued", queue_adapter: :test, skip: !ActiveJob.respond_to?(:perform_all_later) do it "increments enqueued job counter for all jobs" do expect do ActiveJob.perform_all_later([HelloJob.new, HelloJob.new, LongJob.new]) @@ -213,10 +213,10 @@ it "increments scheduled job counter for scheduled jobs in bulk" do expect do ActiveJob.perform_all_later([ - HelloJob.new.set(wait: 1.hour), - HelloJob.new, - LongJob.new.set(wait: 2.hours), - ]) + HelloJob.new.set(wait: 1.hour), + HelloJob.new, + LongJob.new.set(wait: 2.hours), + ]) end.to increment_yabeda_counter(Yabeda.activejob.scheduled_total) .with_tags(queue: "default", activejob: "HelloJob", executions: "0") .by(1).and( From e7fea9d7140ef224798676d7685db577f5ae4138 Mon Sep 17 00:00:00 2001 From: Andrew Markle Date: Thu, 4 Dec 2025 09:22:58 -0500 Subject: [PATCH 9/9] Fix tests, update changelog, update testing matrix to include rails 8.1 --- .github/workflows/build-release.yml | 2 +- .github/workflows/lint.yml | 4 ++-- .github/workflows/test.yml | 4 ++-- CHANGELOG.md | 3 +++ gemfiles/rails_8.1.gemfile | 8 ++++++++ spec/yabeda/activejob_spec.rb | 14 ++++++++++---- 6 files changed, 26 insertions(+), 9 deletions(-) create mode 100644 gemfiles/rails_8.1.gemfile diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml index ea6a577..123d0dd 100644 --- a/.github/workflows/build-release.yml +++ b/.github/workflows/build-release.yml @@ -9,7 +9,7 @@ jobs: release: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: fetch-depth: 0 # Fetch current tag as annotated. See https://github.com/actions/checkout/issues/290 - uses: ruby/setup-ruby@v1 diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index f6e0d66..c1908bc 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v1 + uses: actions/checkout@v4 - uses: ruby/setup-ruby@v1 with: ruby-version: 3.0.0 @@ -24,4 +24,4 @@ jobs: with: rubocop_version: gemfile rubocop_extensions: rubocop-rails:gemfile rubocop-rspec:gemfile - reporter: github-pr-review # Default is github-pr-check \ No newline at end of file + reporter: github-pr-review # Default is github-pr-check diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7218b3b..491d248 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -17,8 +17,8 @@ jobs: strategy: fail-fast: false matrix: - rails: ["7.0", "7.1", "7.2", "8.0"] - ruby: ["3.1", "3.2", "3.3", "3.4"] + rails: ["7.0", "7.1", "7.2", "8.0", "8.1"] + ruby: ["3.3", "3.4"] container: image: ruby:${{ matrix.ruby }} env: diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a878b7..c0e6778 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## Unreleased +- Add support for newer ActiveJob features such as scheduled jobs and bulk enqueued jobs. https://github.com/Fullscript/yabeda-activejob/pull/24 @lewispb + ## 0.6.0 - 2024-10-29 - Add support for Rails 7.1.4+ - Fix rubocop rules and configure Github actions to run the specs for supported Rails / Ruby versions. diff --git a/gemfiles/rails_8.1.gemfile b/gemfiles/rails_8.1.gemfile new file mode 100644 index 0000000..58ae8b3 --- /dev/null +++ b/gemfiles/rails_8.1.gemfile @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +source "https://rubygems.org" +git_source(:github) { |repo| "https://github.com/#{repo}.git" } + +gem "rails", "~> 8.1.0" + +eval_gemfile "../Gemfile" diff --git a/spec/yabeda/activejob_spec.rb b/spec/yabeda/activejob_spec.rb index c41afeb..17233fc 100644 --- a/spec/yabeda/activejob_spec.rb +++ b/spec/yabeda/activejob_spec.rb @@ -58,10 +58,13 @@ describe "job latency calculation" do # Rails 7.1.4 and above it "measures correct latency from end_time in seconds", queue_adapter: :test do - start_time = Time.now + base_time = Time.now + + # Mock the job's enqueued_at time to be exactly base_time + allow_any_instance_of(HelloJob).to receive(:enqueued_at).and_return(base_time) # rubocop:disable RSpec/AnyInstance # Mock the event end time to simulate 60 seconds later - allow_any_instance_of(ActiveSupport::Notifications::Event).to receive(:end).and_return(1.minute.from_now(start_time).to_f) # rubocop:disable RSpec/AnyInstance + allow_any_instance_of(ActiveSupport::Notifications::Event).to receive(:end).and_return((base_time + 60.seconds).to_f) # rubocop:disable RSpec/AnyInstance expect { HelloJob.perform_later }.to have_enqueued_job.on_queue("default") expect { perform_enqueued_jobs }.to measure_yabeda_histogram(Yabeda.activejob.latency) @@ -71,10 +74,13 @@ # Rails 7.1.3 and below it "measures correct latency from end_time in milliseconds", queue_adapter: :test do - start_time = Time.now + base_time = Time.now + + # Mock the job's enqueued_at time to be exactly base_time + allow_any_instance_of(HelloJob).to receive(:enqueued_at).and_return(base_time) # rubocop:disable RSpec/AnyInstance # Mock the event end time to simulate 60 seconds later (in milliseconds) - allow_any_instance_of(ActiveSupport::Notifications::Event).to receive(:end).and_return(1.minute.from_now(start_time).to_f * 1000) # rubocop:disable RSpec/AnyInstance + allow_any_instance_of(ActiveSupport::Notifications::Event).to receive(:end).and_return((base_time + 60.seconds).to_f * 1000) # rubocop:disable RSpec/AnyInstance expect { HelloJob.perform_later }.to have_enqueued_job.on_queue("default") expect { perform_enqueued_jobs }.to measure_yabeda_histogram(Yabeda.activejob.latency)