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.