如何让Ruby自动多次重试命令?

时间:2016-05-05 14:51:14

标签: ruby git

目前我们的应用程序运行有时失败,因为我们的Gitserver非常不可靠。

begin
  repository = Git.clone(remote_repo,deploy_script_root, { })
...
rescue Exception => e
  log.error e
  raise "Could not export deploy scripts: #{e.message}"
end

错误:连接到gitserver失败:80;访问http://gitserver

时正在进行操作

我想知道如何让Ruby多次重试这个命令,以免破坏我们的运行。

3 个答案:

答案 0 :(得分:3)

使用retry

begin
  retries ||= 0
  repository = Git.clone(remote_repo,deploy_script_root, { })
...
rescue Exception => e
  log.error e
  retries += 1
  retry if (retries <= 5)
  raise "Could not export deploy scripts: #{e.message}"
end

答案 1 :(得分:1)

Ruby实际上有一个retry关键字,在rescue内部用来重试一段代码。尝试this article深入了解事情。

此外,这听起来有点像黑客。如果您可以做任何事情来修复服务器,最终会比将代码放入代码更好,当问题的根源似乎是git服务器不可靠时。

答案 2 :(得分:0)

您可以使用Ruby retry语句。 retry将程序的控制权返回到封闭块的开头。简单的例子就是:

begin
  repository = Git.clone(remote_repo,deploy_script_root, { })
  # ...
rescue
  retry
end

以这种方式使用,这将永远重试,这对生产环境不利。事实上,在这一点上,代码甚至不检查导致异常的错误,因此即使错误是不可恢复的,它也会盲目地重试。

在一些重试尝试失败后,您需要一些控制逻辑失败,并在尝试重试之前检查错误是否可恢复。与上面的简单retry示例相比,这将为您提供更强大,更优雅的解决方案。

以此为出发点:

# For more robust support, consider reading these from a config file
MAX_RETRIES = 10
SLEEP_DURATION = 5

# Begin the retryable operation
retry_count = 0
begin
  repository = Git.clone(remote_repo,deploy_script_root, { })
  # ...
rescue Exception => e
  log.error e

  # Check that it's a recoverable error, before trying to recover...
  allow_retry = /Failed connect to gitserver/i.match(e.message)

  if allow_retry && retry_count < MAX_RETRIES
    retry_count += 1
    sleep SLEEP_DURATION
    retry
  end

  raise "Could not export deploy scripts: #{e.message}"
end

使用这样的代码,您可以控制重试操作的次数以及重试之间等待的时间。现在您知道只会重试可恢复的错误,以便在不应重试错误时快速失败。