Есть пара потенциальных проблем с принятым ответом, который стоит указать.
Во-первых, PeriodicTimer
выполняет саморегуляцию для выполнения с использованием рекурсии хвоста, то есть путем вызова EventMachine.add_timer
после выполнения его блока. К сожалению, код не использует begin-ensure-end
, что означает, что если в вашем коде есть исключение, таймер остановится. См. GH#454.
Во-вторых, существует вопрос о том, что реакторный контур EventMachine
работает в одном потоке как однотонный. Если вы запустите PeriodicTimer
и выполните медленные операции электронной почты в своем блоке, вы заблокируете петлю реактора, от которой может зависеть другой код. Лучше всего подтолкнуть работу по сбору электронной почты к отдельной теме, используя EventMachine::Deferrable
. См. Пример this post.
И последнее, но не менее важное: вы должны запускать 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
Руфус-планировщик больше не основан на EventMachine. – Sim