延迟任务(delayed_job):从队列中删除任务

8
class Radar
 include Mongoid::Document
 after_save :post_on_facebook

 private

 def post_on_facebook
  if self.user.settings.post_facebook
    Delayed::Job.enqueue(::FacebookJob.new(self.user,self.body,url,self.title),0,self.active_from)
  end
 end

end

class FacebookJob < Struct.new(:user,:body,:url,:title)
  include SocialPluginsHelper

  def perform
    facebook_client(user).publish_feed('', :message => body, :link => url, :name => title)
  end
end

我希望在特定日期执行post_on_facebook方法。我将这个日期存储在“active_from”字段中。
上面的代码有效,作业会在正确的日期执行。
但是在某些情况下,我首先创建Radar对象并将一些作业发送到延迟作业队列中。之后我更新此对象并发送另一个作业到延迟作业。
这是错误的行为,因为我只想在正确的时间执行一次作业。在这种实现中,将有两个作业被执行。我如何删除以前的作业,以便只执行更新后的作业?
Rails 3.0.7
Delayed Job => 2.1.4 https://github.com/collectiveidea/delayed_job

ps:对不起我的英语不好,我会尽力的

2个回答

13
听起来你想要在雷达对象更新并重新排队时取消队列中的任何作业。
Delayed:: Job.enqueue 应该返回一个 Delayed::Job 记录,因此你可以从中获取 ID,并将其保存回雷达记录中(在雷达文档上创建一个字段),这样以后就可以轻松找到它。
你应该将它更改为 before_save,这样你就不会进入无限保存的循环中。
before_save :post_on_facebook

def post_on_facebook
  if self.user.settings.post_facebook && self.valid?

    # delete existing delayed_job if present
    Delayed::Job.find(self.delayed_job_id).destroy if self.delayed_job_id

    # enqueue job
    dj = Delayed::Job.enqueue(
      ::FacebookJob.new(self.user,self.body,url,self.title),0,self.active_from
    )

    # save id of delayed job on radar record
    self.delayed_job_id = dj.id

  end
end

@Unixmonkey... 如果工作是在 after_save 回调中创建的,会怎样呢? - Rohit
@Rohit,after_save将运行此方法,并且delayed_job_id不会在记录上设置(因为您无法在after_save中调用save而不使其进入无限循环)。 - Unixmonkey

3

您是否尝试过存储延迟作业的ID,以备可能删除: 例如:

job_id = Delayed::Job.enqueue(::FacebookJob.new(self.user,self.body,url,self.title),0,self.active_from)
job = Delayed::Job.find(job_id)
job.delete

有趣的是,如果 Delayed::Worker.delay_jobs = false,这将会出现问题,因为它看起来像是仅运行作业的排队操作,而不会将其保存到数据库中。 - Kevin Davis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接