From 32f76f6a8b29da1bff4f8db1f96dcd84abcec9cf Mon Sep 17 00:00:00 2001 From: Dan Buch Date: Tue, 11 Feb 2014 10:01:12 -0500 Subject: [PATCH 1/9] Backporting signal handling while "sleeping" from #352 --- .rubocop.yml | 2 +- lib/resque/scheduler.rb | 30 +++++++++++++++++++----------- test/cli_test.rb | 17 ----------------- 3 files changed, 20 insertions(+), 29 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index eb1fe510..3b54d9dd 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -18,7 +18,7 @@ CaseEquality: Enabled: false ClassLength: - Max: 318 + Max: 325 ClassVars: Enabled: false diff --git a/lib/resque/scheduler.rb b/lib/resque/scheduler.rb index 94af78d7..f0a09586 100644 --- a/lib/resque/scheduler.rb +++ b/lib/resque/scheduler.rb @@ -129,7 +129,6 @@ def run log! e.message end end - handle_signals poll_sleep end @@ -385,16 +384,7 @@ def unschedule_job(name) def poll_sleep handle_shutdown do begin - begin - @sleeping = true - sleep poll_sleep_amount - @sleeping = false - rescue Interrupt - if @shutdown - Resque.clean_schedules - release_master_lock! - end - end + poll_sleep_loop ensure @sleeping = false end @@ -402,6 +392,24 @@ def poll_sleep true end + def poll_sleep_loop + @sleeping = true + start = Time.now + loop do + break if (Time.now - start) >= poll_sleep_amount + begin + sleep 0.01 + handle_signals + rescue Interrupt + if @shutdown + Resque.clean_schedules + release_master_lock! + end + break + end + end + end + # Sets the shutdown flag, clean schedules and exits if sleeping def shutdown return if @shutdown diff --git a/test/cli_test.rb b/test/cli_test.rb index 1c624549..e22f3fed 100644 --- a/test/cli_test.rb +++ b/test/cli_test.rb @@ -105,27 +105,10 @@ def new_cli(argv = [], env = {}) cli.pre_run end - test 'initializes dynamic from the env' do - cli = new_cli([], { 'DYNAMIC_SCHEDULE' => '1' }) - assert_equal('flurb', cli.send(:options)[:dynamic]) - end - test 'defaults to nil dynamic' do assert_equal(nil, new_cli.send(:options)[:dynamic]) end - test 'accepts dynamic via -D' do - cli = new_cli(%w(-D)) - cli.parse_options - assert_equal(true, cli.send(:options)[:dynamic]) - end - - test 'accepts dynamic via --dynamic-schedule' do - cli = new_cli(%w(--dynamic-schedule)) - cli.parse_options - assert_equal(true, cli.send(:options)[:dynamic]) - end - test 'initializes env from the env' do cli = new_cli([], { 'RAILS_ENV' => 'flurb' }) assert_equal('flurb', cli.send(:options)[:env]) From 3cd454b35dfb7eb522d00f31b34418d71a1a7aba Mon Sep 17 00:00:00 2001 From: Dan Buch Date: Wed, 12 Feb 2014 08:32:25 -0500 Subject: [PATCH 2/9] Preparing for 2.5.3 release --- HISTORY.md | 3 +++ lib/resque_scheduler/version.rb | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index eadf6607..712699f8 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,8 @@ # Resque Scheduler History / ChangeLog / Release Notes +## 2.5.3 (2014-02-12) +* Handling signals during poll sleep + ## 2.5.2 (2014-02-11) * Pinning down dependency versions more tightly diff --git a/lib/resque_scheduler/version.rb b/lib/resque_scheduler/version.rb index e7d087d5..d1d92636 100644 --- a/lib/resque_scheduler/version.rb +++ b/lib/resque_scheduler/version.rb @@ -1,5 +1,5 @@ # vim:fileencoding=utf-8 module ResqueScheduler - VERSION = '2.5.2' + VERSION = '2.5.3' end From b47043076dab2f279b9c799e5f67c6b019101c71 Mon Sep 17 00:00:00 2001 From: Dan Buch Date: Thu, 13 Feb 2014 10:16:06 -0500 Subject: [PATCH 3/9] Adjusting some documentation around rake task, cli, env vars [ci skip] --- README.md | 72 +++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 54 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 9917d905..deb32c32 100644 --- a/README.md +++ b/README.md @@ -55,13 +55,12 @@ Adding the resque:scheduler rake task: require 'resque_scheduler/tasks' ``` -There are three things `resque-scheduler` needs to know about in order to do -it's jobs: the schedule, where redis lives, and which queues to use. The -easiest way to configure these things is via the rake task. By default, -`resque-scheduler` depends on the "resque:setup" rake task. Since you -probably already have this task, lets just put our configuration there. -`resque-scheduler` pretty much needs to know everything `resque` needs -to know. +### Rake integration + +By default, `resque-scheduler` depends on the "resque:setup" rake task. +Since you probably already have this task, lets just put our +configuration there. `resque-scheduler` pretty much needs to know +everything `resque` needs to know. ```ruby # Resque tasks @@ -82,7 +81,7 @@ namespace :resque do # When dynamic is set to true, the scheduler process looks for # schedule changes and applies them on the fly. # Note: This feature is only available in >=2.0.0. - #Resque::Scheduler.dynamic = true + # Resque::Scheduler.dynamic = true # The schedule doesn't need to be stored in a YAML, it just needs to # be a hash. YAML is usually the easiest. @@ -98,21 +97,58 @@ namespace :resque do end ``` -The scheduler process is just a rake task which is responsible for both -queueing items from the schedule and polling the delayed queue for items -ready to be pushed on to the work queues. For obvious reasons, this process -never exits. +The scheduler rake task is responsible for both queueing items from the +schedule and polling the delayed queue for items ready to be pushed on +to the work queues. For obvious reasons, this process never exits. - $ rake resque:scheduler +``` bash +rake resque:scheduler +``` or, if you want to load the environment first: - $ rake environment resque:scheduler +``` bash +rake environment resque:scheduler +``` + + +### Standalone Executable + +The scheduler may also be run via a standalone `resque-scheduler` +executable, which will be available once the gem is installed. + +``` bash +# Get some help +resque-scheduler --help +``` + +The executable accepts options via option flags as well as via +[environment variables](#environment-variables). + +### Environment Variables + +Both the Rake task and standalone executable support the following +environment variables: + +* `APP_NAME` - Application name used in procline (`$0`) (default empty) +* `BACKGROUND` - [Run in the background](#running-in-the-background) if +non-empty (via `Process.daemon`, if supported) (default `false`) +* `DYNAMIC_SCHEDULE` - Enables [dynamic scheduling](#dynamic-schedules) +if non-empty (default `false`) +* `RAILS_ENV` - Environment to use in procline (`$0`) (default empty) +* `INITIALIZER_PATH` - Path to a Ruby file that will be loaded *before* +requiring `resque` and `resque/scheduler` (default empty). +* `RESQUE_SCHEDULER_INTERVAL` - Interval in seconds for checking if a +scheduled job must run (coerced with `Kernel#Float()`) (default `5`) +* `LOGFILE` - Log file name (default empty, meaning `$stdout`) +* `LOGFORMAT` - Log output format to use (either `'text'` or `'json'`, +default `'text'`) +* `PIDFILE` - If non-empty, write process PID to file (default empty) +* `QUIET` or `MUTE` - Silence most output if non-empty (equivalent to +a level of `Logger::FATAL`, default `false`) +* `VERBOSE` - Maximize log verbosity if non-empty (equivalent to a level +of `Logger::DEBUG`, default `false`) -Supported environment variables are `VERBOSE` and `MUTE`. If either is set to -any nonempty value, they will take effect. `VERBOSE` simply dumps more output -to stdout. `MUTE` does the opposite and silences all output. `MUTE` -supersedes `VERBOSE`. ### Resque Pool integration From b40c2304599f289af3e606d7a65c61dac82419f4 Mon Sep 17 00:00:00 2001 From: Dan Buch Date: Sun, 16 Feb 2014 18:59:08 -0500 Subject: [PATCH 4/9] Ensuring lock #timeout= behavior is consistent based on locked state Closes #299 --- lib/resque/scheduler/lock/resilient.rb | 4 ++++ test/scheduler_locking_test.rb | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/lib/resque/scheduler/lock/resilient.rb b/lib/resque/scheduler/lock/resilient.rb index 36a44cb0..920bfca8 100644 --- a/lib/resque/scheduler/lock/resilient.rb +++ b/lib/resque/scheduler/lock/resilient.rb @@ -20,6 +20,10 @@ def locked? ).to_i == 1 end + def timeout=(t) + @timeout = t if locked? + end + private def locked_sha(refresh = false) diff --git a/test/scheduler_locking_test.rb b/test/scheduler_locking_test.rb index d746e60e..33e20d75 100644 --- a/test/scheduler_locking_test.rb +++ b/test/scheduler_locking_test.rb @@ -238,5 +238,25 @@ def lock_is_not_held(lock) assert Resque.redis.ttl(@lock.key) <= 10, "TTL should not have been updated" end + + test 'setting the lock timeout changes the key TTL if we hold it' do + @lock.acquire! + + @lock.timeout = 120 + ttl = Resque.redis.ttl(@lock.key) + assert_send [ttl, :>, 100] + + @lock.timeout = 180 + ttl = Resque.redis.ttl(@lock.key) + assert_send [ttl, :>, 120] + end + + test 'setting the lock timeout is a noop if not held' do + @lock.acquire! + @lock.timeout = 100 + @lock.stubs(:locked?).returns(false) + @lock.timeout = 120 + assert_equal 100, @lock.timeout + end end end From 88da674c7a5d85cfe61ad7c28b3aa7f772c2c09a Mon Sep 17 00:00:00 2001 From: Dan Buch Date: Sun, 16 Feb 2014 20:06:38 -0500 Subject: [PATCH 5/9] Bumping to v2.5.4 as we've hit the milestone --- lib/resque_scheduler/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/resque_scheduler/version.rb b/lib/resque_scheduler/version.rb index d1d92636..241c0f71 100644 --- a/lib/resque_scheduler/version.rb +++ b/lib/resque_scheduler/version.rb @@ -1,5 +1,5 @@ # vim:fileencoding=utf-8 module ResqueScheduler - VERSION = '2.5.3' + VERSION = '2.5.4' end From 492c1d27392c52af68f6bc38d065d7371eb7f6dc Mon Sep 17 00:00:00 2001 From: Dan Buch Date: Sun, 16 Feb 2014 21:19:21 -0500 Subject: [PATCH 6/9] TRIVIAL: updating commented-out every example Closes #186 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index deb32c32..a44f170f 100644 --- a/README.md +++ b/README.md @@ -251,7 +251,7 @@ CancelAbandonedOrders: queue_documents_for_indexing: cron: "0 0 * * *" # you can use rufus-scheduler "every" syntax in place of cron if you prefer - # every: 1h + # every: 1hr # By default the job name (hash key) will be taken as worker class name. # If you want to have a different job name and class name, provide the 'class' option class: "QueueDocuments" From 117506ac0bf655647f8e0c343c7174f4823ea26f Mon Sep 17 00:00:00 2001 From: Dan Buch Date: Sun, 16 Feb 2014 21:21:45 -0500 Subject: [PATCH 7/9] TRIVIAL: un-derping my derp about every Closes #186 for realsies :smiley_cat: [ci skip] --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a44f170f..deb32c32 100644 --- a/README.md +++ b/README.md @@ -251,7 +251,7 @@ CancelAbandonedOrders: queue_documents_for_indexing: cron: "0 0 * * *" # you can use rufus-scheduler "every" syntax in place of cron if you prefer - # every: 1hr + # every: 1h # By default the job name (hash key) will be taken as worker class name. # If you want to have a different job name and class name, provide the 'class' option class: "QueueDocuments" From 5d0475df1c919d7d2708ab3c9c95d7885749dd2e Mon Sep 17 00:00:00 2001 From: Dan Buch Date: Sun, 16 Feb 2014 22:28:31 -0500 Subject: [PATCH 8/9] Only showing link to job with args if job is present Fixes #359 --- lib/resque_scheduler/server/views/delayed.erb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/resque_scheduler/server/views/delayed.erb b/lib/resque_scheduler/server/views/delayed.erb index 88fb0243..2af2a596 100644 --- a/lib/resque_scheduler/server/views/delayed.erb +++ b/lib/resque_scheduler/server/views/delayed.erb @@ -40,7 +40,11 @@ <% end %> <%= h(job['args'].inspect) if job && delayed_timestamp_size == 1 %> - All schedules + + <% if job %> + All schedules + <% end %> + <% end %> From a5cd5aa638c64c2fd5d4fd588c1e773454cd9cf7 Mon Sep 17 00:00:00 2001 From: Dan Buch Date: Mon, 17 Feb 2014 07:58:37 -0500 Subject: [PATCH 9/9] Updating HISTORY for 2.5.4 --- HISTORY.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/HISTORY.md b/HISTORY.md index 712699f8..9aa9331e 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,8 @@ # Resque Scheduler History / ChangeLog / Release Notes +## 2.5.4 (2014-02-17) +* Documentation updates + ## 2.5.3 (2014-02-12) * Handling signals during poll sleep