新しいリソースが作成され、リソースの準備が整う前にいくつかの長い処理を実行する必要がある場合、その処理をどのように送信しますかバックグラウンドに場所Webアプリケーションへの現在の要求または他のトラフィックを保持しません?
私のモデルでは:
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
以下のRailscastを必ずチェックしてください。
彼らはRailsで可能なあらゆる方法で(キューの有無にかかわらず...)バックグラウンドプロセスを実行する方法を説明します...)
別のプロセスを開始します。これはおそらくsystem
を使用して最も簡単に実行できます。「Nohup」を前に付け、渡したコマンドの最後に「&」を追加します。 (コマンドが引数のリストではなく、1つの文字列引数であることを確認してください。)
スレッドを使用するのではなく、この方法で実行する理由はいくつかあります。
I/Oを実行する場合、Rubyのスレッドは少し扱いにくい場合があります。プロセス全体がブロックされないように注意する必要があります。
別の名前でプログラムを実行すると、 'ps'で簡単に識別できるので、FastCGIバックエンドが乱暴になっていると誤って判断したり、強制終了したりすることはありません。
実際、開始するプロセスは「デーモン化」されている必要があります。ヘルプについては、 Daemonize クラスを参照してください。
Herokuホスティングプラットフォームで動作し、セットアップが途方もなく簡単だったため、私は「delayed_job」gemを実験しています。
GemにGemを追加します。bundle install
、Rails g delayed_job
、rake db:migrate
次に、次のコマンドでキューハンドラを開始します。
Rails_ENV=production script/delayed_job start
あなたの長いプロセスであるメソッド呼び出しがある場所、つまり
company.send_mail_to_all_users
に変更します。
company.delay.send_mail_to_all_users
Githubの完全なドキュメントを確認してください: https://github.com/collectiveidea/delayed_job
自分で作成するのではなく、既存のバックグラウンドジョブサーバーを使用するのが理想的です。これらは通常、ジョブを送信して一意のキーを与えることができます。その後、キーを使用して、webappをブロックせずに定期的にjobserverにジョブのステータスを照会できます。 これは素晴らしいまとめです さまざまなオプションがあります。
spawn は、プロセスをforkし、バックグラウンドで処理を実行し、この処理が開始されたことを確認するための優れた方法だと思います。
私はbackgroundrbを使用するのが好きです。Niceを使用すると、長いプロセス中にそれと通信できます。 Railsアプリでステータスを更新できます
何について:
def background_check
exec("script/runner check_for_record_in_www.rb #{self.username}") if fork == nil
end
プログラム "check_for_record_in_www.rb
"は別のプロセスで実行され、ActiveRecordにアクセスして、データベースにアクセスできるようになります。