README.md in rufus-scheduler-3.0.2 vs README.md in rufus-scheduler-3.0.3

- old
+ new

@@ -800,10 +800,14 @@ ### Scheduler#shutdown(:kill) Kills all the job (threads) and then shuts the scheduler down. Radical. +### Scheduler#down? + +Returns true if the scheduler has been shut down. + ### Scheduler#join Let's the current thread join the scheduling thread in rufus-scheduler. The thread comes back when the scheduler gets shut down. ### Scheduler#threads @@ -962,10 +966,12 @@ The idea is to guarantee only one scheduler (in a group of scheduler sharing the same lockfile) is running. This is useful in environments where the Ruby process holding the scheduler gets started multiple times. +If the lockfile mechanism here is not sufficient, you can plug your custom mechanism. It's explained in [advanced lock schemes](#advanced-lock-schemes) below. + ### :max_work_threads In rufus-scheduler 2.x, by default, each job triggering received its own, new, hthread of execution. In rufus-scheduler 3.x, execution happens in a work thread and the max work thread count defaults to 28. One can set this maximum value when starting the scheduler. @@ -1002,10 +1008,57 @@ ```ruby Rufus::Scheduler.s.every '10s' { puts "hello, world!" } ``` +## advanced lock schemes + +As seen above, rufus-scheduler proposes the :lockfile system out of the box. If in a group of schedulers only one is supposed to run, the lockfile mecha prevents schedulers that have not set/created the lockfile from running. + +There are situation where this is not sufficient. + +By overriding #lock and #unlock, one can customize how his schedulers lock. + +This example was provided by [Eric Lindvall](https://github.com/eric): + +```ruby +class ZookeptScheduler < Rufus::Scheduler + + def initialize(zookeeper, opts={}) + @zk = zookeeper + super(opts) + end + + def lock + @zk_locker = @zk.exclusive_locker('scheduler') + @zk_locker.lock # returns true if the lock was acquired, false else + end + + def unlock + @zk_locker.unlock + end + + def confirm_lock + return false if down? + @zk_locker.assert! + rescue ZK::Exceptions::LockAssertionFailedError => e + # we've lost the lock, shutdown (and return false to at least prevent + # this job from triggering + shutdown + false + end +end +``` + +This uses a [zookeeper](http://zookeeper.apache.org/) to make sure only one scheduler in a group of distributed schedulers runs. + +The methods #lock and #unlock are overriden and #confirm_lock is provided, +to make sure that the lock is still valid. + +The #confirm_lock method is called right before a job triggers (if it is provided). The more generic callback #on_pre_trigger is called right after #confirm_lock. + + ## parsing cronlines and time strings Rufus::Scheduler provides a class method ```.parse``` to parse time durations and cron strings. It's what it's using when receiving schedules. One can use it diectly (no need to instantiate a Scheduler). ```ruby @@ -1049,9 +1102,61 @@ # => { :m => 1, :s => 2, :ms => 127 } Rufus::Scheduler.to_duration_hash(62.127, :drop_seconds => true) # => { :m => 1 } ``` + +### cronline notations specific to rufus-scheduler + +#### first Monday, last Sunday et al + +To schedule something at noon every first Monday of the month: + +```ruby +scheduler.cron('00 12 * * mon#1') do + # ... +end +``` + +To schedule something at noon the last Sunday of every month: + +```ruby +scheduler.cron('00 12 * * sun#-1') do + # ... +end +# +# OR +# +scheduler.cron('00 12 * * sun#L') do + # ... +end +``` + +Such cronlines can be tested with scripts like: + +```ruby +require 'rufus-scheduler' + +Time.now + # => 2013-10-26 07:07:08 +0900 +Rufus::Scheduler.parse('* * * * mon#1').next_time + # => 2013-11-04 00:00:00 +0900 +``` + +#### L (last day of month) + +L can be used in the "day" slot: + +In this example, the cronline is supposed to trigger every last day of the month at noon: + +```ruby +require 'rufus-scheduler' +Time.now + # => 2013-10-26 07:22:09 +0900 +Rufus::Scheduler.parse('00 12 L * *').next_time + # => 2013-10-31 12:00:00 +0900 +``` + ## a note about timezones Cron schedules and at schedules support the specification of a timezone.