2012-08-13 60 views
9

我有一個標記爲被delayed_job的異步處理功能:傳遞一個功能塊到delayed_job的

class CapJobs 
    def execute(params, id) 
    begin 
     unless Rails.env == "test" 
     Capistrano::CLI.parse(params).execute! 
     end 
    rescue 
     site = Site.find(id) 
     site.records.create!(:date => DateTime.now, :action => "Task Failure: #{params[0]}", :type => :failure)  
     site.save 
    ensure 
     yield id 
    end 
    end 
    handle_asynchronously :execute 
end 

當我運行這個功能我傳遞一個塊:

capjobs = CapJobs.new 
capjobs.execute(parameters, @site.id) do |id| 
    asite = Site.find(id) 
    asite.records.create!(:date => DateTime.now, :action => "Created", :type => :init) 
    asite.status = "On Demo" 
    asite.dev = true 
    asite.save 
end 

該作品罰款時,沒有delayed_job的運行,但是當運行它,我得到以下錯誤

2012-08-13T09:24:36-0300: [Worker(delayed_job host:eagle pid:12089)] SitesHelper::CapJobs#execute_without_delay failed with LocalJumpError: no block given (yield) - 0 failed attempts 
2012-08-13T09:24:36-0300: [Worker(delayed_job host:eagle pid:12089)] PERMANENTLY removing SitesHelper::CapJobs#execute_without_delay because of 1 consecutive failures. 
2012-08-13T09:24:36-0300: [Worker(delayed_job host:eagle pid:12089)] 1 jobs processed at 0.0572 j/s, 1 failed ... 

看起來沒有回暖傳入的塊。這是不是這樣做的正確方法,或者我應該找到一種不同的方法?

回答

1

我找到了一個這樣做的方法。這是一種哈克,但運作良好。我發現this article談論創建一個SerializableProc類。如果我把它傳遞給函數,那麼一切都很好。

+2

你能請張貼你使用什麼碼? – brauliobo 2014-11-02 23:39:26

8

delayed_job通過將作業保存到數據存儲區(通常是主數據庫)中工作,然後將作業從後臺進程加載到後臺進程中,並在其中進行處理/執行。

要將作業保存到數據庫中,delayed_job需要以某種方式保存使用哪些參數調用哪個對象的方法。這是通過將所有內容序列化爲一個字符串來完成的(delayed_job使用yaml)。不幸的是,塊不能被序列化。所以後臺工作人員不知道block參數,並在沒有它的情況下調用該方法。當方法試圖屈服於塊時,這導致LocalJumpError

0

大多數人會將此視爲抽象問題。

proc代碼可能不會從run-to-run(除了vars之外)發生改變,因此您應該將塊代碼放入類或實例方法中。傳遞方法的名稱,然後把它在你的execute方法,像

@some_data = CapJobs.send(target_method)

或許,更好,甚至

@some_data = DomainSpecificModel.send(target_method)