How can I schedule a 'weekly' job on Heroku?

雨燕双飞 提交于 2019-12-31 09:13:50

问题


I have a Rails app deployed on Heroku with the Heroku scheduler add-on successfully working for daily jobs.

Now I want a weekly job, but the scheduler add-on does not allow me a weekly option.

Any suggestions on how I could accomplish this:

  • I've tried using rufus-scheduler in the past but it caused me some problems, so that's not an option. See here for detail.
  • I'm thinking of something along the lines of checking for current day within a daily job. Has anyone tried it and have feedback or know of issues with the approach?
  • Other ideas much appreciated.

回答1:


One approach would be the one of your 2nd bullet point:

activate the Heroku cron add-on, and add a cron.rake task in app/lib/tasks

Activate the Heroku scheduler add-on, and add a scheduler.rake task in app/lib/tasks

task :your_weekly_task=> :environment do
  if Time.now.friday? # previous answer: Date.today.wday == 5
    #do something
  end
end

You even have the luxury of defining the day you want your task to run ;o) (5 is for Friday)

EDIT: by the way, Cron is deprecated and Heroku recommends switching to their Scheduler add-on. This doesn't change the approach for a weekly job though.

EDIT2: adjustments to my answer based on feedback from sunkencity.




回答2:


An alternate option using only shell code. Setup the Heroku scheduler hourly, and do a comparison against the date command:

# 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 

I've used this code to mimic cron in my local time zone:

nz_hour="$(TZ=NZ date +%H)" ; nz_day="$(TZ=NZ date +%d)" ; if [ "$nz_hour" = 08 ] && [ "$nz_day" = 01 ]; then YOUR_COMMAND ; fi 



回答3:


It's not ideal, but I've taken to adding a RUN_IF environment variable to rake tasks run through heroku:scheduler which lets me weekly and monthly schedules for jobs.

# 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

If a rake task is run without a RUN_IF variable it will run. Otherwise, the job will be aborted unless the value of RUN_IF evals to a falsey value.

$ 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)

Similar to other ideas above, but I prefer moving the scheduling details out of the application code.




回答4:


As discussed over here, and using the above logic from Rob, here are the bash scripts broken down by a day of the week, once a month, and on a specific date.

Run a task every Monday:

if [ "$(date +%u)" = 1 ]; then MY_COMMAND; fi

Run a task every 1st day in a month:

if [ "$(date +%d)" = 01 ]; then MY_COMMAND; fi

You could also run a job every year on December 24th:

if [ "$(date +%m)" = 12 ] && [ "$(date +%d)" = 24 ]; then MY_COMMAND; fi



回答5:


If you don't want or cannot do this with Rake, another option is to do this with Ruby from 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 "$@"

This works even for non-ruby projects (as in my case: Clojure).



来源:https://stackoverflow.com/questions/9835095/how-can-i-schedule-a-weekly-job-on-heroku

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!