2011-02-02 77 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支持。这可能会让事情运行得更快。由于内存的使用,分叉整个过程往往很昂贵。