1

我正在使用collectiveidea/delayed_job 来延迟我的课程模型中的makesandwich 方法。它在开发中运行良好,但在生产中运行时会出现以下错误:

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"
4

3 回答 3

0

它很可能在实际提交到数据库之前被后台作业拾取。尝试将您的回调更改为after_commit

after_commit do |lesson|
  lesson.makesandwich
end

您也可以只向它发送您要执行的方法的符号:

after_commit :makesandwich

这里有一些资源描述了为什么应该使用 after_commit 而不是 after_save/ceate:

于 2013-01-13T22:14:27.107 回答
0

我认为这个问题与:

使用 Thin 或 Unicorn 在生产中运行延迟作业时,作业处理程序序列化不正确

我遇到了同样的问题 - 我猜你的宝石没有被很好地锁定(我认为这也是我的问题)

于 2013-04-06T01:24:27.503 回答
0

我可以通过将我的应用程序设置为在 Heroku 上使用 Unicorn 来解决这个问题。(我假设您使用的是 Heroku……至少示例日志是这样的。)我遵循了Heroku 指南的“Web 服务器”部分。

接下来(我认为这是关键部分)我添加worker: bundle exec rake jobs:work延迟作业(DJ)Procfile中指定的内容中,并且延迟作业开始按预期工作,没有其他代码更改。

于 2013-07-02T05:55:29.157 回答