简体   繁体   English

抢救DelayedJob工作者中的“ RecordNotFound”错误

[英]Rescue “RecordNotFound” errors in DelayedJob workers

I use DelayedJob to handle certain tasks in the background. 我使用DelayedJob在后台处理某些任务。

For example, in my application a user can "like" a message, and when that happens the poster gets notified. 例如,在我的应用程序中,用户可以“喜欢”消息,然后在发生这种情况时通知发布者。 This notification is handled in the background. 该通知在后台处理。

Occasionally, what can happen is that the liker decides to undo his action and delete his "like" before the notification goes out. 有时,可能发生的情况是,在通知消失之前,喜欢者决定撤消其操作并删除其“喜欢”。 In those instances the background code hits a "RecordNotFound" error as the "like" no longer exists. 在这些情况下,由于“赞”不再存在,因此后台代码会出现“ RecordNotFound”错误。

I thought I handled this case by rescuing the error as so (self here is the 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

However, in practice this does not seem to be rescuing the errors, as I still see such errors in my logs: 但是,实际上,这似乎并没有解决错误,因为我仍然在日志中看到这样的错误:

{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'

Any ideas why my rescue statement is not working in this case? 有什么想法为什么我的救援声明在这种情况下不起作用?

The Like object does not exist, so the method with rescue is not even being called. Like对象不存在,因此甚至没有调用具有抢救的方法。

Try defining your delayed method as a class method, not an instance method. 尝试将延迟的方法定义为类方法,而不是实例方法。 That way, delayed job will be able to execute the method, even if the instance does not exist. 这样,即使实例不存在,延迟的作业也将能够执行该方法。 Eg, 例如,

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

I finally solved this by using a class method instead of an instance method for my delay calls. 我终于通过使用类方法而不是实例方法解决了这个延迟调用。 Let me show you by way of example. 让我以身作则。 Here's how I previously structured my delay calls: 这是我以前构造延迟呼叫的方式:

  def background_send_push_notifications
    self.delay.send_push_notifications
  end

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

The issue I kept hitting was that it was common for a user to immediately unlike, right after liking something. 我一直碰到的问题是,用户在喜欢某些东西后立即立即与众不同是很常见的。 This meant that the Like object was no more when the delayed_job tried to execute, and I'd get lots of "RecordNotFound" errors. 这意味着,当delay_job试图执行时,Like对象不再存在,并且我会收到很多“ RecordNotFound”错误。

Now I have transitioned the delay call to a class method that does the object lookup in the background and returns if it no longer exists. 现在,我将延迟调用转换为一个类方法,该方法在后台进行对象查找,如果不再存在则返回。 Here's the new structure 这是新结构

  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

Hope this helps somebody! 希望这对某人有帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM