2011-02-02 78 views
1

我有一長串物品清單。旁邊有一個複選框。有一個jQuery check-all函數,但是當我一次提交所有這些函數時,請求會超時,因爲它正在執行一堆查詢,並在MySQL數據庫中爲每個項目插入一堆記錄。如果不是超時,那可能需要大約20分鐘。相反,我一次只提交30個。Ruby on Rails超時。我如何分叉進程?

我希望能夠檢查所有並提交,然後繼續做其他工作。我的同事(1)說我應該寫一個耙子任務。我這樣做了,但是我最終重複了代碼,並且我更喜歡用戶界面,因爲如果我想取消選中幾個,該怎麼辦?耙子任務只是提交它們。

另一位同事(2)推薦我使用叉子。他說,這會產生一個新的進程在服務器上運行,但允許服務器在完成之前做出響應。然後,由於項目在提交後消失,我可以刷新頁面以檢查它們是否完成。

我在我的本地嘗試了這個,但是,它似乎仍然在等待該過程完成,然後它才響應HTML表單發送的POST請求。該代碼我用看起來像這樣:

def bulk_apply 
    pid = fork do 
    params[:ids].each do |id| 
     Item.find(id).apply # takes a LONG time, esp. x 100 
    end 
    end 
    Process.detach(pid) # reap child process automatically; don't leave running 
    flash[:notice] = "Applying... Please wait... Then, refresh page. Only submit once. PID: #{pid}" 
    redirect_to :back 
end 

同事1表示,一般你不希望到餐桌的Rails,因爲叉創建一個子進程,基本上是Rails的過程中的一個副本。他說,如果你想通過網絡圖形用戶界面來完成,使用BackgroundJob(Bj)(因爲我們已經在我們的Rails應用中使用了它)。所以,我現在正在研究BackgroundJob,但你推薦什麼?

回答

2

我使用後臺工作取得了很好的成功。如果您需要導軌,您將使用腳本/運行器,該腳本仍然啓動一個帶有導軌的新過程。好事是Backround Job將確保一次只能運行一個以上的程序。

您也可以直接使用腳本運行,甚至在後臺運行rake任務,像這樣:

system " RAILS_ENV=#{RAILS_ENV} ruby #{RAILS_ROOT}/script/runner 'CompositeGrid.calculate_values(#{self.id})' & " unless RAILS_ENV == "test" 

的符號告訴它,開始一個新的進程。要小心,因爲你可能不希望一堆這些在同一時間運行。如果它已經可用,我肯定會利用後臺工作。

+0

如何將散列作爲參數傳遞給BackgroundJob? – ma11hew28 2011-02-07 02:59:32

2

你應該檢查出IronWorker。做你想做的事情會非常容易,無論多久都不重要。

在您的操作中,您只需實例化一個具有正在執行所有數據庫查詢的代碼的worker。例如工人:

Item.find(id).apply # takes a LONG time, esp. x 100 

下面是你會怎麼排隊的作業並行運行:

client = IronWorkerNG::Client.new 
ids.each do |id| 
    client.tasks.create("MyWorker", "id"=>id) 
end 

這就是所有你需要做的,鐵工負責剩下的照顧。

+0

太棒了,只是試了一下! – 2012-08-15 22:29:28

0

嘗試delayed_job寶石。這是一個基於數據庫的後臺作業寶石。我們在電子商務網站上使用它。例如,向用戶發送訂單確認電子郵件是延遲工作的理想人選。

此外,您可以嘗試多線程,它受Ruby支持。這可能會讓事情運行得更快。由於內存的使用,分叉整個過程往往很昂貴。