From fffc68522f3caa0b630dc4ed8ba14b0e27cd9a0d Mon Sep 17 00:00:00 2001 From: Bret Weinraub Date: Fri, 4 Mar 2022 13:00:51 +0100 Subject: [PATCH] Add command line switch (--exit-after) or Environment varaible (EXIT_AFTER),which causes work to exit after a specific number of jobs, irrespective of success or failure. --- README.md | 4 ++++ lib/delayed/command.rb | 3 +++ lib/delayed/tasks.rb | 1 + lib/delayed/worker.rb | 8 ++++++-- 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c72ed2f6f..ffc46631c 100644 --- a/README.md +++ b/README.md @@ -258,6 +258,10 @@ You can then do the following: # or to run in the foreground RAILS_ENV=production script/delayed_job run --exit-on-complete + # Exit after a specific number of jobs, irrespective of success or failure. + script/delayed_job start --exit-after=1 + env EXIT_AFTER=4 rake jobs:work + **Rails 4:** *replace script/delayed_job with bin/delayed_job* Workers can be running on any computer, as long as they have access to the diff --git a/lib/delayed/command.rb b/lib/delayed/command.rb index 281078242..2e74d2827 100644 --- a/lib/delayed/command.rb +++ b/lib/delayed/command.rb @@ -80,6 +80,9 @@ def initialize(args) # rubocop:disable MethodLength opt.on('--daemon-options a, b, c', Array, 'options to be passed through to daemons gem') do |daemon_options| @daemon_options = daemon_options end + opt.on('--exit-after N', 'Exit after executing N jobs.') do |n| + @options[:exit_after] = n.to_i + end end @args = opts.parse!(args) + (@daemon_options || []) end diff --git a/lib/delayed/tasks.rb b/lib/delayed/tasks.rb index 409ba48f8..7c21cafe8 100644 --- a/lib/delayed/tasks.rb +++ b/lib/delayed/tasks.rb @@ -24,6 +24,7 @@ @worker_options[:sleep_delay] = ENV['SLEEP_DELAY'].to_i if ENV['SLEEP_DELAY'] @worker_options[:read_ahead] = ENV['READ_AHEAD'].to_i if ENV['READ_AHEAD'] + @worker_options[:exit_after] = ENV['EXIT_AFTER'].to_i if ENV['EXIT_AFTER'] end desc "Exit with error status if any jobs older than max_age seconds haven't been attempted yet." diff --git a/lib/delayed/worker.rb b/lib/delayed/worker.rb index 1a352f775..584d9fa50 100644 --- a/lib/delayed/worker.rb +++ b/lib/delayed/worker.rb @@ -22,7 +22,7 @@ class Worker # rubocop:disable ClassLength cattr_accessor :min_priority, :max_priority, :max_attempts, :max_run_time, :default_priority, :sleep_delay, :logger, :delay_jobs, :queues, :read_ahead, :plugins, :destroy_failed_jobs, :exit_on_complete, - :default_log_level + :default_log_level, :exit_after # Named queue into which jobs are enqueued by default cattr_accessor :default_queue_name @@ -131,7 +131,7 @@ def initialize(options = {}) @quiet = options.key?(:quiet) ? options[:quiet] : true @failed_reserve_count = 0 - [:min_priority, :max_priority, :sleep_delay, :read_ahead, :queues, :exit_on_complete].each do |option| + [:min_priority, :max_priority, :sleep_delay, :read_ahead, :queues, :exit_on_complete, :exit_after].each do |option| self.class.send("#{option}=", options[option]) if options.key?(option) end @@ -190,6 +190,7 @@ def start # rubocop:disable CyclomaticComplexity, PerceivedComplexity say format("#{count} jobs processed at %.4f j/s, %d failed", count / @realtime, @result.last) end + break if self.class.exit_after and @total_jobs_run >= self.class.exit_after break if stop? end end @@ -208,6 +209,7 @@ def stop? def work_off(num = 100) success = 0 failure = 0 + @total_jobs_run ||= 0 num.times do case reserve_and_run_one_job @@ -218,6 +220,8 @@ def work_off(num = 100) else break # leave if no work could be done end + @total_jobs_run += 1 + break if self.class.exit_after and @total_jobs_run >= self.class.exit_after break if stop? # leave if we're exiting end