繁体   English   中英

如果我安排一名工人每天在Heroku上运行,我怎么能确定它不会运行两次或被跳过?

[英]If I schedule a worker to run every day on Heroku, how can I be sure it doesn't run twice or get skipped?

鉴于Heroku每天至少重启一次dynos,我觉得Clockwork,Sidekiq和Redis如何在Heroku上完全融合,我有点困惑。

假设我有一个每天运行一次的工作者,所以它在config/clock.rbconfig/clock.rb为:

module Clockwork
  every(1.day, 'Resend confirmation') { ResendConfirmationWorker.perform_async }
end

在此工作人员中,我获得了创建帐户但尚未在两天内确认帐户的所有用户,并向每个帐户重新发送确认电子邮件。

class ResendConfirmationWorker
  include Sidekiq::Worker
  sidekiq_options queue: :resend_confirmation, retry: false

  def perform
    d = Time.zone.now - 2.days
    users = User.where.not(confirmation_sent_at: nil)
                .where(confirmed_at: nil)
                .where(created_at: d.beginning_of_day..d.end_of_day)

    users.find_each do |user|
      user.send_confirmation_instructions
    end
  end
end

假设有人在星期一报到,这个工作在周三运行,找到他们,并向他们发送第二封确认电子邮件。 然后dyno因任何原因重新启动,并且作业再次运行。 他们会收到另一封电子邮件。 或者,如果重新启动发生在作业需要运行之前的那一刻,那么它们将无法获得任何结果。

鉴于其在Heroku dyno中的“寿命”,发条如何有超过24小时的任何工作概念? 有没有办法简单地管理这个限制,而不必经常将这种东西保存到数据库?

如果你知道你将在每个星期三执行它,我建议使用Heroku Scheduler( https://devcenter.heroku.com/articles/scheduler )。 它允许您以设定的时间间隔运行特定命令。 减少复杂性。

IMO如果要避免此类问题,则需要在数据库中获取更多信息。 状态机可能有帮助或显式second_confirmation_send_at列。

这将允许您在工作中编写查询,如下所示:

users = User.where('confirmation_sent_at < ?', 2.days.ago)
            .where(second_confirmation_send_at: nil)

如果它一天运行多次,或者一天后意外运行,则查询不再关心。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM