手动 API 速率限制

Manual API rate limiting

我正在尝试为 rgithub 包编写一个手动速率限制函数。到目前为止,这就是我所拥有的:

library(rgithub)

pull <- function(i){
 commits <- get.pull.request.commits(owner = owner, repo = repo, id = i, ctx = get.github.context(), per_page=100)
 links <- digest_header_links(commits)
 number_of_pages <- links[2,]$page
 if (number_of_pages != 0)
   try_default(for (n in 1:number_of_pages){
    if (as.integer(commits$headers$`x-ratelimit-remaining`) < 5)
     Sys.sleep(as.integer(commits$headers$`x-ratelimit-reset`)-as.POSIXct(Sys.time()) %>% as.integer())
  else
    get.pull.request.commits(owner = owner, repo = repo, id = i, ctx = get.github.context(), per_page=100, page = n)
}, default = NULL)
else 
   return(commits)
}

list <- c(500, 501, 502)

pull_lists <- lapply(list, pull)

我的意图是,如果 x-ratelimit-remaining 变量低于某个阈值,脚本应该等到 x-ratelimit-reset 中指定的时间过去,然后继续执行脚本。但是,我不确定这是否是我在此处设置的 if else 的实际行为。

该函数运行良好,但我怀疑它是否真的进行了速率限制,或者它是否以某种方式跳过了这些步骤。因此我问:a) 我怎样才能知道它是否确实进行了速率限制,以及 b) 如果没有,我如何重写它以便它实际上进行速率限制? while condition/loop 会更好吗?

不是规范的答案,而是一些工作示例。
您应该在脚本中添加一些日志记录,甚至 write.csv(append=TRUE)

我已经实施了自动 antiddos 流程,以防止您的 ip 被交易市场禁止。你可以找到它 jangorecki/Rbitcoin/R/utils.R.
Rbitcoin.last_api_call 是存储在包命名空间中的环境对象,一种会话包缓存。
这可以帮助您在包中进行设置。

您还应该考虑可选的 并行 支持版本。链接到具有并发读取的数据库。我的功能可以很容易地修改为每 X 秒排队调用和重新检查时间。

编辑
我忘记添加提到的功能支持多个 源系统 。这允许例如为 bitbucket 等扩展你的 rgithub,并且仍然有效地管理 API 速率限制。

您可以测试它是否将 5 的速率限制更改为足够大的数字并添加 Sys.sleep 的时间显示,使用:

print(system.time(Sys.sleep(...)))

也就是说,这个功能对我来说似乎没问题,不幸的是我无法轻松测试它,因为 rgithub 不适用于我的 R (3.1.3) 版本。