开发者

retry connection to rate limited URL until successful in Scala

I need make a GET call to a REST api which is rate limited. I can find out what the current rate limit is by making a call and checking the HTTP headers. If I've exceeded my rate limit, I should wait for a bit before retrying. I'd like to write something like:

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

I have a working solution using a var, a while loop and some repetitious code, but it feels clunky:

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
}

Is there a cleaner way to do this?


You could make it tail-recursive:

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)
  }
}

Or you could use an infinite iterator pattern, either 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
}

or by wrapping the URL call in a wait that returns an option (especially useful if you want option handling elsewhere; not sure whether you want to embed the wait there or outside):

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
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