Coder Social home page Coder Social logo

kjwierenga / rufus-scheduler Goto Github PK

View Code? Open in Web Editor NEW

This project forked from jmettraux/rufus-scheduler

1.0 3.0 0.0 328 KB

scheduler for Ruby (at, in, cron and every jobs)

Home Page: http://rufus.rubyforge.org/rufus-scheduler/

License: MIT License

rufus-scheduler's Introduction

rufus-scheduler

rufus-scheduler is a Ruby gem for scheduling pieces of code (jobs). It understands running a job AT a certain time, IN a certain time, EVERY x time or simply via a CRON statement.

rufus-scheduler is no replacement for cron/at since it runs inside of Ruby.

alternatives / complements

A list of related Ruby projects :

github.com/javan/whenever github.com/yakischloba/em-timers/

More like complements :

github.com/mojombo/chronic/ github.com/hpoydar/chronic_duration

installation

sudo gem install rufus-scheduler

usage

The usage is similar to the one of the old rufus-scheduler. There are a few differences though.

require 'rubygems'
require 'rufus/scheduler'

scheduler = Rufus::Scheduler.start_new

scheduler.in '20m' do
  puts "order ristretto"
end

scheduler.at 'Thu Mar 26 07:31:43 +0900 2009' do
  puts 'order pizza'
end

scheduler.cron '0 22 * * 1-5' do
  # every day of the week at 00:22
  puts 'activate security system'
end

scheduler.every '5m' do
  puts 'check blood pressure'
end

# ...

scheduler.stop

This code summons a plain version of the scheduler, this can be made more explicit via :

scheduler = Rufus::Scheduler::PlainScheduler.start_new

This PlainScheduler accepts a :thread_name option :

scheduler = Rufus::Scheduler::PlainScheduler.start_new(:thread_name => 'my scheduler')

might be helpful when tracking threads.

Note that is there is EventMachine present and running,

scheduler = Rufus::Scheduler.start_new

will return an instance of Rufus::Scheduler::EmScheduler (leveraging EventMachine).

block parameters

Scheduled blocks accept 0 or 1 parameter (this unique parameter is the job instance itself).

scheduler.every '5m' do
  puts 'check blood pressure'
end
scheduler.every '1y' do |job|
  puts "check cholesterol levels (#{job.job_id})"
end

See the class Job for more details :

rufus.rubyforge.org/rufus-scheduler/classes/Rufus/Scheduler/Job.html

the time strings understood by rufus-scheduler

require 'rubygems'
require 'rufus/scheduler'

p Rufus.parse_time_string '500'      # => 0.5
p Rufus.parse_time_string '1000'     # => 1.0
p Rufus.parse_time_string '1h'       # => 3600.0
p Rufus.parse_time_string '1h10s'    # => 3610.0
p Rufus.parse_time_string '1w2d'     # => 777600.0

p Rufus.to_time_string 60              # => "1m"
p Rufus.to_time_string 3661            # => "1h1m1s"
p Rufus.to_time_string 7 * 24 * 3600   # => "1w"

:blocking

Jobs will, by default, trigger in their own thread. This is usually desirable since one expects the scheduler to continue scheduling even if a job is currently running.

Jobs scheduled with the :blocking parameter will run in the thread of the scheduler, blocking it.

scheduler.in '20m', :blocking => true do
  puts "order ristretto"
  sleep 2 * 60
end
scheduler.in '21m' do
  puts "order espresso"
end

Hence, our espresso wil come in 22 minutes instead of 21.

'every' jobs and :first_at / :first_in

This job will execute every 3 days, but first time will be in 5 days from now :

scheduler.every '3d', :first_in => '5d' do
  # do something
end

This job will execute every 3 days, starting from Christmas Eve at noon :

scheduler.every '3d', :first_at => '2009/12/24 12:00' do
  # do something
end

The chronic gem may help (chronic.rubyforge.org/) :

require 'chronic' # sudo gem install chronic

scheduler.every '3h', :first_at => Chronic.parse('this tuesday 5:00') do
  # do something starting this tueday
end

self unschedule for 'cron' and 'every' jobs

'at' and 'in' jobs fire once only. 'cron' and 'every' jobs do fire repeatedly, so it might be useful to stop them.

scheduler.every '3d' do |job|
  l = determine_crop_maturity_level()
  if l >= 7
    puts "crop is ready."
    job.unschedule
  else
    puts "crop not yet ready..."
  end
end

In this example, the 'every' job will unschedule itself when the crop is ready.

schedulables

Sometimes passing a block isn't that convenient :

