SuperAPI AI 工具集

Linear Rate Limiting

部署与运维

查看项目

更新于 10-16 05:29

技能介绍

Linear Rate Limiting

参考:https://linear.app/developers/rate-limiting

两类预算

Linear 按以下两种方式计费:

  • 请求速率 —— 按 IP、按令牌(取决于套餐层级:免费版约 1500/小时,付费版更高)
  • 复杂度点数 —— 按令牌(典型约 5000/小时)

真正会对大型查询造成影响的是复杂度预算。每个查询的成本取决于:

  • 字段数量
  • 连接规模(first: 100 比 first: 10 成本更高)
  • 嵌套解析
  • 请求头

每个响应都包含:

  • X-RateLimit-Limit —— 每个窗口的额度
  • X-RateLimit-Remaining —— 剩余额度
  • X-RateLimit-Reset —— 额度重置的时间戳(epoch)
  • X-Complexity —— 本次查询的成本
  • X-Complexity-Limit、X-Complexity-Remaining、X-Complexity-Reset

lib/linear-client.mjs GraphQL 客户端将这些信息以回调形式暴露:

client.onRateLimit((info) => {
  if (info.complexityRemaining < 1000) backoff(info.resetIn);
});

退避策略

当你收到 429(或 complexity_limit GraphQL 错误)时:

  1. 读取 X-RateLimit-Reset / X-Complexity-Reset
  2. 休眠至该时间戳 + 1 秒抖动
  3. 重试一次;第二次 429 → 进入死信队列(DLQ)并告警(不要让用户在重试中被淹没)
async function withBackoff<T>(fn: () => Promise<T>, max = 3): Promise<T> {
  for (let i = 0; i < max; i++) {
    try { return await fn(); }
    catch (e: any) {
      if (e.status !== 429) throw e;
      const reset = Number(e.headers["x-ratelimit-reset"]) * 1000 - Date.now();
      await new Promise(r => setTimeout(r, Math.max(reset, 1000) + Math.random() * 500));
    }
  }
  throw new Error("rate-limit retries exhausted");
}

批量操作的节流

当变更操作超过 50 个时,需要显式节流:

  • 最多 10 个并发在途(令牌桶容量)
  • 每 100ms 补充 1 个令牌
  • 若 complexity_remaining < 30%,则暂停

实现位于 lib/rate-limit.ts(令牌桶)。

Webhook 背压

能用 Webhook 时就不要轮询 Linear。桥接智能体:

  • 订阅 Webhook 以获取实时变更
  • 仅在数据对账时轮询(每 6 小时一次),或在 Webhook 死信队列重放之后轮询

提示

  • 优先使用一个包含所有所需字段的大查询,而非许多小查询(往返更少,通常总复杂度更低)
  • 如果只需要 10 条,就不要请求 first: 250
  • 在某个流程持续期间缓存变化缓慢的数据(团队列表、标签列表)
  • 避免在大连接上使用 every: 和 none: 过滤器 —— 它们开销很高