From 3e1031cd8620d7d811c8e5b8425ddf9c3b5b3756 Mon Sep 17 00:00:00 2001 From: Vijay Ramesh Date: Wed, 8 Apr 2020 17:20:55 -0700 Subject: [PATCH] Add support for active jobs --- README.md | 16 +++++++++++++++- lib/resque/plugins/job_stats.rb | 34 +++++++++++++++++++++++++++++++++ resque-job-stats.gemspec | 2 ++ test.yml | 6 ++++++ test/test_job_stats.rb | 22 +++++++++++++++++++-- 5 files changed, 77 insertions(+), 3 deletions(-) create mode 100644 test.yml diff --git a/README.md b/README.md index 8a8e405..2ba4688 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,19 @@ class MyJob end ``` +If you are using ActiveJob::Base, you need to include it instead: + +```ruby +class MyActiveJob < ActiveJob::Base + include Resque::Plugins::JobStats + + queue_as :my_job + def perform(*args) + # .. + end +end +``` + And you will have a set of keys starting with `'stats:jobs:my_job'` inside your Resque redis namespace. Alternatively you can include just the metric you wish to record. @@ -140,7 +153,8 @@ If you wish to display only certain metrics, you can filter the metrics accordin * Fork the project * Start a feature/bugfix branch * Commit and push until you are happy with your contribution -* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally. +* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally. +* You can use `docker-compose -f test.yml up` to bring up a redis container needed for the tests to run. * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it. ## Contributers diff --git a/lib/resque/plugins/job_stats.rb b/lib/resque/plugins/job_stats.rb index 651d138..6e94c12 100644 --- a/lib/resque/plugins/job_stats.rb +++ b/lib/resque/plugins/job_stats.rb @@ -10,6 +10,40 @@ module Resque module Plugins module JobStats + + def self.included(base) + # this is all needed to support ActiveJobs + # the main difference is `perform` is an instance method, not a class + # method, and it will not magically call all of our after_ hooks + base.extend Resque::Plugins::JobStats::Performed + base.extend Resque::Plugins::JobStats::Enqueued + base.extend Resque::Plugins::JobStats::Failed + base.extend Resque::Plugins::JobStats::Duration + base.extend Resque::Plugins::JobStats::Timeseries::Enqueued + base.extend Resque::Plugins::JobStats::Timeseries::Performed + base.extend Resque::Plugins::JobStats::History + self.measured_jobs << base + + if base.ancestors.map(&:to_s).include?("ActiveJob::Base") + # ActiveJob does not magically call all of our after_perform_ABC methods like resque does + base.after_perform do |job| + job.class.methods.select do |meth| + meth.to_s.start_with?("after_perform_") + end.each do |meth| + job.class.send(meth) + end + end + + base.after_enqueue do |job| + job.class.methods.select do |meth| + meth.to_s.start_with?("after_enqueue_") + end.each do |meth| + job.class.send(meth) + end + end + end + end + include Resque::Plugins::JobStats::Performed include Resque::Plugins::JobStats::Enqueued include Resque::Plugins::JobStats::Failed diff --git a/resque-job-stats.gemspec b/resque-job-stats.gemspec index ac330b1..19abd0f 100644 --- a/resque-job-stats.gemspec +++ b/resque-job-stats.gemspec @@ -34,4 +34,6 @@ Gem::Specification.new do |s| s.add_development_dependency "minitest", '~> 5.0' s.add_development_dependency "timecop", '~> 0.6' s.add_development_dependency 'rack-test', '>= 0' + s.add_development_dependency 'activejob', '>= 5.1.7' + end diff --git a/test.yml b/test.yml new file mode 100644 index 0000000..c44bee7 --- /dev/null +++ b/test.yml @@ -0,0 +1,6 @@ +version: '2.2' +services: + redis: + image: redis + ports: + - "6379:6379" \ No newline at end of file diff --git a/test/test_job_stats.rb b/test/test_job_stats.rb index 1832fe8..29806f0 100644 --- a/test/test_job_stats.rb +++ b/test/test_job_stats.rb @@ -1,5 +1,5 @@ require 'helper' - +require 'active_job' class BaseJob @queue = :test @@ -35,6 +35,14 @@ class CustomHistJob < BaseJob @histories_recordable = 5 end +class InstanceMethodJob < ActiveJob::Base + include Resque::Plugins::JobStats + queue_as :test + def perform(sleep_time=0.01) + sleep sleep_time + end +end + class TestResqueJobStats < MiniTest::Unit::TestCase def setup @@ -142,7 +150,7 @@ def test_enqueue_timeseries end def test_measured_jobs - assert_equal [SimpleJob], Resque::Plugins::JobStats.measured_jobs + assert_equal [SimpleJob, InstanceMethodJob], Resque::Plugins::JobStats.measured_jobs end def test_history @@ -205,4 +213,14 @@ def test_failure_history assert ! FailJob.job_histories.first["success"] assert_equal "fail", FailJob.job_histories.first["exception"]["name"] end + + def test_instance_method_jobs_perform + assert_equal 'stats:jobs:InstanceMethodJob:performed', InstanceMethodJob.jobs_performed_key + InstanceMethodJob.jobs_performed = 0 + 3.times do + InstanceMethodJob.perform_now + @worker.work(0) + end + assert_equal 3, InstanceMethodJob.jobs_performed + end end