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)