单个延迟工作的工人可以在正在进行的工作结束之前开始下一份工作吗?

Can single delayed job worker start the next job before the ongoing job ends?

我在调用第 3 方 API 服务的应用程序中实施了 API 速率限制,它限制了在指定时间间隔内对服务提出的请求数量。

我查看了延迟的工作文档,但找不到我要找的信息。

我的情况是;

如果时间非常短,比如说 5 秒,在 2 个延迟的作业之间,工人会做什么?

第二个作业执行时间到了,是等第一个作业完成,还是在指定时间开始作业?

如果是后者,它将打破我的速率限制实施,因为 API 只允许我每分钟 60 个请求,并且两个作业都会将自己限制为每分钟 60 个请求,并且两个作业总共都会尝试一分钟内发送大约 120 个请求。

提前致谢,干杯!

这取决于可用的 DelayedJob worker 的数量。因为自由工人会在 run_at 时间一到就挑选工作并处理它。

如果您需要确保一次只运行一个作业,我看到两个简单的选项:

  1. 将您的工人数量限制在 1。或者
  2. 将下一个作业作为处理的最后一步排队。

可能看起来像这样:

class Job
  def process
    # code for the job ... 

    # enqueue the next job to run in 5 seconds
    Job.delay(run_at: 5.seconds.from_now).process
  end
end

第三个选项有点复杂,使用 named queues。当您将此类作业排入一个特殊的命名队列时,您可以使用该特殊队列来计算下一个作业的时间。而不是像这样排队工作:

Job.delay.process

检查作业是否已经存在,像这样:

queue_name = 'one_at_a_time'
latest_job = Delayed::Job.where(queue: queue_name).order(:run_at).last
run_at     = latest_job ? latest_job.run_at + 5.seconds : Time.current
Job.delay(queue: queue_name, run_at: run_at).process

另一种选择是 运行 每个队列一个工作实例:

RAILS_ENV=production bin/delayed_job --queue=tracking start

RAILS_ENV=production bin/delayed_job --queues=mailers,tasks start

Documentation