红宝石的背景工作线程

时间:2012-06-01 14:19:17

标签: ruby-on-rails background event-handling

我想在rails应用程序中添加类似“后台”线程的东西。我需要不时检查电子邮件(假设每10分钟一次),然后根据电子邮件做一些事情。这应该与bug跟踪器的工作方式相同,您可以回复从错误跟踪器获得的电子邮件,它将接收电子邮件并将其添加到故障单中。

有没有简单的方法在后台运行这样的东西?我不想使用cron或任何系统工具,只是纯粹的红宝石。我开始申请,我不应该关心其他任何事情。

4 个答案:

答案 0 :(得分:3)

EventMachine有PeriodicTimer

 n = 0
 timer = EventMachine::PeriodicTimer.new(5) do
   puts "the time is #{Time.now}"
   timer.cancel if (n+=1) > 5
 end

rufus-scheduler是纯Ruby基础EventMachine中类似cron的工具。

答案 1 :(得分:1)

值得指出的接受答案有几个潜在的问题。

首先,PeriodicTimer重新安排自己使用尾递归执行,即在执行其块后调用EventMachine.add_timer。不幸的是,代码不使用begin-ensure-end,这意味着如果代码中存在异常,则计时器将停止。见GH#454

其次,EventMachine的反应器循环在单个线程中作为单例运行的问题。如果您启动PeriodicTimer并在其块中执行慢速电子邮件操作,您将阻止其他代码可能依赖的reactor循环。更好的方法是使用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

答案 2 :(得分:0)

结帐Daemon-Kit。它允许您在具有与Rails项目类似约定的框架中创建Ruby Daemons。我们使用它来监控和执行各种后台任务。

答案 3 :(得分:0)

我在我的项目中使用delayed_job

  

Delayed_job(或DJ)封装了在后台异步执行更长任务的常见模式。