README.md in rufus-scheduler-3.6.0 vs README.md in rufus-scheduler-3.7.0
- old
+ new
@@ -22,11 +22,15 @@
scheduler.in '3s' do
puts 'Hello... Rufus'
end
scheduler.join
+ #
# let the current thread join the scheduler thread
+ #
+ # (please note that this join should be removed when scheduling
+ # in a web application (Rails and friends) initializer)
```
(run with `ruby quickstart.rb`)
Various forms of scheduling are supported:
```ruby
@@ -71,10 +75,11 @@
## related and similar gems
* [Whenever](https://github.com/javan/whenever) - let cron call back your Ruby code, trusted and reliable cron drives your schedule
+* [ruby-clock](https://github.com/jjb/ruby-clock) - a clock process / job scheduler for Ruby
* [Clockwork](https://github.com/Rykian/clockwork) - rufus-scheduler inspired gem
* [Crono](https://github.com/plashchynski/crono) - an in-Rails cron scheduler
* [PerfectSched](https://github.com/treasure-data/perfectsched) - highly available distributed cron built on [Sequel](https://sequel.jeremyevans.net) and more
(please note: rufus-scheduler is not a cron replacement)
@@ -98,12 +103,12 @@
* ```scheduler.every('100') {``` will schedule every 100 seconds (previously, it would have been 0.1s). This aligns rufus-scheduler with Ruby's ```sleep(100)```
* The scheduler isn't catching the whole of Exception anymore, only StandardError
* The error_handler is [#on_error](#rufusscheduleron_errorjob-error) (instead of #on_exception), by default it now prints the details of the error to $stderr (used to be $stdout)
* Rufus::Scheduler::TimeOutError renamed to Rufus::Scheduler::TimeoutError
* Introduction of "interval" jobs. Whereas "every" jobs are like "every 10 minutes, do this", interval jobs are like "do that, then wait for 10 minutes, then do that again, and so on"
-* Introduction of a :lockfile => true/filename mechanism to prevent multiple schedulers from executing
-* "discard_past" is on by default. If the scheduler (its host) sleeps for 1 hour and a ```every '10m'``` job is on, it will trigger once at wakeup, not 6 times (discard_past was false by default in rufus-scheduler 2.x). No intention to re-introduce ```:discard_past => false``` in 3.0 for now.
+* Introduction of a lockfile: true/filename mechanism to prevent multiple schedulers from executing
+* "discard_past" is on by default. If the scheduler (its host) sleeps for 1 hour and a `every '10m'` job is on, it will trigger once at wakeup, not 6 times (discard_past was false by default in rufus-scheduler 2.x). No intention to re-introduce `discard_past: false` in 3.0 for now.
* Introduction of Scheduler #on_pre_trigger and #on_post_trigger callback points
## getting help
@@ -371,10 +376,27 @@
While paused, the scheduler still accepts schedules, but no schedule will get triggered as long as #resume isn't called.
## job options
+### :name => string
+
+Sets the name of the job.
+
+```ruby
+scheduler.cron '*/15 8 * * *', name: 'Robert' do |job|
+ puts "A, it's #{Time.now} and my name is #{job.name}"
+end
+
+job1 =
+ scheduler.schedule_cron '*/30 9 * * *', n: 'temporary' do |job|
+ puts "B, it's #{Time.now} and my name is #{job.name}"
+ end
+# ...
+job1.name = 'Beowulf'
+```
+
### :blocking => true
By default, jobs are triggered in their own, new threads. When `:blocking => true`, the job is triggered in the scheduler thread (a new thread is not created). Yes, while a blocking job is running, the scheduler is not scheduling.
### :overlap => false
@@ -458,11 +480,10 @@
s.every '3s', :first => :now do
n = Time.now; p [ :in, n, n.to_f ]
end
s.join
-
```
that'll output something like:
```
@@ -755,13 +776,13 @@
job = scheduler.schedule_in('10d', :tag => 'hello') do; end
job.tags
# => [ 'hello' ]
```
-### []=, [], key? and keys
+### []=, [], key?, has_key?, keys, values, and entries
-Threads have thread-local variables. Rufus-scheduler jobs have job-local variables.
+Threads have thread-local variables, similarly Rufus-scheduler jobs have job-local variables. Those are more like a dict with thread-safe access.
```ruby
job =
@scheduler.schedule_every '1s' do |job|
job[:timestamp] = Time.now.to_f
@@ -772,18 +793,34 @@
sleep 3.6
job[:counter]
# => 3
-job.key?(:timestamp)
- # => true
-job.keys
- # => [ :timestamp, :counter ]
+job.key?(:timestamp) # => true
+job.has_key?(:timestamp) # => true
+job.keys # => [ :timestamp, :counter ]
```
-Job-local variables are thread-safe.
+Locals can be set at schedule time:
+```ruby
+job0 =
+ @scheduler.schedule_cron '*/15 12 * * *', locals: { a: 0 } do
+ # ...
+ end
+job1 =
+ @scheduler.schedule_cron '*/15 13 * * *', l: { a: 1 } do
+ # ...
+ end
+```
+One can fetch the Hash directly with `Job#locals`. Of course, direct manipulation is not thread-safe.
+```ruby
+job.locals.entries do |k, v|
+ p "#{k}: #{v}"
+end
+```
+
### call
Job instances have a #call method. It simply calls the scheduled block or callable immediately.
```ruby
@@ -961,10 +998,14 @@
### Scheduler#shutdown(:wait)
Shuts down the scheduler, waits (blocks) until all the jobs cease running.
+### Scheduler#shutdown(wait: n)
+
+Shuts down the scheduler, waits (blocks) at most n seconds until all the jobs cease running. (Jobs are killed after n seconds have elapsed).
+
### Scheduler#shutdown(:kill)
Kills all the job (threads) and then shuts the scheduler down. Radical.
### Scheduler#down?
@@ -983,10 +1024,12 @@
### Scheduler#join
Lets the current thread join the scheduling thread in rufus-scheduler. The thread comes back when the scheduler gets shut down.
+`#join` is mostly used in standalone scheduling script (or tiny one file examples). Calling `#join` from a web application initializer will probably hijack the main thread and prevent the web application from being served. Do not put a `#join` in such a web application initializer file.
+
### Scheduler#threads
Returns all the threads associated with the scheduler, including the scheduler thread itself.
### Scheduler#work_threads(query=:all/:active/:vacant)
@@ -1095,12 +1138,14 @@
"err#{error.object_id} #{i}: #{line}")
end
end
```
-## Rufus::Scheduler #on_pre_trigger and #on_post_trigger callbacks
+## Callbacks
+### Rufus::Scheduler #on_pre_trigger and #on_post_trigger callbacks
+
One can bind callbacks before and after jobs trigger:
```ruby
s = Rufus::Scheduler.new
@@ -1119,10 +1164,25 @@
The ```trigger_time``` is the time at which the job triggers. It might be a bit before ```Time.now```.
Warning: these two callbacks are executed in the scheduler thread, not in the work threads (the threads where the job execution really happens).
+### Rufus::Scheduler#around_trigger
+
+One can create an around callback which will wrap a job:
+
+```ruby
+def s.around_trigger(job)
+ t = Time.now
+ puts "Starting job #{job.id}..."
+ yield
+ puts "job #{job.id} finished in #{Time.now-t} seconds."
+end
+```
+
+The around callback is executed in the thread.
+
### Rufus::Scheduler#on_pre_trigger as a guard
Returning ```false``` in on_pre_trigger will prevent the job from triggering. Returning anything else (nil, -1, true, ...) will let the job trigger.
Note: your business logic should go in the scheduled block itself (or the scheduled instance). Don't put business logic in on_pre_trigger. Return false for admin reasons (backend down, etc), not for business reasons that are tied to the job itself.
@@ -1572,9 +1632,11 @@
require 'rufus-scheduler'
s = Rufus::Scheduler.singleton
return if defined?(Rails::Console) || Rails.env.test? || File.split($0).last == 'rake'
+# return if $PROGRAM_NAME.include?('spring')
+ # see https://github.com/jmettraux/rufus-scheduler/issues/186
# do not schedule when Rails is run from its console, for a test/spec, or
# from a Rake task
s.every '1m' do