Check rake if it is already running

Is it possible to somehow execute the rake command only if it is not running, I want to use cron to perform some rake tasks, but the rake task should not start if the previous call is not completed Thanks

+6
source share
5 answers

I use lockrun to prevent cron tasks from executing multiple times (this only works when invoking a command through the same lockrun call, so if you need to protect against different call paths, you will need to look for other methods).

In your crontab, you call it like this:

 */5 * * * * /usr/local/bin/lockrun --lockfile=/tmp/this_task.lockrun -- cd /my/path && RAILS_ENV=production bundle exec rake this:task 
+12
source

In addition, you can use the lock file, but process it in the task:

 def lockfile # Assuming you're running Rails Rails.root.join('tmp', 'pids', 'leads_task.lock') end def running! `touch #{lockfile}` end def done! `rm #{lockfile}` end def running? File.exists?(lockfile) end task :long_running do unless running? running! # long running stuff done! end end 

It can probably be extracted into some kind of module, but you get this idea.

+6
source

A general non rake solution is to use the pid file as a lock. You complete the rake task in a script that creates this file when it starts rake, deletes it when rake finishes, and checks it before starting.

Not sure if the rake has something built in, I don't know anything.

+5
source

If you just want to skip this rake task, you can also use the database to store information about the progress of the task (for example, update the field when starting and completing a given task) and check this information before starting each task.

However, if you want queued behavior, you might consider creating a daemon to solve problems. The process is very simple and gives you more control. There is a very good railscast about this: Custom daemon

The daemon approach will also not allow loading the rail environment for each task. This is especially useful if your rake tasks are frequent.

+2
source

Here is my version with file locking for rake rails tasks.

Put this in your rake task file (in the namespace so that it does not match other rake tasks):

 def cron_lock(name) path = Rails.root.join('tmp', 'cron', "#{name}.lock") mkdir_p path.dirname unless path.dirname.directory? file = path.open('w') return if file.flock(File::LOCK_EX | File::LOCK_NB) == false yield end 

using:

 cron_lock 'namespace_task_name' do # your code end 

full example:

 namespace :service do def cron_lock(name) path = Rails.root.join('tmp', 'cron', "#{name}.lock") mkdir_p path.dirname unless path.dirname.directory? file = path.open('w') return if file.flock(File::LOCK_EX | File::LOCK_NB) == false yield end desc 'description' task cleaning: :environment do cron_lock 'service_cleaning' do # your code end end end 
+1
source

Source: https://habr.com/ru/post/896715/


All Articles