Ruby on Rails:如何在后台运行东西?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/897605/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 21:15:53  来源:igfitidea点击:

Ruby on Rails: How to run things in the background?

ruby-on-railsrubybackground-process

提问by Stefan

When a new resource is created and it needs to do some lengthy processingbefore the resource is ready, how do I send that processing away into the backgroundwhere it won't hold upthe current request or other traffic to my web-app?

当一个新资源被创建并且它需要在资源准备好之前进行一些冗长的处理时,我如何将该处理发送到后台,它不会阻止当前请求或其他流量到我的网络应用程序?

in my model:

在我的模型中:

class User < ActiveRecord::Base
 after_save :background_check

 protected
 def background_check
  # check through a list of 10000000000001 mil different
  # databases that takes approx one hour :)
  if( check_for_record_in_www( self.username ) )
    # code that is run after the 1 hour process is finished.
    user.update_attribute( :has_record )
  end
 end
end

回答by ujh

You should definitely check out the following Railscasts:

您绝对应该查看以下 Railscast:

They explain how to run background processes in Rails in every possible way (with or without a queue ...)

他们解释了如何以各种可能的方式在 Rails 中运行后台进程(有或没有队列......)

回答by cjs

Start a separate process, which is probably most easily done with system, prepending a 'nohup' and appending an '&' to the end of the command you pass it. (Make sure the command is just one string argument, not a list of arguments.)

启动一个单独的进程,这可能是最容易完成的system,在您传递的命令的末尾添加一个“nohup”并附加一个“&”。(确保命令只是一个字符串参数,而不是参数列表。)

There are several reasons you want to do it this way, rather than, say, trying to use threads:

您想这样做有几个原因,而不是尝试使用线程:

  1. Ruby's threads can be a bit tricky when it comes to doing I/O; you have to take care that some things you do don't cause the entire process to block.

  2. If you run a program with a different name, it's easily identifiable in 'ps', so you don't accidently think it's a FastCGI back-end gone wild or something, and kill it.

  1. 在处理 I/O 时,Ruby 的线程可能有点棘手;您必须注意您所做的某些事情不会导致整个过程阻塞。

  2. 如果你用不同的名字运行一个程序,它在'ps'中很容易识别,所以你不会意外地认为它是一个FastCGI后端狂野之类的,然后杀死它。

Really, the process you start should be "deamonized," see the Daemonizeclass for help.

确实,您启动的进程应该被“去魔化”,请参阅Daemonize类以获得帮助。

回答by Sujimichi

I've just been experimenting with the 'delayed_job' gem because it works with the Heroku hosting platform and it was ridiculously easy to setup!!

我刚刚尝试了“delayed_job” gem,因为它适用于 Heroku 托管平台,而且设置起来非常简单!!

Add gem to Gemfile, bundle install, rails g delayed_job, rake db:migrateThen start a queue handler with;

将 gem 添加到 Gemfile, bundle install, rails g delayed_job,rake db:migrate然后启动一个队列处理程序;

RAILS_ENV=production script/delayed_job start

Where you have a method call which is your lengthy process i.e

你有一个方法调用,这是你漫长的过程,即

company.send_mail_to_all_users

you change it to;

你把它改成;

company.delay.send_mail_to_all_users

Check the full docs on github: https://github.com/collectiveidea/delayed_job

查看 github 上的完整文档:https: //github.com/collectiveidea/delayed_job

回答by Martin DeMello

you ideally want to use an existing background job server, rather than writing your own. these will typically let you submit a job and give it a unique key; you can then use the key to periodically query the jobserver for the status of your job without blocking your webapp. here is a nice roundupof the various options out there.

理想情况下,您希望使用现有的后台作业服务器,而不是自己编写。这些通常会让您提交作业并为其提供唯一键;然后,您可以使用密钥定期向作业服务器查询您的作业状态,而不会阻止您的 web 应用程序。这是对各种选项的一个很好的综述

回答by Matthew Campbell

I like to use backgroundrb, its nice it allows you to communicate to it during long processes. So you can have status updates in your rails app

我喜欢使用 backgroundrb,它很好,它允许您在长时间的进程中与它通信。这样您就可以在 Rails 应用程序中进行状态更新

回答by Vojto

I think spawnis a great way to fork your process, do some processing in background, and show user just some confirmation that this processing was started.

我认为spawn是一个很好的方法来分叉你的进程,在后台做一些处理,并向用户显示一些确认这个处理已经开始。

回答by Edu

What about:

关于什么:

def background_check
   exec("script/runner check_for_record_in_www.rb #{self.username}") if fork == nil
end

The program "check_for_record_in_www.rb" will then run in another process and will have access to ActiveRecord, being able to access the database.

然后程序“ check_for_record_in_www.rb”将在另一个进程中运行,并且可以访问 ActiveRecord,从而能够访问数据库。