[英]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.