【问题标题】:Easy inquiry: how to precisely schedule a job in Rails?轻松查询:如何在 Rails 中精确调度作业?
【发布时间】:2012-05-30 02:33:44
【问题描述】:

我想在一个非常精确的时间运行一个进程。现在我正在使用延迟作业:

handle_asynchronously :make_live, :run_at => (exact_time_down_to_the_second)

但它根本不精确。例如,当我这样做时:

handle_asynchronously :make_live, :run_at => (Time.now + 30.seconds)

...它在 30 秒 +/- 15 秒内执行。随后的尝试会在Time.now 左右的 6 秒内发生,有时几乎是立即发生。

有没有精确的方法来做到这一点?没有卡在延迟的工作上。

编辑

当我这样做时:

handle_asynchronously :make_live, :run_at => Proc.new {|event| event.occurs_at }

...它运作良好(似乎将队列轮询到第二个)。即使使用短间隔(30 秒)。

看起来只是控制台测试效果不佳。

所以这暂时解决了我的问题。

【问题讨论】:

    标签: ruby-on-rails delayed-job


    【解决方案1】:

    延迟可能是由两个因素造成的:延迟作业定期检查作业。延迟的作业也按顺序执行作业,所以如果队列中已经有一些作业,它就会被延迟。

    如果您知道并且可以提前定义任务(即与当前时间无关),请使用 Whenever gem,它是 cronjobs 的包装器。

    为 Delayedjobs 创建单独的队列还可以减少长队列造成的延迟。

    你也可以切换到Resque,这就像内存中的队列,它可能会以更短的间隔检查队列。

    【讨论】:

    • 我会随时查看。顺便说一句,我正在测试队列中只有一项工作;应用程序本身永远不会超过 4 个,间隔一天左右。
    【解决方案2】:

    好的。您的工作包装对您来说不够精确。我看到 2 个选项:

    1. 替换或修改作业包装以更精确。 Resque 可能会有所帮助,或者您可以查看 Delayed::Job 内部以更频繁地轮询工作。可行,但我更喜欢这个 hack:
    2. 在需要运行之前将作业安排 60 秒。传递您需要执行作业的确切时间,作为参数。然后,运行sleep until Time.now == exact_time_down_to_the_second

    轰隆隆!精确执行,精确到秒。

    【讨论】:

    • 另外,lulalala 提出了一个很好的观点:如果您有工作在此之前排队,Delayed::Job 可能仍然无法及时完成工作。听起来您的应用程序现在将作业分开,但在未来,如果您有其他类型的作业,您将希望为此类重要任务设置一个队列,并将您的其他作业留在一个单独的队列中单独的工作池。我相信 Delayed::Job 现在支持命名队列,或者 Resque 肯定支持。祝你好运!
    • 如果您的查询长度很大会发生什么?所有工作人员都会睡觉,查询会增加。这是个非常糟糕的主意。
    • 唯一应该在我的解决方案的正确实施中休眠的工作人员是运行这项关键工作的工作人员。为了安全起见,您可以将作业包装在超时块中,或相应地调整 MAX_RUN_TIME。
    【解决方案3】:

    Delayed Job 默认设置为每 5 秒轮询一次数据库。您可以调整它,使其每秒轮询一次。我很好奇需要这种精度水平的用例。也许有更好的解决方案?

    【讨论】:

      猜你喜欢
      • 2017-02-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-20
      • 1970-01-01
      • 2021-08-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多