在 Rails 5 中 运行 后台进程的最佳方式是什么?
What is the best way to run a background process in Rails 5?
我有一个 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
Rails 使用 ActiveJob,它允许您在后台排队昂贵的任务并 运行 它们。它们使用起来非常简单。
拳头,你可以使用rails生成器创建一个:
rails generate job slow_algorithm
...这将在 app/jobs/slow_algorithm_job.rb
下创建一个工作。在那里,您可以实现您的算法逻辑。
排队工作同样简单,只需在您的控制器中执行即可:
SlowAlgorithmJob.perform_later
您需要介绍的最后一件事是设置实际上 运行 作业的排队后端。 Rails 支持其中的几个。可能最简单的设置是 delayed_job, but if you're looking for something more scalable, I'd recommend looking into Sidekiq.
编辑: 如何通知用户作业已完成?
为了做到这一点,您显然必须以某种方式跟踪任务的进度。一个可能的方向是创建一条记录,我们称它为 Task
,它代表您的算法的一次调用。
当用户触发应排队作业的操作时,将创建状态为 pending
的任务记录,然后 before_perform
和 after_perform
作业挂钩可用于移动 Task
状态到running
然后到completed
.
after_perform
hook可以用来通知客户。该应用程序将如何执行此操作取决于您。例如,Dropbox 在下载大量文件时使用类似的系统。他们排队工作,压缩文件,然后在工作完成后发送电子邮件下载 link。
另一种方法是使用应用内通知系统。
最后,要在不需要用户刷新页面的情况下弹出通知,您必须使用 ActiveCable
并将通知推送回用户,再次使用 after_perform
钩子.
我会建议 sidekiq 作为后台任务的更好的解决方案
我有一个 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
Rails 使用 ActiveJob,它允许您在后台排队昂贵的任务并 运行 它们。它们使用起来非常简单。
拳头,你可以使用rails生成器创建一个:
rails generate job slow_algorithm
...这将在 app/jobs/slow_algorithm_job.rb
下创建一个工作。在那里,您可以实现您的算法逻辑。
排队工作同样简单,只需在您的控制器中执行即可:
SlowAlgorithmJob.perform_later
您需要介绍的最后一件事是设置实际上 运行 作业的排队后端。 Rails 支持其中的几个。可能最简单的设置是 delayed_job, but if you're looking for something more scalable, I'd recommend looking into Sidekiq.
编辑: 如何通知用户作业已完成?
为了做到这一点,您显然必须以某种方式跟踪任务的进度。一个可能的方向是创建一条记录,我们称它为 Task
,它代表您的算法的一次调用。
当用户触发应排队作业的操作时,将创建状态为 pending
的任务记录,然后 before_perform
和 after_perform
作业挂钩可用于移动 Task
状态到running
然后到completed
.
after_perform
hook可以用来通知客户。该应用程序将如何执行此操作取决于您。例如,Dropbox 在下载大量文件时使用类似的系统。他们排队工作,压缩文件,然后在工作完成后发送电子邮件下载 link。
另一种方法是使用应用内通知系统。
最后,要在不需要用户刷新页面的情况下弹出通知,您必须使用 ActiveCable
并将通知推送回用户,再次使用 after_perform
钩子.
我会建议 sidekiq 作为后台任务的更好的解决方案