def worker_finish
#message the user
end
def worker_finish
#message the user
end
我认为你可能没有理解后台工作的重点,基本上,你试图做的是自我打败的。-- 如果用户提交表单并且您在控制器中将作业排队,只是让用户等待工作程序启动和完成,那么您不仅实现了控制器本来可以独立完成的任务,而且还使整个过程变得更加复杂(这种类型的功能既不内置于Resque,也不内置于Sidekiq)。
当将作业卸载到队列以进行处理时,您希望立即向客户端返回响应,即
class PostsController < ApplicationController
def create
@post = Post.create(params[:post])
BackgroundBlogOperation.enque(@post.id)
respond_with(@post)
end
end
BackgroundBlogOperation 类将被放置到队列中,供工作线程处理。如果在完成后需要 BackgroundBlogOperation 工作线程执行其他操作,则应该在任务本身中进行,在这样做的情况下,工作线程可以负责处理。
如果您只想在创建文章后显示和隐藏旋转图标,而不需要重新加载页面,只需在提交按钮点击之前显示 JavaScript 旋转图标,并确保请求类型为 js(向表单添加 :remote => true)。然后创建一个类似于以下内容的 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();
现在,虽然你最初所询问的内容没有任何意义(因为要在控制器完成操作后显示和隐藏旋转图标需要等待),但是在某些情况下,向客户端显示作业已经完成处理是有用的。
首先,让我们定义一个实际应用后台处理的场景。假设您有一个按钮,当单击该按钮时,将从某个外部 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)通过电子邮件通知用户(在我看来通常是最差的选择) 2)使用某种支持html5或websocket的rails服务器运行rails,并通过websocket向客户端发送推送,虽然非常酷,但在大多数情况下过于繁琐并且超出了这个回答的范围。如果您想查看选项,请搜索rails websocket pushing。 3)在大多数情况下,我认为最好的选项是创建一个通知模型来处理各种用户通知,在作业完成后,例如执行以下操作:
Notification.create(:user_id => user.id, :message => 'Sync has finished', type => 'sync_complete')
然后,当用户请求下一页时,在页面顶部工具栏或其他位置,我会提示用户有未读通知,以便提醒用户点击它。
--- 此外,我认为在您的帖子中您提到了您正在使用resque。我尝试过resque,它还不错,但是我发现在生产环境中调试过于复杂,并且它使用的内存非常高 - 我建议您检查一下sidekiq,如果您还没有使用过,它也使用redis,但由于使用线程,因此速度要快得多:
https://github.com/mperham/sidekiq
它更快,更干净,而且易于设置,个人认为。