# rufus-scheduler
[](http://travis-ci.org/jmettraux/rufus-scheduler)
[](http://badge.fury.io/rb/rufus-scheduler)
Job scheduler for Ruby (at, cron, in and every jobs).
**Note**: maybe are you looking for the [README of rufus-scheduler 2.x](https://github.com/jmettraux/rufus-scheduler/blob/two/README.rdoc)?
Quickstart:
```ruby
require 'rufus-scheduler'
scheduler = Rufus::Scheduler.new
scheduler.in '3s' do
puts 'Hello... Rufus'
end
scheduler.join
# let the current thread join the scheduler thread
```
Various forms of scheduling are supported:
```ruby
require 'rufus-scheduler'
scheduler = Rufus::Scheduler.new
# ...
scheduler.in '10d' do
# do something in 10 days
end
scheduler.at '2030/12/12 23:30:00' do
# do something at a given point in time
end
scheduler.every '3h' do
# do something every 3 hours
end
scheduler.cron '5 0 * * *' do
# do something every day, five minutes after midnight
# (see "man 5 crontab" in your terminal)
end
# ...
```
## non-features
Rufus-scheduler (out of the box) is an in-process, in-memory scheduler.
It does not persist your schedules. When the process is gone and the scheduler instance with it, the schedules are gone.
## related and similar gems
* [whenever](https://github.com/javan/whenever) - let cron call back your Ruby code, trusted and reliable cron drives your schedule
* [clockwork](https://github.com/tomykaira/clockwork) - rufus-scheduler inspired gem
(please note: rufus-scheduler is not a cron replacement)
## note about the 3.0 line
It's a complete rewrite of rufus-scheduler.
There is no EventMachine-based scheduler anymore.
## Notables changes:
* As said, no more EventMachine-based scheduler
* ```scheduler.every('100') {``` will schedule every 100 seconds (previously, it would have been 0.1s). This aligns rufus-scheduler on Ruby's ```sleep(100)```
* The scheduler isn't catching the whole of Exception anymore, only StandardError
* The error_handler is #on_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 Scheduler #on_pre_trigger and #on_post_trigger callback points
## getting help
So you need help. People can help you, but first help them help you, and don't waste their time. Provide a complete description of the issue. If it works on A but not on B and others have to ask you: "so what is different between A and B" you are wasting everyone's time.
"hello" and "thanks" are not swear words.
Go read [how to report bugs effectively](http://www.chiark.greenend.org.uk/~sgtatham/bugs.html), twice.
Update: [help_help.md](https://gist.github.com/jmettraux/310fed75f568fd731814) might help help you.
### on StackOverflow
Use this [form](http://stackoverflow.com/questions/ask?tags=rufus-scheduler+ruby). It'll create a question flagged "rufus-scheduler" and "ruby".
Here are the [questions tagged rufus-scheduler](http://stackoverflow.com/questions/tagged/rufus-scheduler).
### on IRC
I sometimes haunt #ruote on freenode.net. The channel is not dedicated to rufus-scheduler, so if you ask a question, first mention it's about rufus-scheduler.
Please note that I prefer helping over Stack Overflow because it's more searchable than the ruote IRC archive.
### issues
Yes, issues can be reported in [rufus-scheduler issues](https://github.com/jmettraux/rufus-scheduler/issues), I'd actually prefer bugs in there. If there is nothing wrong with rufus-scheduler, a [Stack Overflow question](http://stackoverflow.com/questions/ask?tags=rufus-scheduler+ruby) is better.
### faq
* [It doesn't work...](http://www.chiark.greenend.org.uk/~sgtatham/bugs.html)
* [I want a refund](http://blog.nodejitsu.com/getting-refunds-on-open-source-projects)
* [Passenger and rufus-scheduler](http://stackoverflow.com/questions/18108719/debugging-rufus-scheduler/18156180#18156180)
* [Passenger and rufus-scheduler (2)](http://stackoverflow.com/questions/21861387/rufus-cron-job-not-working-in-apache-passenger#answer-21868555)
* [Unicorn and rufus-scheduler](https://jkraemer.net/running-rufus-scheduler-in-a-unicorn-rails-app)
## scheduling
Rufus-scheduler supports five kinds of jobs. in, at, every, interval and cron jobs.
Most of the rufus-scheduler examples show block scheduling, but it's also OK to schedule handler instances or handler classes.
### in, at, every, interval, cron
In and at jobs trigger once.
```ruby
require 'rufus-scheduler'
scheduler = Rufus::Scheduler.new
scheduler.in '10d' do
puts "10 days reminder for review X!"
end
scheduler.at '2014/12/24 2000' do
puts "merry xmas!"
end
```
In jobs are scheduled with a time interval, they trigger after that time elapsed. At jobs are scheduled with a point in time, they trigger when that point in time is reached (better to choose a point in the future).
Every, interval and cron jobs trigger repeatedly.
```ruby
require 'rufus-scheduler'
scheduler = Rufus::Scheduler.new
scheduler.every '3h' do
puts "change the oil filter!"
end
scheduler.interval '2h' do
puts "thinking..."
puts sleep(rand * 1000)
puts "thought."
end
scheduler.cron '00 09 * * *' do
puts "it's 9am! good morning!"
end
```
Every jobs try hard to trigger following the frequency they were scheduled with.
Interval jobs, trigger, execute and then trigger again after the interval elapsed. (every jobs time between trigger times, interval jobs time between trigger termination and the next trigger start).
Cron jobs are based on the venerable cron utility (```man 5 crontab```). They trigger following a pattern given in (almost) the same language cron uses.
### #schedule_x vs #x
schedule_in, schedule_at, schedule_cron, etc will return the new Job instance.
in, at, cron will return the new Job instance's id (a String).
```ruby
job_id =
scheduler.in '10d' do
# ...
end
job = scheduler.job(job_id)
# versus
job =
scheduler.schedule_in '10d' do
# ...
end
# also
job =
scheduler.in '10d', :job => true do
# ...
end
```
### #schedule and #repeat
Sometimes it pays to be less verbose.
The ```#schedule``` methods schedules an at, in or cron job. It just decide based on its input. It returns the Job instance.
```ruby
scheduler.schedule '10d' do; end.class
# => Rufus::Scheduler::InJob
scheduler.schedule '2013/12/12 12:30' do; end.class
# => Rufus::Scheduler::AtJob
scheduler.schedule '* * * * *' do; end.class
# => Rufus::Scheduler::CronJob
```
The ```#repeat``` method schedules and returns an EveryJob or a CronJob.
```ruby
scheduler.repeat '10d' do; end.class
# => Rufus::Scheduler::EveryJob
scheduler.repeat '* * * * *' do; end.class
# => Rufus::Scheduler::CronJob
```
(Yes, no combination heres gives back an IntervalJob).
### schedule blocks arguments (job, time)
A schedule block may be given 0, 1 or 2 arguments.
The first argument is "job", it's simple the Job instance involved. It might be useful if the job is to be unscheduled for some reason.
```ruby
scheduler.every '10m' do |job|
status = determine_pie_status
if status == 'burnt' || status == 'cooked'
stop_oven
takeout_pie
job.unschedule
end
end
```
The second argument is "time", it's the time when the job g