2013-01-13 61 views
1

我正在使用collectiveidea/delayed_job來延遲我的Lesson模型中的makesandwich方法。它工作正常發展,但給人當生產運行下面的錯誤:如何在使用delayed_job時修復「NilClass#after錯誤」錯誤?

Worker(host:b75643e6-bc2b-4f9f-97ff-b31aa3c50b0f pid:2)] Starting job worker 
[Worker(host:b75643e6-bc2b-4f9f-97ff-b31aa3c50b0f pid:2)] NilClass# completed after 0.0095 
[Worker(host:b75643e6-bc2b-4f9f-97ff-b31aa3c50b0f pid:2)] 1 jobs processed at 5.5022 j/s, 0 failed ... 

我怎樣才能解決這個問題?

這裏是我的模型和方法:

#encoding: utf-8 

class Lesson < ActiveRecord::Base 
    attr_accessible :content, :title, :parsed_content, :html_content, :user_id 

    serialize :parsed_content, Array 
    serialize :html_content, Array 
    serialize :pinyin_content, Array 
    serialize :defined_content, Array 
    serialize :literal_content, Array 

    validates :title, :presence => true 
    validates :content, :presence => true 

    belongs_to :user 

    #before_update do |lesson| 
    # lesson.makesandwich 
    #end 

    after_create do |lesson| 
     lesson.makesandwich 
    end 

    def makesandwich 

     require 'rmmseg' 
                 #require 'to_lang' 
     require 'bing_translator' 
     require 'ruby-pinyin' 

     self.parsed_content = [] 

     RMMSeg::Dictionary.load_dictionaries 

     content    = self.content 
     paragraphs   = content.split(/\r\n\r\n/) #convert to array of paragraphs 
     self.parsed_content = paragraphs 
     paragraphs.each_with_index do |text, ti| 

      text = text.gsub("。", "^^.") 
      text = text.gsub("?", "~~?") 
      text = text.gsub("!", "||!") 
      text = text.gsub(":", ":") #fix missing colons 

      text = text.split(/[.?!]/u) #convert to an array 
      text.each do |s| 
       s.gsub!("^^", "。") 
       s.gsub!("~~", "?") 
       s.gsub!("||", "!") 
       #s.gsub!("———————————",":") 
      end 

      text.each_with_index do |val, index| 
       algor  = RMMSeg::Algorithm.new(text[index]) 
       splittext = [] 
       loop do 
        tok = algor.next_token 
        break if tok.nil? 
        tex = tok.text.force_encoding('UTF-8') 
        splittext << tex 
        text[index] = splittext 
       end 
       paragraphs[ti] = text 
      end 
     end 
     bing     = BingTranslator.new('8bacb905-c59b-4363-bbf5-89ef2c32c26e', 'g82QvinzO7GhmP7qJQpfxTMXzClSGX3yiPcsedFDXYQ=') 
     self.parsed_content = paragraphs 
     textarray   = Marshal.load(Marshal.dump(paragraphs)) 
     self.defined_content = Marshal.load(Marshal.dump(paragraphs)) 
     self.literal_content = Marshal.load(Marshal.dump(paragraphs)) 
     self.pinyin_content = Marshal.load(Marshal.dump(paragraphs)) 
     textarray.each_with_index do |paragraph, pi| 
      paragraph.each_with_index do |sentence, si| 
       sentence.each_with_index do |word, wi| 
        if DictionaryEntry.find_by_simplified(word) != nil 
         self.defined_content[pi][si][wi] = DictionaryEntry.find_by_simplified(word).definition 
         #self.literal_content is down below 
         self.pinyin_content[pi][si][wi] = DictionaryEntry.find_by_simplified(word).pinyin 
        else 
         self.defined_content[pi][si][wi] = bing.translate(word, :from => 'zh-CHS', :to => 'en') 
         #self.defined_content[pi][si][wi] = word 
         #self.literal_content is down below 
         if PinYin.of_string(word, true).length > 1 #for punctuation 
          self.pinyin_content[pi][si][wi] = PinYin.of_string(word, true).join(" ").downcase 
         else 
          self.pinyin_content[pi][si][wi] = word 
         end 
        end 
       end 
      end 
     end 

     #Literal 
     literalarray = Marshal.load(Marshal.dump(paragraphs)) 
     literalarray.each_with_index do |paragraph, pi| 
      paragraph.each_with_index do |sentence, si| #iterate array of sentence 
       literalarray[pi][si] = [] 
       sentence.each_with_index do |word, wi| #iterate sentence's array of words 
        entrytobesliced = DictionaryEntry.find_by_simplified(word) 
        slicedentry  = [] 

        if entrytobesliced == nil 
         if word.length > 1 && word !~ /\w/ #/^\s*\w\d+\s*$/ #number regex #for cases where there is no DictionaryEntry 
          split  = [] 
          wordarray = word.split("").each_with_index() do |ws, wsi| 
           split << [DictionaryEntry.find_by_simplified(ws).definition] 
          end 
          literalarray[pi][si] << split 
         else 
          literalarray[pi][si] << [word] #in case none of the above work 
         end 
        else 
         entrytobesliced.simplified.each_char do |w| 
          singlechar = DictionaryEntry.find_by_simplified(w) 
          slicedentry << singlechar.definition.split("\", \"") 
         end 
         literalarray[pi][si] << slicedentry 
        end 
        self.literal_content = literalarray #slicedentry #literalarray 
       end 
      end 
     end 
     self.save 
    end 
    handle_asynchronously :makesandwich 
end 

