12

バックグラウンドでジョブを実行するには、delayed_job (またはその他のバックグラウンド ジョブ プロセッサ) を使用する必要がありますが、サーバーのブート スクリプト/ブート レベルを変更することはできません。これは、プロバイダーがサーバーを再起動した場合、デーモンが利用可能であることが保証されないことを意味します (デーモンは、デプロイメントごとに 1 回だけ実行される capistrano レシピによって開始されるため)。

現在のところ、delayed_job デーモンが常に実行されていることを確認するために考えられる最善の方法は、デーモンが実行されているかどうかを確認するイニシャライザを Rails アプリケーションに追加することです。デーモンが実行されていない場合、イニシャライザはデーモンを開始します。それ以外の場合はそのままになります。

したがって、問題は、Delayed_Job デーモンがスクリプト内から実行されていることをどのように検出するかということです。(デーモンをかなり簡単に起動できるはずですが、デーモンが既にアクティブになっているかどうかを検出する方法がわかりません)。

誰にもアイデアはありますか?

よろしく、バーニー

以下の回答に基づいて、これが私が思いついたものです。config/initializers に入れるだけで準備完了です:

#config/initializers/delayed_job.rb

DELAYED_JOB_PID_PATH = "#{Rails.root}/tmp/pids/delayed_job.pid"

def start_delayed_job
  Thread.new do 
    `ruby script/delayed_job start`
  end
end

def process_is_dead?
  begin
    pid = File.read(DELAYED_JOB_PID_PATH).strip
    Process.kill(0, pid.to_i)
    false
  rescue
    true
  end
end

if !File.exist?(DELAYED_JOB_PID_PATH) && process_is_dead?
  start_delayed_job
end
4

4 に答える 4

9

いくつかのクリーンアップのアイデア: 「begin」は必要ありません。何か問題が発生したときに新しいプロセスを起動しないように、「そのようなプロセスはありません」をレスキューする必要があります。条件を簡素化するために、「そのようなファイルまたはディレクトリはありません」もレスキューします。

DELAYED_JOB_PID_PATH = "#{Rails.root}/tmp/pids/delayed_job.pid"

def start_delayed_job
  Thread.new do 
    `ruby script/delayed_job start`
  end
end

def daemon_is_running?
  pid = File.read(DELAYED_JOB_PID_PATH).strip
  Process.kill(0, pid.to_i)
  true
rescue Errno::ENOENT, Errno::ESRCH   # file or process not found
  false
end

start_delayed_job unless daemon_is_running?

複数のワーカーを起動すると、このコードは機能しないことに注意してください。そして、デーモンと一緒に監視プロセスを生成する script/delayed_job の "-m" 引数を確認してください。

于 2010-12-14T17:20:31.817 に答える
5

デーモン PID ファイル ( File.exist? ...) の存在を確認します。そこにある場合は、実行中であると想定し、そうでない場合は起動します。

于 2010-04-05T20:57:12.927 に答える
0

質問(およびそれを刺激した答え:-)で提供された解決策をありがとう、それは複数のワーカー(Rails 3.2.9、Ruby 1.9.3p327)でも機能します。

たとえば、libにいくつかの変更を加えた後、delayed_jobを再起動するのを忘れて、気付く前に何時間もデバッグする可能性があるのではないかと心配しています。

script/railsRailsを起動するたびに、ただしワーカーが起動するたびにではなく、質問で提供されたコードを実行できるようにするために、ファイルに次を追加しました。

puts "cleaning up delayed job pid..."
dj_pid_path = File.expand_path('../../tmp/pids/delayed_job.pid',  __FILE__)
begin
  File.delete(dj_pid_path)
rescue Errno::ENOENT # file does not exist
end
puts "delayed_job ready."

rails generate私がこれに直面している小さな欠点は、たとえば、それも呼び出されることです。私はその解決策を探すのに多くの時間を費やしませんでしたが、提案は大歓迎です:-)

ユニコーンを使用している場合は、呼び出しconfig/unicorn.rbの前に同じコードを追加することをお勧めします。before_fork

-編集: 上記の解決策をもう少し試した後、私は次のことを行うことになりました:

script/start_delayed_job.rb次の内容のファイルを作成しました。

puts "cleaning up delayed job pid..."
dj_pid_path = File.expand_path('../../tmp/pids/delayed_job.pid',  __FILE__)

def kill_delayed(path)
  begin
    pid = File.read(path).strip
    Process.kill(0, pid.to_i)
    false
  rescue
    true
  end
end

kill_delayed(dj_pid_path)

begin
  File.delete(dj_pid_path)
rescue Errno::ENOENT # file does not exist
end

# spawn delayed
env = ARGV[1]
puts "spawing delayed job in the same env: #{env}" 

# edited, next line has been replaced with the following on in order to ensure delayed job is running in the same environment as the one that spawned it
#Process.spawn("ruby script/delayed_job start")
system({ "RAILS_ENV" => env}, "ruby script/delayed_job start")

puts "delayed_job ready."

これで、次のようにして、「script/rails」や「config/unicorn.rb」など、好きな場所でこのファイルを要求できます。

# in top of script/rails
START_DELAYED_PATH = File.expand_path('../start_delayed_job',  __FILE__)
require "#{START_DELAYED_PATH}"

# in config/unicorn.rb, before before_fork, different expand_path
START_DELAYED_PATH = File.expand_path('../../script/start_delayed_job',  __FILE__)
require "#{START_DELAYED_PATH}"
于 2013-02-22T10:02:09.570 に答える