简体   繁体   English

在Rails 5中运行后台进程的最佳方法是什么?

[英]What is the best way to run a background process in Rails 5?

I have a web application where I need to perform a process that takes a while to complete (Usually 1 minute). 我有一个Web应用程序,我需要在其中执行需要一段时间才能完成的过程(通常需要1分钟)。

I'll try to explain it briefly: In my app I have an algorithm that assigns foreign keys to a set of objects based on a bunch of parameters (mainly dates). 我将尝试简要地解释一下:在我的应用程序中,我有一个算法,该算法基于一堆参数(主要是日期)将外键分配给一组对象。 When a user presses the designated button inside my application a controller method is executed. 当用户按下应用程序内的指定按钮时,将执行控制器方法。 Inside that method I make a call to a method in the model where all the logic is handled and the keys are being assigned. 在该方法内部,我调用模型中的一种方法,在该方法中处理了所有逻辑并分配了键。 As mentioned before, the whole process takes about a minute to complete. 如前所述,整个过程大约需要一分钟才能完成。

So my question is: What is the best way to run this process in the background in Rails 5? 所以我的问题是:在Rails 5中在后台运行此过程的最佳方法是什么? I obviously don't want to force my users to wait an entire minute before they can navigate around the application and I also don't want the application to time out while the browser is waiting for a response from the server. 我显然不想强迫我的用户等待一分钟,然后他们才能浏览应用程序,并且我也不希望浏览器在等待服务器响应时应用程序超时。 So what's the best way to handle this? 那么解决这个问题的最佳方法是什么? Do I need a framework that can make the request asynchronously? 我需要一个可以异步发出请求的框架吗? If so, which one? 如果是这样,哪一个? (I would prefer if it doesn't require too many dependencies and if I can keep using ActiveRecord). (如果它不需要太多的依赖关系并且我可以继续使用ActiveRecord,我会更喜欢)。

I haven't really worked too much with ActionCable or AJAX, but if they can get the job done in any way, then I would be thrilled to know how. 我在ActionCable或AJAX方面并没有做太多工作,但是如果他们能以任何方式完成工作,那么我会很高兴知道如何做。

Ideally I should be able to send a notification to the user, within the app, once the process is done 理想情况下,完成该过程后,我应该能够在应用内向用户发送通知

view.html.erb: view.html.erb:

# Button the user presses to execute the algorithm
<%= link_to 'execute algorithm', algorithm_path(@variable), :method => :put %>

my_controller.rb: my_controller.rb:

def button_method
  Object.execute_algorithm(@variable)
  redirect_to :back
end

Object.rb: Object.rb:

def self.execute_algorithm(variable)
  # Logic
end

Rails uses ActiveJob , which allow you to queue up an expensive tasks and run them in the background. Rails使用ActiveJob ,它使您可以将昂贵的任务排队并在后台运行它们。 They are quite simple to use. 它们非常易于使用。

Fist, you can use rails generator to create one: 拳头,您可以使用rails generator创建一个:

rails generate job slow_algorithm

...which will create a job under app/jobs/slow_algorithm_job.rb . ...这将在app/jobs/slow_algorithm_job.rb下创建工作。 There, you can implement your algorithm logic. 在那里,您可以实现算法逻辑。

Queue up the job is just as easy, simply do it in your controller: 排队工作很容易,只需在控制器中完成即可:

SlowAlgorithmJob.perform_later

Last thing you need to cover is setting up queuing backend that will actually run the jobs. 您需要介绍的最后一件事是设置将实际运行作业的后端队列。 Rails supports couple of them. Rails支持其中的几个。 Probably the simplest one to set up is delayed_job , but if you're looking for something more scalable, I'd recommend looking into Sidekiq . 可能最简单的设置是delay_job ,但是如果您正在寻找可扩展性更高的东西,我建议您查看Sidekiq

EDIT: How to notify user that the job is done? 编辑: 如何通知用户作业已完成?

In order to do this, you clearly have to somehow track the progress of the task. 为此,您显然必须以某种方式跟踪任务的进度。 One possible direction is to create a record, let's call it a Task , which represents one invocation of your algorithm. 一个可能的方向是创建一条记录,我们称它为Task ,它代表算法的一次调用。

When user triggers the action that should queue up the job, Task record is created with status pending , then before_perform and after_perform job hooks can be used to move the Task status to running and then to completed . 当用户触发应将作业排队的操作时,将创建任务记录并具有pending状态,然后可以使用before_performafter_perform作业挂钩将Task状态移至“ running ,然后移至“ completed

after_perform hook can be used to notify the customer. after_perform挂钩可用于通知客户。 How the app is going to do it, is up to you. 应用程序将如何执行,取决于您。 For example, Dropbox uses similar system when downloading large amount of files. 例如,Dropbox在下载大量文件时使用类似的系统。 They queue up the job, the zips ups the files and then send the email with download link once the job is finished. 他们将作业排队,压缩文件,然后在完成作业后发送带有下载链接的电子邮件。

Another approach would be using in-app notification system. 另一种方法是使用应用内通知系统。

Lastly, to have the notification pop-up without requiring user to refresh the page, you'd have to use ActiveCable and push the notification back to user, again, using after_perform hook. 最后,要弹出通知而不需要用户刷新页面,您必须使用ActiveCable并再次使用after_perform挂钩将通知推回给用户。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在Ruby on Rails中将大型集作为后台进程进行地理编码的最佳方法是什么? - What is the best way to geocode large sets as a background process in Ruby on Rails? 什么是在后台发送电子邮件而不干扰ruby on rails的最佳方法? - What is the best way to send emails in background without interferring the process in ruby on rails? 在后台进程中运行rails -windows - run rails in background process -windows 在与Rails应用程序相同的域上运行Wordpress的最佳方法是什么? - What's the best way to run Wordpress on the same domain as a Rails application? 使用Ruby On Rails在Heroku上运行长任务的最佳方法是什么? - What is the best way to run a long task on Heroku with Ruby On Rails? 在Rails中运行PHP的最佳方法是什么? - What's the best way to run PHP within Rails? 验证终端命令的最佳方法是什么在Rails中成功运行? - What is the best way to validate a terminal command has run successfully in Rails? 在Rails上运行npm软件包的最佳方法是什么? - What's the best way to run npm packages on Rails? 在Rails应用程序中运行异步作业的最佳方法是什么? - What is the best way to run asynchronous jobs in a Rails application? Rails最佳实践:后台进程/线程? - Rails best practice: background process/thread?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM