我正在使用最新版本的rails和ruby。通过表单,我导入一个CSV,然后触发异步作业(我正在使用gem https://github.com/brandonhilkert/sucker_punch)来读取文件并处理数据。
总而言之,一切正常,但是:
我的问题是,如何在后台工作完成时让控制器知道?我想用闪光灯通知重定向,但显然我不应该从模型中做到这一点......我能在这做什么?
这是我的sucker_punch工作:
#app/jobs/import_job.rb
class ImportJob
include SuckerPunch::Job
def perform(import_file)
ActiveRecord::Base.connection_pool.with_connection do
ModelName.import_from_csv(import_file)
end
end
end
这是我的控制器动作:
def import
ImportJob.new.async.perform(import_file)
redirect_to list_data_path, notice: 'Data being imported...'
# i get sent to list_data_path and i stay there even though the background job already finished successfully
end
答案 0 :(得分:3)
对于这种任务,我会创建一个模型(ActiveRecord)来保存作业的状态(等待,处理,完成并可能是进度),并从控制器查询模型以呈现使用导入作业状态。
答案 1 :(得分:0)
Web应用程序严格按照“拉”模式运行。客户端发送请求,服务器响应。当您重定向到list_data_path时,那就是您的服务器响应。在收到其他请求之前,您无法发送其他回复。
这意味着,服务器无法联系客户并说“嘿,我已经完成了!”你需要做的是在客户端放一些Javascript来询问服务器,“你还没完成?”这使服务器有机会回答“是的,我已经完成”或“不,仍在工作。”
这是使用JQuery的一个简单的例子:
function processJob(jobId) {
$.ajax({
url: "path/to/job/status/" + jobId,
success: function(result) {
alert("Job done!");
window.location("path/to/completed/job/" + jobId);
},
error: function(req, statusText, err) {
if(req.status == 202)
setTimeout(function() { processJob(jobId); }, 2000);
}
else { alert("Error processing job."); }
});
}
在服务器端,path / to / job / status应该是在作业仍在处理时呈现状态202的路由,如果作业完成则呈现200,如果作业遇到错误则呈现500。 path / to / completed / job应该是显示已完成作业结果的路径。
当用户最初提交要处理的文件时,请在客户端调用此方法。它将静默监视作业的状态,直到完成为止,每2秒对服务器执行一次ping操作。作业完成后,它将提醒用户并在新选项卡中弹出已完成的作业。