每当使用 Rails 在 Heroku 中执行计划任务

Posted

技术标签:

【中文标题】每当使用 Rails 在 Heroku 中执行计划任务【英文标题】:Whenever Scheduled Task in Heroku with Rails 【发布时间】:2014-09-14 22:58:38 【问题描述】:

我需要随时在 Heroku 中运行计划任务。我在 Rails 中的第一份 cron 工作! :-)

它在本地运行良好,但你如何让它在 Heroku 中运行?

我试过这个: heroku 在 --update-crontab 存储时运行

但是……

[失败] 无法编写 crontab;尝试在没有选项的情况下运行 `whenever' 以确保您的计划文件有效。

我还在 Heroku 中的应用中添加了 Heroku Scheduler。

这是我的 config/schedule.rb

RAILS_ROOT = File.dirname(__FILE__) + '/..'
require File.expand_path(File.dirname(__FILE__) + "/environment")


every :day, :at => "11:00am" do
  @appointments = Appointment.where('date between ? and ?', Date.today, Date.today + 2.day)
  @appointments.each do |appointment|

    @emails = []

    @informated_people = InformatedPerson.where(person_id: appointment.person_id)
    @users = User.find(Authorization.where(:person_id => appointment.person_id).pluck(:user_id))
    @person = Person.find(appointment.person_id)

    @emails << @person.email

    @informated_people.each do |informated_person|
        @emails << informated_person.email
    end

    @users.each do |user|
        @emails << user.email
    end

    UserEmail.appointment_reminder_email(@emails.uniq, @person , 'Cita para el día ' + appointment.date.strftime("%d/%m/%Y %H:%M") + ' con el doctor ' + appointment.doctor + ' para la especialidad ' + appointment.specialty + ' en el centro ' + appointment.center + '.' ).deliver

  end
end

【问题讨论】:

【参考方案1】:

Heroku 为这些类型的任务提供调度程序 (https://devcenter.heroku.com/articles/scheduler)

Scheduler 是一个附加组件,用于按预定时间间隔在您的应用上运行作业,很像传统服务器环境中的 cron。

我建议您将此代码移动到约会模型中的函数中。

def appointments_reminder
  @appointments = Appointment.where('date between ? and ?', Date.today, Date.today + 2.day)
  @appointments.each do |appointment|

  @emails = []

  @informated_people = InformatedPerson.where(person_id: appointment.person_id)
  @users = User.find(Authorization.where(:person_id => appointment.person_id).pluck(:user_id))
  @person = Person.find(appointment.person_id)

  @emails << @person.email

  @informated_people.each do |informated_person|
      @emails << informated_person.email
  end

  @users.each do |user|
      @emails << user.email
  end

  UserEmail.appointment_reminder_email(@emails.uniq, @person , 'Cita para el día ' + appointment.date.strftime("%d/%m/%Y %H:%M") + ' con el doctor ' + appointment.doctor + ' para la especialidad ' + appointment.specialty + ' en el centro ' + appointment.center + '.' ).deliver
end

接下来,您需要创建lib/tasks/scheduler.rake 文件

desc "Heroku scheduler tasks"
task :email_appointments_reminder => :environment do
  puts "Sending out email reminders for appointments."
  Appointment.appointments_reminder
  puts "Emails sent!"
end

最后,使用网络界面,您可以使用任务名称安排它。在此示例中,它是 rake email_appointments_reminder,您可以从下拉选项中选择频率以在每天上午 11:00 运行它。

我还建议在使用以下控制台命令安排任务之前手动测试任务:heroku run rake email_appointments_reminder

【讨论】:

Thaaaanks Aytan,现在我对其进行了测试并在 heroku 中工作。 :-) Scheduler 是一项“尽力而为”的服务,这意味着执行是预期的,但不能保证执行。众所周知,调度程序偶尔(但很少)错过计划作业的执行。如果计划的作业是您应用程序的关键组件,则建议运行自定义时钟进程,以获得更高的可靠性、控制力和可见性。” (devcenter.heroku.com/articles/scheduler)

以上是关于每当使用 Rails 在 Heroku 中执行计划任务的主要内容,如果未能解决你的问题,请参考以下文章

如何将 Rails + Webpacker 应用程序部署到 Heroku?

Heroku 推送错误:“无法检测到 rake 任务”(Rails 6.1)

Rails:Heroku 的预编译?

如何使用Rails和Heroku创建多个并行并发请求

为啥我的 sidekiq 计划的 cron 作业没有在 heroku 上运行?

Rails - jQuery 不能在 Heroku 的生产环境中工作