我在 Rails 中有一个应用程序,我想做的是在用户从一个特定页面导航到另一个页面时异步执行数据库存储过程 - 用户必须在存储过程运行时继续导航。
当程序完成时,我真的不需要回调,我只需要在后台运行它。
我正在尝试使用以下代码:
require 'eventmachine'
require 'em-http'
require 'fiber'
def async_fetch(url)
f = Fiber.current
http = EventMachine::HttpRequest.new(url).get :timeout => 10
http.callback { f.resume(http) }
http.errback { f.resume(http) }
return Fiber.yield
end
EventMachine.run do
Fiber.new{
url = url_for :controller => 'common', :action => 'execute_stored_procedure'
data = async_fetch(url)
EventMachine.stop
}.resume
end
这里的问题是,当存储过程启动时,用户必须被重定向到另一个页面,但下一页仍然“待定”并且仅在过程完成时呈现。
我尝试使用thin(在我的开发环境中)作为我的服务器,带有--threaded 选项但没有成功,现在我正在考虑在生产服务器中以多线程模式使用Phusion Passenger Enterprise,但它是商业版本并且它确实没有任何试验,恐怕不是我需要的。
有人知道实现这一目标的好方法吗?要执行存储过程,我必须向我的应用程序正在运行的同一个网络服务器发出请求,所以我的网络服务器必须一次接受多个连接(多线程),对吗?
一些有用的信息:
- 红宝石 1.9.3p385
- 导轨 3.2.13
- SQL Server 2012
发展:
- Linux lucid32 2.6.32-45-generic #102-Ubuntu (vagrant machine)
- 瘦网络服务器
生产:
- Linux debian 2.6.32-5-xen-amd64
- 阿帕奇 / Phusion 乘客
我真的很感激任何帮助。
更新#1
我按照杰西的建议尝试了赛璐珞。这是我的代码:
require 'celluloid/autostart'
class PropertyWorker
include Celluloid
def engage(args)
ActiveRecord::Base.execute_procedure("gaiainc.sp_ins_property_profiles", args[:id])
end
end
...
def create
@property = Property.new(params[:property])
respond_to do |format|
if @property.save
PropertyWorker.new.async.engage({:id => @property.id})
format.html { redirect_to new_enterprise_property_activation_url(@property.enterprise.id, @property.id) }
format.json { render json: @property, status: :created, location: @property }
else
format.html { render action: "new" }
format.json { render json: @property.errors, status: :unprocessable_entity }
end
end
end
然后调用“create”操作时,创建记录,存储过程启动但不呈现下一页,请求在浏览器中保持“待处理”,直到过程完成。一旦过程完成,页面就会被渲染。
我不知道发生了什么。该程序不应该在后台运行吗?