Ruby on Rails + Sidekiq:如何更改预定的作业开始时间?

Okt*_*tav 8 ruby ruby-on-rails sidekiq

我最近开始与Sidekiq合作,并注意到它有一个很棒的功能,我已经搜索了很长时间:

UserMailer.delay_until(5.days.from_now).find_more_friends_email
Run Code Online (Sandbox Code Playgroud)

基本上我可以在将来安排工作,所以我不需要我的应用程序连续轮询开始时间的新事件.

现在这就像一个魅力,但我如何改变工作的开始时间?通常,某些预定事件的开始时间会更改.我怎么在sidekiq复制这个?

我知道我可以删除作业并创建一个新作业,但是可以只修改开始时间吗?

编辑:

我建立在Oto Brglez的想法之上,这里是文档化的代码:

module TaskStuff
  class TaskSetter
    include Sidekiq::Worker
    sidekiq_options retry: false

    def perform(task_id)
      task = Task.find(task_id)
      # Get the worker that's performing this job
      if worker = AppHelpers.find_worker(jid)
        # If the worker matches the "at" timestamp then this is the right one and we should execute it
        if worker.last["payload"]["at"].to_s.match(/(\d*\.\d{0,3})\d*/)[1] == task.start.to_f.to_s.match(/(\d*\.\d{0,3})\d*/)[1]
          task.execute
        else
          custom_logger.debug("This worker is the wrong one. Skipping...")
        end
      else
        custom_logger.error("We couldn't find the worker")
      end
    end
  end
end


module AppHelpers

  [...]

  def self.find_worker(jid)
    Sidekiq::Workers.new.select {|e| e.last["payload"]["jid"] == jid}.first
  end

  [...]

end

> task = Task.create(start: 5.hours.from_now)
> TaskStuff::TastSetter.perform_at(task.start, task.id)
Run Code Online (Sandbox Code Playgroud)

现在,如果我这样做

> task.update_attributes(start: 4.hours.from_now)
> TaskStuff::TastSetter.perform_at(task.start, task.id)
Run Code Online (Sandbox Code Playgroud)

任务将在4小时内执行,另一项工作(将在5小时内执行)将被忽略并在到达时间时被删除.

最初我尝试使用Time.now而不是,worker.last["payload"]["at"]但这可能是非常不准确的,因为预定的作业不会总是按时执行.检查间隔为15秒,如果所有工人在其他地方忙碌,工作可能会进一步延迟.

我必须使用Regexp匹配开始时间,因为在读取时task.start我可能得到一个具有不同小数位数的浮点数,并且if条件不会通过.这样我得到两个值为3十进制.

我发现获得工作的"at"属性的唯一方法是通过工作者获取它.如果我要问Redis或者使用Mike,Sidekiq::ScheduledSet.new我就不会得到当前的工作,因为它已经从Redis中撤出了.

编辑2:

对于任何有兴趣的人,我采用了类似但不同的方法.基本上不是比较开始时间,而是Task在模型和Sidekiq调用中添加了一个额外的字段,称为start_token.如果使用与对象相同的令牌调用sidekiq作业,则该作业有效,否则丢弃并跳过作业.每次模型更改start_time时,令牌都会更新.

Dic*_*Boy 36

这可能没有回答这个问题,但这首先是google上的"sidekiq增加已经安排的工作时间".

Sidekiq在SortedEntry作业上使用此方法.

找工作:

job = Sidekiq::ScheduledSet.new.find_job(job_id)
Run Code Online (Sandbox Code Playgroud)

重新安排工作:

job.reschedule(Time.now + 2.hours)
Run Code Online (Sandbox Code Playgroud)

  • 请注意,您还可以通过执行`Sidekiq :: ScheduledSet.new.find {条件} .at`来查看何时计划运行特定作业。[文档在这里](http://www.rubydoc.info/github/mperham/sidekiq/Sidekiq/SortedEntry#at-instance_method) (2认同)

Oto*_*lez 5

我不认为编辑/更新工作是方法。每次发生变化时,我通常都会创建新工作。然后在作业本身检查执行某个任务的时间是否正确......如果时间合适,继续执行任务,否则就跳过......