后台工作进程在Rails应用程序中的通信视图

9
假设我有一个带有文章的博客应用程序。在创建了一篇文章之后,会创建一个工作线程来处理一些后台操作。我的情况是,在提交文章表单之后,我想显示某种加载消息(GIF加载器或类似内容),当工作者完成工作后,我想隐藏加载消息并显示工作者提供的一些数据。我的问题是,如何最好地通知用户工作者已经完成了它的工作,并在前台上显示它。工作者回调函数大致如下:
def worker_finish
  #message the user
end
1个回答

13

我认为你可能没有理解后台工作的重点,基本上,你试图做的是自我打败的。-- 如果用户提交表单并且您在控制器中将作业排队,只是让用户等待工作程序启动和完成,那么您不仅实现了控制器本来可以独立完成的任务,而且还使整个过程变得更加复杂(这种类型的功能既不内置于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

它更快,更干净,而且易于设置,个人认为。


虽然所提供的使用案例可能不是理想的,但该功能在运行报告时非常有用。 - aaandre

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接