我主要使用Node作为后端服务,但使用Ruby 1.9.3维护Rails 3.2 API。最近我们意识到在某些极端情况下,我们的FoosController#create
控制器方法需要很长时间才能使客户端在收到响应之前超时。我有类似
def create
if check_for_bad(params) # Validation step
return bad_params_error # Return 400 error
end
Foo.create(params) # Need to move this to a parallel thread
output = { status: 200, message: 'OK' }
return render json:output
end
客户端在初始params检查后不需要知道任何错误,所以我想在运行Foo#create
之前返回响应,但我确实需要将params
传递给该方法。我尝试使用after_filter
方法(尝试undefined method
时得到after_action
)。
看起来这应该很容易,可能是使用光纤或基于它构建的宝石,但我对可用的东西不够熟悉,以确保我做的工作没有造成比我更多的问题解决。
提前感谢您的帮助。
答案 0 :(得分:1)
正如@BroiSatse所提到的,我建议在Sidekiq的后台执行此操作。 Sidekiq上的指南给出了整体设置,但在这种情况下,你必须改变你对创建Foo意味着什么的一点想法。
你会立即创建一个状态为“pending”或其他东西的Foo,然后将你的params和创建的Foo id传递给后台工作者,这将完成艰苦的工作。如果一切都在那里成功,你会更新你的Foo“完成”或“准备好”。
要进行Foo创建后台工作,您需要创建一个worker:
# app/workers/CreateFooWorker.rb
class CreateFooWorker
include Sidekiq::Worker
def perform(foo_id, params)
if foo = Foo.find(foo_id) && foo.update_attributes(params)
foo.update_attribute(:state, "ready")
end
end
end
# Change create to immediately create a foo without the params
# and then actually build the real foo with params in the background
def create
if check_for_bad(params) # Validation step
return bad_params_error # Return 400 error
end
foo = Foo.create(state: "pending") # Just create with a pending state...
CreateFooWorker.perform_async(foo.id, params) # Now do the real work in the background
# You're going to want to retun the foo json here
# because your client will need to hold onto the
# foo.id and query the server for when the foo is "ready"
return render json: foo.to_json, status: created
end