2013-03-04 76 views
0

我使用DelayedJob處理後臺中的某些任務。DelayedJob工作人員救援「RecordNotFound」錯誤

例如,在我的應用程序中,用戶可以「喜歡」一條消息,當發生這種情況時,通知海報。此通知在後臺處理。

偶爾,可能發生的事情是,liker決定撤消他的行爲,並在通知發出之前刪除他的「like」。在這些情況下,由於「like」不再存在,後臺代碼會遇到「RecordNotFound」錯誤。

我想我被搶救誤差所以處理這種情況下(這裏自我是等):

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' 

任何想法爲什麼我的救援聲明不起作用在這種情況下?

+0

在Urbanairship :: push_now呼叫之前它失敗嗎?你能粘貼整個堆棧跟蹤嗎? – 2013-03-04 22:13:16

+0

對不起,這裏是完整的堆棧跟蹤:https://gist.github.com/pejmanjohn/8cf9f1f1d55a90f1ae39 – pejmanjohn 2013-03-04 22:20:40

+0

你確定你的'begin'和'rescue'之間發生錯誤嗎?嘗試在'begin'之後直接添加'raise ActiveRecord :: RecordNotFound'。如果這種方法有效並且被捕獲,那麼將它直接移到「搶救」之前並嘗試。也許這可以給你一些線索...... – 244an 2013-03-05 01:04:07

回答

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 

希望這可以幫助別人!

1

Like對象不存在,所以救援方法甚至沒有被調用。

嘗試將您的延遲方法定義爲類方法,而不是實例方法。這樣,即使實例不存在,延遲作業也能夠執行該方法。例如,

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 
+0

不,那不是那麼正確。 Delayed_job會重試失敗的作業。它保持一個計數,並重新嘗試n次,其中n是可配置的(默認是25我相信)。失敗次數越多,再次重試之前等待的時間越長。 DelayedJob.retry_at屬性是下一次嘗試的時間。現在仔細看,我認爲你的救援不會被調用,因爲Like對象不存在。將send_push_notifications重新定義爲類方法,而不是實例方法,則即使對象不存在,delayed_job也可以調用它。如果您需要更多解釋,我會編輯答案。 – pduey 2013-04-19 13:44:22

+0

更多的澄清,將不勝感激。我可以告訴你,我正在檢查重試屬性,它在這些作業上是「0」,而在其他失敗的作業中,我確實看到多次退役。 – pejmanjohn 2013-04-19 17:15:54