重试连接到速率有限的URL,直到Scala成功

时间:2010-08-25 13:53:05

标签: scala rest

我需要对速率有限的REST api进行GET调用。我可以通过拨打电话和检查HTTP标头来了解当前的速率限制。如果我超过了我的速率限制,我应该等一会儿再重试。我想写一些类似的东西:

val conn = connect(url, _.getHeaderField("X-RateLimit-Remaining").toInt > 0, 500)

我有一个使用var,while循环和一些重复代码的工作解决方案,但它感觉很笨:

def connect(url: String, succeeded: URLConnection=>Boolean, waitMillis: Int) = {
  var conn = new URL(url).openConnection
  while (!succeeded(conn)) {
    Thread.sleep(waitMillis)
    conn = new URL(url).openConnection
  }
  conn
}

有更简洁的方法吗?

1 个答案:

答案 0 :(得分:3)

你可以让它尾递归:

def connect(url: String, succeeded: URLConnection=>Boolean, wait: Int): URLConnection = {
  val conn = new URL(url).openConnection
  if (succeeded(conn)) conn
  else {
    Thread.sleep(wait)
    connect(url,succeeded,wait)
  }
}

或者你可以使用无限的迭代器模式,raw:

def connect(url: String, succeeded: URLConnection=>Boolean, waitMillis: Int) = {
  val tries = Iterator.continually( new URL(url).openConnection )
  tries.dropWhile(
    conn => if (succeeded(conn)) false else { Thread.sleep(waitMillis); true }
  ).next
}

或通过在返回选项的等待中包装URL调用(如果您希望在其他位置处理选项,则特别有用;不确定是否要在那里或外部嵌入等待):

def attemptConnect(url: String, succeeded: URLConnection=>Boolean, waitMillis: Int) = {
  val conn = new URL(url).openConnection
  if (succeeded(conn)) Some(conn)
  else { Thread.sleep(waitMillis); None }
}
def connect(url: String, succeeded: URLConnection=>Boolean, waitMillis: Int) = {
  val tries = Iterator.continually( attemptConnect(url,succeeded,waitMillis) )
  tries.dropWhile(_.isEmpty).next
}