Rails 和 sucker_punch:执行作业前去抖 x 秒以控制执行速度

Rails and sucker_punch: Debounce x seconds before executing job to control rate of execution

在我的 Rails 3.2 项目中,当模型为 created/updated 时,我正在使用 SuckerPunch 到 运行 一项昂贵的后台任务。

用户可以在此模型上进行不同类型的交互。大多数时候,这些更新都很好 间隔 ,但是对于一些其他操作,如重新排序、批量更新等,这些 POST 请求可能会非常频繁地出现,那就是它使服务器不堪重负的时候。

我的问题是,什么是最 elegant/smart 在第一次更新发生时启动后台作业的策略,但是等待说 10 秒 以确保没有更多更新进入该模型(Table,不是一行),然后执行作业。无需排队即可有效节流。

我的 sucker_punch 工人看起来像这样:

class StaticMapWorker
    include SuckerPunch::Job
    workers 10

    def perform(map,markers)
        #perform some expensive job
    end
end

它从 Marker 和 'Map' 模型调用,有时从控制器(对于 update_all 情况)调用,如下所示:

after_save :generate_static_map_html

def generate_static_map_html
    StaticMapWorker.new.async.perform(self.map, self.map.markers)
end

因此,运行宁后台作业的标准设置。在我的模型(或 Table)

上没有更新 x seconds 之前,如何让工作等待或不安排

如果有帮助,Map has_many Markers 因此触发作业的逻辑是当地图的任何标记关联时更新也会好的。

您正在寻找的是通过 ActiveJob 的 perform_later 实现的延迟工作。根据边缘指南,sucker_punch.
中未实现 ActiveJob::QueueAdapters comparison

但是不要担心,因为您可以非常简单地自己实现它。当您的作业从队列中检索作业时,首先对记录 modified_at 时间戳执行一些数学运算,将其与 10 秒前进行比较。如果模型已被修改,只需将作业添加到队列并优雅地中止。

代码!

根据页面下方 2/5 处的示例,说明如何在工作人员中添加工作 Github sucker punch

class StaticMapWorker
  include SuckerPunch::Job
  workers 10

  def perform(map,markers)
    if Map.where(modified_at: 10.seconds.ago..Time.now).count > 0
      StaticMapWorker.new.async.perform(map,markers)
    else
      #perform some expensive job
    end
  end
end