延迟作业 ActiveRecord::Job 加载 - 运行 每 5 秒?

Delayed Job ActiveRecord::Job Load - run every 5 seconds?

我觉得这是 Rails 疑病症的等价物...但我看了一眼 tail -f logs/development.log 然后被输出催眠了:

  Delayed::Backend::ActiveRecord::Job Load (0.8ms)  UPDATE "delayed_jobs" SET locked_at = '2016-08-26 12:49:09.594888', locked_by = 'host:ghost pid:4564' WHERE id IN (SELECT  "delayed_jobs"."id" FROM "delayed_jobs" WHERE ((run_at <= '2016-08-26 12:49:09.594275' AND (locked_at IS NULL OR locked_at < '2016-08-26 08:49:09.594332') OR locked_by = 'host:ghost pid:4564') AND failed_at IS NULL) ORDER BY priority ASC, run_at ASC LIMIT 1 FOR UPDATE) RETURNING *
  Delayed::Backend::ActiveRecord::Job Load (0.5ms)  UPDATE "delayed_jobs" SET locked_at = '2016-08-26 12:49:14.651262', locked_by = 'host:ghost pid:4564' WHERE id IN (SELECT  "delayed_jobs"."id" FROM "delayed_jobs" WHERE ((run_at <= '2016-08-26 12:49:14.650707' AND (locked_at IS NULL OR locked_at < '2016-08-26 08:49:14.650765') OR locked_by = 'host:ghost pid:4564') AND failed_at IS NULL) ORDER BY priority ASC, run_at ASC LIMIT 1 FOR UPDATE) RETURNING *
  Delayed::Backend::ActiveRecord::Job Load (0.5ms)  UPDATE "delayed_jobs" SET locked_at = '2016-08-26 12:49:19.716179', locked_by = 'host:ghost pid:4564' WHERE id IN (SELECT  "delayed_jobs"."id" FROM "delayed_jobs" WHERE ((run_at <= '2016-08-26 12:49:19.715433' AND (locked_at IS NULL OR locked_at < '2016-08-26 08:49:19.715494') OR locked_by = 'host:ghost pid:4564') AND failed_at IS NULL) ORDER BY priority ASC, run_at ASC LIMIT 1 FOR UPDATE) RETURNING *

每五秒运行一次。所以...呃,那是...正常吗?

我想到这就是 Delayed Job 必须工作的方式,通过根据时间戳检查作业,所以这就是它做的事情,但我没能找到这方面的合适的书面证据。

如果是这样...我的第二个担心是这不会在我的 Heroku 实例上烧钱吗?我安装了 workless gem 以试图降低成本 - 但我没有看到任何代码进来关闭它...

Bug 或 feature,如何才能不让自己破产?

这确实是延迟作业的工作原理。默认 sleep_delay 为 5 秒 (Source Code)。

您可以按照 here 所述在初始化程序中配置自定义延迟。寻找 sleep_delay.

添加以下行并根据需要更改频率值。

#initializers/delayed_job_config.rb
Delayed::Worker.sleep_delay = 60 #for a 60 second sleep time.

我会尽力比其他人更完整地回答您的问题。

是的,这是正常行为。当您启动延迟作业流程时,它会以可配置的时间间隔检查您的数据库中是否有未处理的作业。 (默认为每 5 秒一次,您可以使用 Delayed::Worker.sleep_delay 设置将其配置为不同的间隔。)

你是对的,在它的一次定期检查中,延迟作业会检查下一个需要完成的可用作业,然后 运行 完成它。

为了有效地 运行 延迟工作,您通常随时都有一个工人测功机不断检查新工作 运行。

但是,您 link 在问题中提出的无用 gem 可以帮助您解决这个问题。 workless 不需要让工作人员全天候 24/7 检查新工作,只有在队列中有 运行 工作时才会启动工作人员测功机。工作完成后,workless 关闭 worker dyno。

您可以在 workless 的自述文件中阅读 description of this behavior

How does Workless work?

  • Delayed::Workless::Scaler is mixed into the Delayed::Job class, which adds a bunch of callbacks to it.
  • When a job is created on the database, a create callback starts a worker.
  • The worker runs the job, which removes it from the database.
  • A destroy callback stops the worker.

然而,总有一个权衡。 Heroku 启动 worker dyno 需要时间,因此处理新作业不会那么即时。例如,使用持续 运行ning 的工人测功机,您的工作通常会在 5 秒内 运行。如果您改用 workless,启动测功机和延迟工作可能需要大约 30 秒才能开始工作。显然,什么是可以接受的取决于您的应用,所以这完全是您的决定。