在 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_performafter_perform 作业挂钩可用于移动 Task状态到running然后到completed.

after_perform hook可以用来通知客户。该应用程序将如何执行此操作取决于您。例如,Dropbox 在下载大量文件时使用类似的系统。他们排队工作,压缩文件,然后在工作完成后发送电子邮件下载 link。

另一种方法是使用应用内通知系统。

最后,要在不需要用户刷新页面的情况下弹出通知,您必须使用 ActiveCable 并将通知推送回用户,再次使用 after_perform 钩子.

我会建议 sidekiq 作为后台任务的更好的解决方案