Ruby: Run Code Blocks at Specific Time Intervals

3

While working on a Rails project, some of my business logic parts need to run at specific time intervals. First, I create Rake tasks for my code blocks and use "cron" jobs to run those Rake tasks at the required time intervals. But, as you know, every Rake task loads the whole Rails application into the memory to run and this is costly, especially if my Rake tasks run at high frequency (every ~1 min).

So, I decided to load the tasks into the memory and make them sleep and run at specific time intervals. One of the great Rails gems that help me in doing this job is EventMachine, an event processing library for Ruby applications. Using it, you can define specific code blocks to run at specific times and also define a periodic timer for code blocks.

So, what I did is create one Rake task that contains EventMachine running, and defined some periodic timers to run code blocks at the required time intervals. In this case, my Rake task will be loaded into the memory and will be asleep (using EventMachine), merely running my code blocks at the defined time intervals without the need to reload.

  • To install this gem:
    gem install eventmachine
    and then choose the required gem version from the given list.

  • If you need your code block to run periodically every 10 secs, create a periodic timer:
    EventMachine.run {
        @periodic_job = EventMachine::PeriodicTimer.new(10){
          # code block to run every 10 secs
        }
    } 
  • You can cancel the periodic job at any time by calling:
    @periodic_job.cancel
  • Note:Do not forget to stop the event machine at the end of your periodic job, e.g. if you need your periodic job to run just 10 times:
    x = 0
    EventMachine.run {
      EventMachine::PeriodicTimer.new(0.1){
        x += 1 
           # your code go here
           EventMachine.stop if x == 10
      }
    }

Checkout the full documentation of EventMachine.

 

Written By:

Wael Shaban (wshaban.blogspot.com)

Comments

1

In the periodical timer, what would happen if there is an overlapping schedule, I mean if I'm running a periodical task every one second and the first run didn't end while the second run has the turn, will the second one run or block?

2

It will be queued until the running one competes its processing and then it will start immediately.

3

It does not work as I expected. I created a PeriodicTimer to run some tasks every 60 seconds, I print the current time (Time. now) when a new task begins:

new round started: Sun Feb 22 18:31:27 -0500 2009
new round started: Sun Feb 22 18:32:49 -0500 2009
new round started: Sun Feb 22 18:33:54 -0500 2009
new round started: Sun Feb 22 18:34:59 -0500 2009
new round started: Sun Feb 22 18:36:05 -0500 2009

It is always longer than 60 seconds.

Post a Comment

eSpace podcast Prodcast

RSS iTunes