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

前端 未结 5 1784
走了就别回头了
走了就别回头了 2020-12-24 08:49

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 schedul

相关标签:
5条回答
  • 2020-12-24 08:49

    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 
    
    0 讨论(0)
  • 2020-12-24 08:49

    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
    
    0 讨论(0)
  • 2020-12-24 08:57

    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.

    0 讨论(0)
  • 2020-12-24 09:13

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

    0 讨论(0)
  • 2020-12-24 09:16

    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.

    0 讨论(0)
提交回复
热议问题