在资源准备好之前创建新资源并且需要执行一些冗长处理时,如何将该处理从发送到后台所在的位置< em>不会阻止当前请求或其他流量到我的网络应用程序?
在我的模型中:
class User < ActiveRecord::Base
after_save :background_check
protected
def background_check
# check through a list of 10000000000001 mil different
# databases that takes approx one hour :)
if( check_for_record_in_www( self.username ) )
# code that is run after the 1 hour process is finished.
user.update_attribute( :has_record )
end
end
end
答案 0 :(得分:39)
您一定要查看以下Railscast:
他们解释了如何以各种可能的方式在Rails中运行后台进程(有或没有队列......)
答案 1 :(得分:7)
开始一个单独的过程,这可能最容易用system
完成,在'nohup'之前加上'&amp;'到你传递它的命令的末尾。 (确保命令只是一个字符串参数,而不是参数列表。)
有几个原因你想这样做,而不是试图使用线程:
在执行I / O时,Ruby的线程可能有点棘手;你必须注意你做的一些事情不会导致整个过程被阻止。
如果你运行一个名字不同的程序,它很容易在'ps'中识别出来,所以你不会意外地认为它是一个疯狂的后端,或者杀了它。
真的,你开始的过程应该是“deamonized”,请参阅Daemonize课程寻求帮助。
答案 2 :(得分:6)
我刚刚尝试使用'delayed_job'宝石,因为它与Heroku托管平台配合使用,设置非常简单!
将gem添加到Gemfile,bundle install
,rails g delayed_job
,rake db:migrate
然后启动队列处理程序;
RAILS_ENV=production script/delayed_job start
你有一个方法调用,这是你漫长的过程,即
company.send_mail_to_all_users
你把它改成了;
company.delay.send_mail_to_all_users
检查github上的完整文档:https://github.com/collectiveidea/delayed_job
答案 3 :(得分:2)
理想情况下,您希望使用现有的后台作业服务器,而不是自己编写。这些通常会让你提交一份工作并给它一个独特的钥匙;然后,您可以使用该密钥定期向作业服务器查询作业状态,而不会阻止您的Web应用程序。 here is a nice roundup各种各样的选择。
答案 4 :(得分:1)
我喜欢使用backgroundrb,它很好,它允许你在长时间的过程中与它进行通信。因此,您可以在rails应用程序中进行状态更新
答案 5 :(得分:1)
我认为spawn是分叉流程,在后台进行一些处理以及向用户显示此处理已启动的确认方式的好方法。
答案 6 :(得分:0)
怎么样:
def background_check
exec("script/runner check_for_record_in_www.rb #{self.username}") if fork == nil
end
程序“check_for_record_in_www.rb
”将在另一个进程中运行,并且可以访问ActiveRecord,从而能够访问数据库。