如何在Heroku上处理长时间运行的作业?

时间:2016-10-30 00:13:37

标签: ruby-on-rails ruby heroku delayed-job ruby-on-rails-5

我想使用Heroku,但他们每24小时随机重启dynos的事实让事情变得有点困难。

我有一系列处理付款处理非常重要的工作,我希望它们由数据库支持,因此它们100%可靠。出于这个原因,我选择了慢的DJ。

因为我选择了DJ,这意味着我也不能一次将5,000,000个事件推送到数据库(每个电子邮件发送1个)。

因为这样,我有更长时间的工作(在几个小时内发送200,000条短信)。

对于这些运行时间较长的工作,如果它们在中间被切断,那么让它们工作会更具挑战性。

看来heroku发送SIGTERM,然后期望该过程在30秒内关闭。我的长期工作不会发生这种情况。

现在我不确定如何处理它们...我能想到的唯一方法是在发送文本后立即更新数据库(例如,sms_sent_at列),但这只是意味着我正在破坏数据库性能,而不是为每个批次发送一个更新查询。

如果我可以安排重启,这会好得多,至少我可以在晚上做到这一点,当我99%可能不会运行任何不需要超过30秒关闭的工作时

或者......换句话说,我可以在长时间播放的DJ中“监听”SIGTERM并至少提前中止循环以便以后恢复吗?

2 个答案:

答案 0 :(得分:1)

手动重启将重置24小时制 - heroku ps:restart在您首选的时间应该为您提供您正在寻找的控制。

可以在此处找到更多信息:Dynos and the Dyno Manager

答案 1 :(得分:0)

这里有正确的答案,你在听SIGTERM(我在这里使用DJ),然后优雅地解救。工作是幂等的,这一点非常重要。

Long running delayed_job jobs stay locked after a restart on Heroku

class WithdrawPaymentsJob

  def perform
    begin
      term_now = false
      old_term_handler = trap('TERM') { term_now = true; old_term_handler.call }

      loop do

        puts 'doing long running job'
        sleep 1

        if term_now
          raise 'Gracefully terminating job early...'
        end
      end

    ensure
      trap('TERM', old_term_handler)
    end
  end

end

以下是Que

解决问题的方法
    if Que.worker_count.zero?
      raise 'Gracefully terminating job early...'
    end