3

鉴于 Heroku 每天至少重新启动一次 dynos,我对 Clockwork、Sidekiq 和 Redis 如何在 Heroku 上组合在一起感到有些困惑。

假设我有一个每天运行一次的工人,所以它的配置config/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

假设有人在星期一注册,这项工作在星期三运行,找到他们,然后向他们发送第二封确认电子邮件。然后无论出于何种原因,测功机都会重新启动,并且作业再次运行。他们将收到另一封电子邮件。或者,如果重新启动发生在作业需要运行之前的那一刻,那么他们将一无所获。

考虑到它在 Heroku 测功机中的“寿命”,Clockwork 如何对超过 24 小时的工作有任何概念?有没有办法简单地管理这个限制,而不必不断地将这种东西保存到数据库中?

4

2 回答 2

1

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

于 2017-01-07T07:17:17.747 回答
0

如果您想避免此类问题,IMO 您需要数据库中的更多信息。状态机可能会提供帮助或显式second_confirmation_send_at列。

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

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

然后查询不再关心它是一天运行多次,还是一天后意外运行。

于 2017-01-07T08:34:24.770 回答