0

我想在 Rails 应用程序中添加类似“背景”线程的东西。我需要不时查看邮件(比如说每 10 分钟),然后根据邮件做一些事情。这应该与错误跟踪器的工作方式相同,您可以回复从错误跟踪器收到的电子邮件,它会接收电子邮件并将其添加到工单中。

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

4

4 回答 4

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 的工具。

于 2012-06-01T14:25:38.987 回答
1

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

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

其次,存在EventMachine作为单例在单线程中运行的反应器循环的问题。如果您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
于 2013-07-25T23:57:17.640 回答
0

查看Daemon-Kit。它允许您在与 Rails 项目具有相似约定的框架中创建 Ruby 守护程序。我们用它来监控和执行各种后台任务。

于 2012-06-01T14:30:01.317 回答
0

我在我的项目中使用了delayed_job 。

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

于 2012-06-01T14:30:22.303 回答