class JobThing
  def initialize (relevant_info)
    @ri = relevant_info
  end
  def call (job)
    do_something_about_it
  end
end

# ...

scheduler.in '3d', JobThing.new('http://news.example.com/data_xyz')
scheduler.in '1w', JobThing.new('http://news.example.com/data_abc'), :timeout => '1d'

rufus-scheduler accepts anything that responds to a call method with a unique parameter (it will pass the job) as a 'schedulable'.

looking up jobs

scheduler.jobs
  # returns a map job_id => job of at/in/every jobs

scheduler.cron_jobs
  # idem for cron jobs

scheduler.all_jobs
  # idem but for every/at/in/cron jobs (all of them)

scheduler.find_by_tag(t)
  # returns all the jobs with a given tag (passed at schedule time with :tags)

unscheduling jobs

The 'scheduling' methods always return an instance of Rufus::Scheduler::Job. This object can be used for unscheduling :

job = scheduler.in '2d', :tags => 'admin' do
  run_backlog_cleaning()
end

# later ...

job.unschedule
  # or
scheduler.unschedule(job.job_id)

tags

You can specify tags at schedule time :

scheduler.in '2d', :tags => 'admin' do
  run_backlog_cleaning()
end
scheduler.every '3m', :tags => 'production' do
  check_order_log()
end

And later query the scheduler for those jobs :

admin_jobs = scheduler.find_by_tag('admin')
production_jobs = scheduler.find_by_tag('production')

timeout

One can specify a timeout for the triggering of a job.

scheduler.every '2d', :timeout => '40m' do
  begin
    run_backlog_cleaning()
  rescue Rufus::Scheduler::TimeOutError => toe
    # timeout occurred
  end
end

This job will run every two days. If a run takes more than 40 minutes it will timeout (its thread will receive a TimeOutError).

This timeout feature relies on an 'in' job scheduled at the moment the main job gets triggered, hence the '40m' time string format.

exceptions in jobs

By default, when exception occur when a job performs, the error message will be output to the STDOUT.

It's easy to customize that behaviour :

scheduler = Rufus::Scheduler::PlainScheduler.start_new
  # or
#scheduler = Rufus::Scheduler::EmScheduler.start_new

def scheduler.handle_exception (job, exception)
  puts "job #{job.job_id} caught exception '#{exception}'"
end

For backward compatibility, overriding #log_exception is still OK :

def scheduler.log_exception (exception)
  puts "caught exception '#{exception}'"
end

Note that an every job or a cron job will stay scheduled even if it experiences an exception.

frequency

The default frequency for the scheduler is 0.330 seconds. This means that the usual scheduler implementation will wake up, trigger jobs that are to be triggered and then go back to sleep for 0.330 seconds. Note that this doesn't mean that the scheduler will wake up very 0.330 seconds (checking and triggering do take time).

You can set a different frequency when starting / initializing the scheduler :

require 'rubygems'
require 'rufus/scheduler'

scheduler = Rufus::Scheduler.start_new(:frequency => 60.0)
  # for a lazy scheduler that only wakes up every 60 seconds

usage with EventMachine

rufus-scheduler 2.0 can be used in conjunction with EventMachine (github.com/eventmachine/eventmachine/).

More and more ruby applications are using EventMachine. This flavour of the scheduler relies on EventMachine, thus it doesn't require a separate thread like the PlainScheduler does.

require 'rubygems'
require 'eventmachine'

EM.run {

  scheduler = Rufus::Scheduler::EmScheduler.start_new

  scheduler.in '20m' do
    puts "order ristretto"
  end
}

tested with

ruby 1.8.6, ruby 1.9.1p0 on jruby 1.2.0 it has some tiny issues (spec/blocking_spec.rb)

dependencies

the ruby gem 'eventmachine' if you use Rufus::Scheduler::EmScheduler, else no other dependencies.

mailing list

On the rufus-ruby list :

groups.google.com/group/rufus-ruby

issue tracker

rubyforge.org/tracker/?atid=18584&group_id=4812&func=browse

irc

irc.freenode.net #ruote

source

github.com/jmettraux/rufus-scheduler

git clone git://github.com/jmettraux/rufus-scheduler.git

credits

github.com/jmettraux/rufus-scheduler/blob/master/CREDITS.txt

authors

John Mettraux, [email protected], jmettraux.wordpress.com

the rest of Rufus

rufus.rubyforge.org

license

MIT

rufus-scheduler's People

Contributors

jmettraux avatar

Stargazers

 avatar

Watchers

 avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.