指摘する価値のある、受け入れられた回答にはいくつかの潜在的な問題があります。
最初に、PeriodicTimer
末尾再帰を使用して、つまり、EventMachine.add_timer
そのブロックを実行した後に呼び出すことによって、実行のために自分自身を再スケジュールします。残念ながら、コードは使用していませんbegin-ensure-end
。つまり、コードに例外がある場合、タイマーは停止します。GH#454を参照してください。
EventMachine
第 2 に、シングルトンとしてシングル スレッドで実行されている のリアクター ループの問題があります。を開始しPeriodicTimer
、そのブロックで遅い電子メール操作を実行すると、他のコードが依存しているリアクター ループがブロックされます。より良いアプローチは、メール収集作業を を使用して別のスレッドにプッシュすることEventMachine::Deferrable
です。例については、この投稿を参照してください。
最後になりましたがEventMachine
、リアクターがまだ実行されていない場合は別のスレッドで実行する必要がありますが、リアクターのスレッドが既に実行されている場合は、作業を「スケジュール」する必要があります。
これをまとめると、次のようになります。
def check_email
timer = EM::PeriodicTimer.new(10.minutes) do
begin
DefferableEmailChecker.new.errback do |error|
# handle error
# note that this code will run OUTSIDE the
# periodic timer block
end
rescue Exception => e
# even with a Deferable this is good practice
# if you want to cancel, use timer.cancel
end
end
end
if EM.reactor_running?
EM.schedule do
check_email
end
else
Thread.new do
EM.run do
check_email
end
end
end