Ruby(rails)非阻塞递归算法?

时间:2015-06-25 08:26:24

标签: ruby-on-rails ruby recursion

我写了下面的伪红宝石来说明我正在尝试做什么。我有一些电脑,我想知道是否有任何东西与他们有关。如果没有任何东西连接到它们,请再次尝试两次尝试,如果仍然是这种情况,请将其关闭。

这是一个大型部署,因此这个递归计时器可以运行数百个节点。我只是想检查,这种方法听起来不错?在阻止工作进程的同时,它会产生大量线程并占用大量RAM吗? (我希望它将作为delayed_job

运行
check_status(0)


def check_status(i)
  if instance.connected.true? then return

  if instance.connected.false? and i < 3
    wait.5.minutes
    instance.check_status(i+1)
  else 
    instance.shutdown
    return
  end
end

3 个答案:

答案 0 :(得分:3)

当这里的最大递归深度为3时,不会出现大的问题。应该没问题。递归方法不会创建线程,但每次调用都会存储有关调用堆栈的更多信息,最终用于该存储的资源可能会耗尽。不过3次电话之后,这是非常安全的。

但是,不需要递归来解决您的问题。以下循环也应该这样做:

def check_status
  return if instance.connected.true?
  2.times do 
    wait.5.minutes
    return if instance.connected.true?
  end
  instance.shutdown
end

答案 1 :(得分:2)

您已经从其他用户那里得到了答案。但是,由于您等待至少两次5分钟,您可能会考虑使用其他语言或更改设计。

Ruby(MRI)有一个全局解释器锁,它限制Ruby代码的并行执行。 MRI不平行。你可能会因此而效率低下。

  • 考虑使用线程(合理数量的线程池可能有意义),可能由带有任务的队列提供
  • 确保你不要等5分钟。而是把它们放在 sleep 那段时间。这样其他线程就可以执行,而有些则正在等待 / 等待
  • 您还可以考虑使用jRuby,因为jRuby具有真正的并行性(MRI受GIL限制,因此它不是真正的并行)
  • 考虑使用其他可能性能更高的编程语言

答案 2 :(得分:1)

如果它通过delayed_job运行,为什么不使用gem的功能来实现你想要的呢?举个例子,我会选择以下内容。无需安排延迟工作或任何事情。

class CheckStatusJob

  def before(job)
    @job = job
  end

  def perform
    if instance.connected.true? then return

    if instance.connected.false? and @job.attempts < 3
      raise 'The job failed!'
    else
      instance.shutdown
    end
  end

  def max_attempts
    3
  end

  def reschedule_at(current_time, attempts)
    current_time + 5.minutes
  end

end