Tuesday, September 16, 2008

Avoiding simultaneous run for rake tasks

Sometimes we cannot guarantee that some periodic job will be finished before its next call. Especially if the environment is heavily loaded or the interval between job runs is small enough relative to a processed data set. This is why I decided to run some rake tasks wrapped in this helper:


def if_not_running(task, &block)
  lock_file = Rails.root + "/tmp/running-task-#{task.name}.lock"
  unless File.exists?(lock_file)
    FileUtils.touch(lock_file)
    begin
      yield
    ensure
      File.delete(lock_file)        
    end
  else
    puts "#{Time.now}: task #{task.name} is already running, skipping"
  end
end

I wonder if the helper covers all situations (and possible race conditions). Anyway it seems to work fine at the moment.

Usage:


namespace :test do
  task :test => :environment do |t|
    if_not_running(t) do
      puts Rails.env
      sleep 20
    end
  end
end

1 comments:

Sergey Gershun said...

to bu sure that periodic background job is finished you can use daemon_controller from Phusion
http://github.com/FooBarWidget/daemon_controller/tree/master