我有一个Web应用程序,需要执行一段时间(通常需要1分钟)才能完成该过程。
我将尝试简要地解释一下:在我的应用程序中,我有一种算法,该算法基于一堆参数(主要是日期)将外键分配给一组对象。当用户按下应用程序内的指定按钮时,将执行控制器方法。在该方法内部,我调用模型中的一种方法,在该方法中处理了所有逻辑并分配了键。如前所述,整个过程大约需要一分钟才能完成。
所以我的问题是:在Rails 5中在后台运行此过程的最佳方法是什么?我显然不想强迫我的用户等待一分钟,然后他们才能浏览应用程序,并且我也不希望浏览器在等待服务器响应时应用程序超时。那么解决这个问题的最佳方法是什么?我需要一个可以异步发出请求的框架吗?如果是这样,哪一个? (我希望它不需要太多的依赖关系,并且我可以继续使用ActiveRecord)。
我在ActionCable或AJAX方面并没有做太多工作,但是如果他们能以任何方式完成工作,那么我将很高兴知道如何做。
理想情况下,完成该过程后,我应该能够在应用内向用户发送通知
view.html.erb:
# Button the user presses to execute the algorithm
<%= link_to 'execute algorithm', algorithm_path(@variable), :method => :put %>
my_controller.rb:
def button_method
Object.execute_algorithm(@variable)
redirect_to :back
end
Object.rb:
def self.execute_algorithm(variable)
# Logic
end
答案 0 :(得分:4)
Rails使用ActiveJob,它使您可以将昂贵的任务排队并在后台运行它们。它们非常易于使用。
拳头,您可以使用rails生成器创建一个:
rails generate job slow_algorithm
...这将在app/jobs/slow_algorithm_job.rb
下创建工作。在那里,您可以实现算法逻辑。
排队工作同样简单,只需在您的控制器中完成
:SlowAlgorithmJob.perform_later
您需要介绍的最后一件事是设置将实际运行作业的后端队列。 Rails支持其中的几个。可能最简单的设置是delayed_job,但是如果您正在寻找更具扩展性的东西,建议您使用Sidekiq。
编辑:如何通知用户作业已完成?
为此,您显然必须以某种方式跟踪任务的进度。一个可能的方向是创建一条记录,我们称它为Task
,它代表算法的一次调用。
当用户触发应使作业排队的操作时,将创建状态为pending
的任务记录,然后可以使用before_perform
和after_perform
作业挂钩来移动{{1 }}状态更改为Task
,然后更改为running
。
completed
挂钩可用于通知客户。应用程序将如何执行,取决于您。例如,Dropbox在下载大量文件时使用类似的系统。他们将工作排队,压缩文件,然后在完成工作后发送带有下载链接的电子邮件。
另一种方法是使用应用内通知系统。
最后,要弹出通知而不需要用户刷新页面,您必须使用after_perform
并再次使用ActiveCable
钩子将通知推回用户。 / p>
答案 1 :(得分:1)
我会建议sidekiq作为针对后台任务的更好的解决方案