在DelayedJob工作程序中解决“RecordNotFound”错误

时间:2013-03-04 21:47:11

标签: ruby-on-rails delayed-job rescue

我使用DelayedJob在后台处理某些任务。

例如,在我的应用程序中,用户可以“喜欢”一条消息,当发生这种情况时,会通知海报。此通知在后台处理。

偶尔会发生的事情是,在通知发出之前,liker决定撤消他的行动并删除他的“喜欢”。在这些情况下,后台代码会出现“RecordNotFound”错误,因为“like”不再存在。

我以为我是通过拯救错误来处理这个案子的(这里的自我就是这样):

  def send_push_notifications
    begin
      user = self.message.user
      message = "#{self.user.name} liked your workout"
      Urbanairship::push_now(user, message, ["message", self.message.id]) if self.user != user
    rescue ActiveRecord::RecordNotFound
      # Do nothing
    end
  end

然而,在实践中,这似乎并没有挽救错误,因为我仍然在我的日志中看到这样的错误:

{ActiveRecord::RecordNotFound, class: Like , primary key: 1557 
/app/vendor/bundle/ruby/1.9.1/gems/delayed_job-3.0.2/lib/delayed/serialization/active_record.rb:12:in `rescue in yaml_new'
/app/vendor/bundle/ruby/1.9.1/gems/delayed_job-3.0.2/lib/delayed/serialization/active_record.rb:6:in `yaml_new'
/usr/local/lib/ruby/1.9.1/syck.rb:135:in `transfer'
/usr/local/lib/ruby/1.9.1/syck.rb:135:in `node_import'
/usr/local/lib/ruby/1.9.1/syck.rb:135:in `load'
/usr/local/lib/ruby/1.9.1/syck.rb:135:in `load'

为什么我的救援声明在这种情况下不起作用?

2 个答案:

答案 0 :(得分:1)

Like对象不存在,因此甚至没有调用具有rescue的方法。

尝试将延迟方法定义为类方法,而不是实例方法。这样,即使实例不存在,延迟的作业也能够执行该方法。如,

class Like < ActiveRecord::Base

...

def self.send_push_notifications(like_id=nil)
  begin
    like = Like.find like_id
    user = like.message.user
    message = "#{like.user.name} liked your workout"
    Urbanairship::push_now(user, message, ["message", like.message.id]) if like.user != user
  rescue ActiveRecord::RecordNotFound
    # Do nothing
  end
end

...

end

答案 1 :(得分:0)

我终于通过使用类方法而不是实例方法来解决这个问题。让我以举例的方式向您展示。以下是我之前构建延迟调用的方式:

  def background_send_push_notifications
    self.delay.send_push_notifications
  end

  def send_push_notifications
    message = "#{self.user.name} liked your workout"
    ...
  end

我一直在讨论的问题是,用户在喜欢某事之后立刻就不同了。这意味着当delayed_job尝试执行时,Like对象不再存在,并且我会收到大量“RecordNotFound”错误。

现在我已经将延迟调用转换为在后台执行对象查找的类方法,如果它不再存在则返回。这是新结构

  def background_send_push_notifications
    Like.delay.send_push_notifications(self.id)
  end

  def self.send_push_notifications(id)
    like = Like.find_by_id(id)
    like.send_push_notifications unless like.nil?
  end

  def send_push_notifications
    message = "#{self.user.name} liked your workout"
    ...
  end

希望这有助于某人!