Как я могу запланировать еженедельную работу на Heroku?
У меня есть приложение Rails, развернутое на Heroku, и надстройка планировщика Heroku успешно работает для ежедневных заданий.
Теперь я хочу еженедельную работу, но надстройка планировщика не разрешает мне недельный вариант.
Любые предложения о том, как я могу это сделать:
- Я пытался использовать rufus-scheduler в прошлом, но это вызвало у меня некоторые проблемы, так что это не вариант. Подробнее см. здесь.
- Я думаю о чем-то вроде проверки текущего дня в повседневной работе. Кто-нибудь пробовал это и имел обратную связь или знал о проблемах с этим подходом?
- Другие идеи получили высокую оценку.
Ответы
Ответ 1
Один из подходов - это ваш второй пункт:
активировать дополнение к керону Heroku и добавить задачу cron.rake
в app/lib/tasks
Активируйте надстройку планировщика Heroku и добавьте задачу scheduler.rake
в app/lib/tasks
task :your_weekly_task=> :environment do
if Time.now.friday? # previous answer: Date.today.wday == 5
#do something
end
end
У вас даже есть возможность определить день, когда вы хотите, чтобы ваша задача выполнялась; o)
(5 в пятницу)
РЕДАКТИРОВАТЬ: К сожалению, Cron не рекомендуется, и Heroku рекомендует переключиться на дополнение к планировщику. Однако это не изменяет подход к еженедельной работе.
EDIT2: корректировки моего ответа на основе обратной связи от заката.
Ответ 2
Альтернативный вариант с использованием только кода оболочки. Настройте планировщик Heroku ежечасно и выполните сравнение с командой date:
# setting the schedular to run hourly at *:30 is equivalent to the
# crondate: 30 8 * * 1
if [ "$(date +%H)" = 08 ] && [ "$(date +%d)" = 01 ]; then YOUR_COMMAND ; fi
Я использовал этот код для имитации cron в моем локальном часовом поясе:
nz_hour="$(TZ=NZ date +%H)" ; nz_day="$(TZ=NZ date +%d)" ; if [ "$nz_hour" = 08 ] && [ "$nz_day" = 01 ]; then YOUR_COMMAND ; fi
Ответ 3
Это не идеальный вариант, но я добавил добавить переменную среды RUN_IF для запуска задач, выполняемых через heroku: scheduler, который позволяет мне выполнять еженедельные и ежемесячные расписания для заданий.
# lib/tasks/scheduler.rake
def run?
eval ENV.fetch('RUN_IF', 'true')
end
def scheduled
if run?
yield
else
puts "RUN_IF #{ENV['RUN_IF'].inspect} eval'd to false: aborting job."
end
end
# lib/tasks/job.rake
task :job do
scheduled do
# ...
end
end
Если задача rake выполняется без переменной RUN_IF, она будет запущена. В противном случае задание будет прервано, если значение RUN_IF не станет равным значению false.
$ rake job # => runs always
$ rake job RUN_IF='Date.today.monday?' # => only runs on Mondays
$ rake job RUN_IF='Date.today.day == 1' # => only runs on the 1st of the month
$ rake job RUN_IF='false' # => never runs (not practical, just demonstration)
Как и другие идеи выше, но я предпочитаю перемещать детали планирования из кода приложения.
Ответ 4
Как обсуждалось здесь, и используя приведенную выше логику от Rob, вот сценарии bash, разбитые на день неделю, раз в месяц и в определенную дату.
Запуск задачи каждый понедельник:
if [ "$(date +%u)" = 1 ]; then MY_COMMAND; fi
Запуск задачи каждый 1-й день в месяц:
if [ "$(date +%d)" = 01 ]; then MY_COMMAND; fi
Вы также можете запускать работу каждый год 24 декабря:
if [ "$(date +%m)" = 12 ] && [ "$(date +%d)" = 24 ]; then MY_COMMAND; fi
Ответ 5
Если вы не хотите или не можете сделать это с помощью Rake, другой вариант - сделать это с Ruby от bash:
#!/bin/bash
cmd="echo your schedule job here"
# Only run on even days
ruby -e 'if Time.now.utc.day.even?; puts "Not today!"; exit 1; end' && $cmd "[email protected]"
Это работает даже для нерубинных проектов (как в моем случае: Clojure).