這裏是工作在數據庫中是什麼樣子:

irb(main):012:0> job 
=> #<Delayed::Backend::ActiveRecord::Job id: 5, priority: 0, attempts: 0, handler: "--- !ruby/object:Delayed::PerformableMethod\nattribu...", last_error: nil, run_at: "2013-01-13 19:42:38", locked_at: nil, failed_at: nil, locked_by: nil, queue: nil, created_at: "2013-01-13 19:42:38", updated_at: "2013-01-13 19:42:38"> 

這裏是處理:

irb(main):011:0> job.handler 
=> "--- !ruby/object:Delayed::PerformableMethod\nattributes:\n id: 14\n title: test\n content: ! \"1最初,上帝創造了天地。\\r\\n\\r\\n2大地混沌蒼茫,深淵的表面一片黑暗。上帝發出的動力運行在水面上。\\r\\n\\r\\n3上帝說:「要有光。」光就出現了。4上帝看光是好的。上帝把光暗分開了。5上帝稱光爲「晝」,稱暗爲「夜」。過了晚上,到了早晨,是第一日。\\r\\n\\r\\n6上帝說:「水和水之間要有天空,把水上下分開。」7於是上帝造出天空把水分開,天空以下有水,天空以上也有水。事就這樣成了。8上帝稱天空爲「天」。過了晚上,到了早晨,是第二日。\\r\\n\\r\\n9上帝說:「天下的水要聚在一處,讓陸地露出來。」事就這樣成了。10上帝稱陸地爲「地」,稱聚起來的水爲「海」。上帝看這是好的。11上帝說:「地要長出青草和結種子的植物,又要長出結果子的樹木,各按其類;果子裏要有種子,在地上生長。」事就這樣成了。12地上長出青草和結種子的植物,各按其類;又長出結果子的樹木,果子裏都有種子,各按其類。上帝看這是好的。13過了晚上,到了早晨,是第三日。\\r\\n\\r\\n14上帝說:「天空要有光源,可以分晝夜,做記號,定季節、日子、年月。15光源要在天空普照大地。」事就這樣成了。16上帝造出兩大光源,大的管晝,小的管夜,又造星星。17上帝把光源放在天空,普照大地,18支配晝夜,分開光暗。上帝看這是好的。19過了晚上,到了早晨,是第四日。\\r\\n\\r\\n20上帝說:「水裏要涌現成羣的活物,地上要有飛禽在天空飛翔。」21於是上帝創造巨大的海獸,使水裏涌現各樣遊動的活物,各按其類;又創造各種有翅膀的飛禽,各按其類。上帝看這是好的。22上帝賜福給這些活物說:「要繁衍增多,充滿海洋;飛禽也要在地上增多。」23過了晚上,到了早晨,是第五日。\\r\\n\\r\\n24上帝說:「地要生出活物來,各按其類,就是牲畜、爬行的動物、地上的走獸,各按其類。」事就這樣成了。25上帝造出地上的走獸,各按其類;牲畜,各按其類;地上各樣爬行的動物,各按其類。上帝看這是好的。\\r\\n\\r\\n26上帝說:「我們要照我們的形像、按我們的樣式造人,讓他們管理海里的魚、天上的飛禽、地上的牲畜,以及全地和地上各樣爬行的動物。」27於是上帝照自己的形像創造人,就是照上帝的形像把人創造出來。上帝創造了男人和女人。28上帝賜福給他們,對他們說:「要繁衍增多,遍滿地面,開拓大地,也要管理海里的魚、天上的飛禽和地上各樣爬行的活物。」\\r\\n\\r\\n29上帝說:「全地上各樣結種子的植物和各樣結種子的果樹,我都賜給你們做食物。30至於地上各樣的走獸、天上各樣的飛禽、地上各樣有生命的爬行動物,我把一切青菜綠葉都賜給它們吃。」事就這樣成了。\\r\\n\\r\\n31上帝看他所造的一切,都非常好。過了晚上,到了早晨,是第六日。\"\n created_at: 2013-01-13 19:42:38.696201148 Z\n updated_at: 2013-01-13 19:42:38.696201148 Z\n parsed_content: []\n html_content: []\n literal_content: []\n pinyin_content: []\n defined_content: []\n user_id: 1\n" 

回答

0

很可能在它實際提交到數據庫之前被後臺作業拾取。試着改變你的回調after_commit

after_commit do |lesson| 
    lesson.makesandwich 
end 

你也可以發送一個符號的方法要執行:

after_commit :makesandwich 

這裏有一些資源描述爲什麼要使用after_commit代替after_save的/ ceate:

+0

我嘗試了你的建議,但它仍然無法工作。我不明白爲什麼它會在開發中起作用,但不在heroku上。 – webmagnets

+0

本地數據庫可能在開發中更快,因爲它沒有任何負載。這裏有一些資源http://rails-bestpractices.com/posts/695-use-after_commit和http://alindeman.github.com/2011/10/02/after-save-and-background-jobs。 html –

+0

謝謝,但將其更改爲after_commit沒有幫助。你有沒有其他想法可以探索? – webmagnets

0

我能夠通過設置我的應用程序在Heroku上使用Unicorn來解決這個問題。 (我假設你正在使用Heroku ...至少這就是示例日誌的樣子)。我遵循this Heroku guide的「Web Server」部分。

接下來(我認爲這是關鍵部分)我將worker: bundle exec rake jobs:work添加到Procfile中,如Delayed Job (DJ)中所述,並且delayed_job按照預期開始工作,沒有其他代碼更改。

相關問題