проверка граблей, если уже работает - PullRequest
7 голосов
/ 06 сентября 2011

Можно ли каким-либо образом выполнить задачу rake, только если она еще не запущена, Я хочу использовать cron для выполнения некоторых задач rake, но задача rake не должна запускаться, если предыдущий вызов не завершен Спасибо

Ответы [ 5 ]

12 голосов
/ 14 сентября 2011

Я использую lockrun для предотвращения многократного запуска задач cron (это работает только при вызове команды через один и тот же вызов lockrun, так что если вам нужно защитить от различных путей вызова, надо искать другие методы).

В вашем crontab вы вызываете его так:

*/5 * * * * /usr/local/bin/lockrun --lockfile=/tmp/this_task.lockrun -- cd /my/path && RAILS_ENV=production bundle exec rake this:task
7 голосов
/ 21 октября 2011

Кроме того, вы можете использовать файл блокировки, но обработайте его в задаче:

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

Это, вероятно, может быть извлечено в какой-то модуль, но вы поняли идею.

5 голосов
/ 06 сентября 2011

Общее решение, не относящееся к рейку, заключается в использовании pid-файла в качестве блокировки. Вы бы включили задачу rake в скрипт, который создает этот файл при запуске rake, удаляет его, когда rake завершает работу, и проверяет его перед началом.

Не уверен, что в грабли что-то встроено, я ничего не знаю.

2 голосов
/ 13 сентября 2011

Если вы просто хотите пропустить эту задачу rake, вы также можете использовать базу данных для хранения информации о ходе выполнения задачи (например, обновить поле при запуске и завершении данной задачи) и проверять эту информацию перед запуском каждой задачи. 1001 *

Однако, если вам нужно поведение, похожее на очередь, вы можете рассмотреть возможность создания демона для обработки задач. Процесс очень прост и дает вам гораздо больше контроля. Существует очень хороший Railscast об этом: Custom Daemon

Демонический подход также предотвратит повторную загрузку среды rails при каждой задаче. Это особенно полезно, если ваши задачи по рейку часты.

1 голос
/ 25 августа 2015

Вот мой вариант с блокировкой файла для задач рейка рельса.

Поместите это в файл задачи рейка (в пространстве имен, чтобы он не перекрывался с другими задачами рейка):

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

использование:

cron_lock 'namespace_task_name' do
  # your code
end

полный пример:

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
...