def worker_finish #message the user end
解决方法
卸载要由队列处理的作业时,您希望立即向客户端返回响应,即
class PostsController < ApplicationController def create @post = Post.create(params[:post]) BackgroundBlogoperation.enque(@post.id) respond_with(@post) end end
然后将BackgroundBlogoperation类放入队列中,供工作人员完成并处理.如果您需要BackgroundBlogoperation工作程序在完成之后执行其他操作,则可以执行此操作,但这应该在作业本身内进行,以便工作人员可以对此负责.
如果您只是在创建帖子后尝试显示和隐藏微调器,而不重新加载页面,只需在单击提交按钮之前显示javascript微调器,并确保请求类型为js(add:remote => true to形成).然后创建一个javascript视图响应,如下所示:
class PostsController < ApplicationController respond_to :js,:only => [:create] def create @post = Post.create(params[:post]) BackgroundBlogoperation.enque(@post.id) respond_with(@post) end end
而create.js.erb也可以附加一条消息,告诉他们你在后台做的任何事情都已排队,如果它比创建帖子或其他更复杂.
$("#spinner").hide();
现在 – 虽然你最初要求doesent用于任何目的(因为在完成工作时显示和隐藏微调器需要等待控制器完成操作) – 有些情况下向客户端显示该工作已经完成处理是有用的.
首先,我们定义一个后台处理实际有用的场景.假设您有一个按钮,当单击时,将从某些外部API中提取数据,并在从外部站点获取数据后,您正在根据响应执行数据库操作.这将是何时使用后台进程的一个很好的例子.基本上在控制器中,您可以执行以下操作:
class ApiController < ApplicationController respond_to :js,:only => [:create] def sync_tweets TwitterApiJob.enque(current_user.twitter_username) respond_with(message: 'Syncing Tweets') end end
现在,告诉用户推文完成同步的时间有点复杂,你有3个基本选项:
1)通过电子邮件通知用户(通常最差的选项imo)
2)使用某种html5或支持websocket的rails服务器来运行rails,并通过websocket向客户端发送推送,虽然非常酷,但在大多数情况下都是过度杀伤并超出了此响应的范围.如果你想看到你的选择,谷歌会推动websocket推送.
3)对于大多数情况,IMO最佳选择,创建一个通知模型来处理各种用户通知,并在工作中,在工作完成后,执行类似的操作
Notification.create(:user_id => user.id,:message => 'Sync has finished',type => 'sync_complete')
然后,用户请求的下一页,在标题工具栏或任何地方,我会注意到用户有未读通知,提醒用户点击它.
—我想在你提到的帖子中你使用的是resque.我尝试了resque并且它很不错,但是我发现它在生产中调试过于复杂,并且它使用了疯狂的内存 – 我建议你查看sidekiq如果你还没有,它使用redis也可以更快,因为它使用主题:
https://github.com/mperham/sidekiq
它更快,更清洁,更容易安装,imho.