{
  "synthetic": true,
  "execution": "Teaching record only; no live integration tested",
  "slug": "rate-limit-backoff-job-budget",
  "group": "operations",
  "title": [
    "An integration retry needs a wait budget and a stop state",
    "集成重试，要有等待预算和停止状态"
  ],
  "intro": [
    "A product synchronisation job that retries immediately can turn a temporary throttle into a longer incident. Before buying an integration, ask for bounded waiting, a resumable queue and an honest incomplete state. Request-count limits and cost-based limits must not be mixed.",
    "商品同步一限流就立即重试，可能把短暂问题拖成长故障。采购集成时，应要求有界等待、可接续队列及真实未完成状态；按请求数与按成本限流不能混用。"
  ],
  "facts": [
    [
      "Retry-After can specify delay seconds or an HTTP date.",
      "Retry-After可表达等待秒数或HTTP日期。",
      "https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Retry-After"
    ],
    [
      "Shopify states that limit mechanics vary by API and plan, including cost-based versus request-based approaches.",
      "Shopify说明限流机制依API及套餐不同，包括按成本及按请求数。",
      "https://shopify.dev/docs/api/usage/limits"
    ]
  ],
  "columns": [
    [
      "Synthetic response",
      "Declared job policy",
      "Next state"
    ],
    [
      "合成响应",
      "本例任务策略",
      "下一状态"
    ]
  ],
  "example": [
    [
      [
        "429 at 10:00:00; Retry-After:30",
        "No retry earlier than advised",
        "Earliest10:00:30, plus chosen jitter"
      ],
      [
        "10:00:00收到429；等待30秒",
        "不得早于指示时间",
        "最早10:00:30，再加约定抖动"
      ]
    ],
    [
      [
        "503; date 10:01:00Z; now 10:00:20Z",
        "Date-based wait",
        "Wait at least 40 seconds"
      ],
      [
        "503；指定10:01:00Z；现在10:00:20Z",
        "按日期等待",
        "至少等待40秒"
      ]
    ],
    [
      [
        "Third transient failure",
        "Example max 3 attempts reached",
        "Stop automatic retry; keep cursor/pending rows"
      ],
      [
        "第三次暂时失败",
        "本例最多3次已到",
        "停止自动重试，保留游标及待处理行"
      ]
    ],
    [
      [
        "No valid header; permanent validation error",
        "No transient classification",
        "Quarantine for correction, not busy retry"
      ],
      [
        "无有效头；永久参数错误",
        "不属于暂时错误",
        "隔离纠错，不能忙重试"
      ]
    ]
  ],
  "steps": [
    [
      "Record the actual API/version, throttle signals and retryable errors. Agree total attempts, maximum elapsed time, job ownership and manual escalation. Three attempts here is illustrative.",
      "记录实际API版本、限流信号及可重试错误，约定次数、总耗时、归属及人工升级；三次只是本例。"
    ],
    [
      "Calculate wait from the received response, preserve server-date evidence and account for clock uncertainty. Use bounded backoff/jitter where appropriate, rather than a zero-delay loop.",
      "按收到响应计算等待，保留服务器时间依据并考虑时钟误差；按情况使用有界退避和抖动，不能零延迟循环。"
    ],
    [
      "Exercise a throttle, a malformed header and a permanent error offline. In authorised integration testing verify checkpoint readback and no duplicate side effects when the queue resumes.",
      "离线演练限流、错误响应头及永久错误；获准集成测试再核对断点回读和接续后没有重复副作用。"
    ]
  ],
  "result": [
    "The first two waits are 30 and 40 seconds respectively, not a universal “retry in one second”. A stopped job still owns unfinished rows and needs an operator outcome. The provider’s capacity cannot be inferred from these teaching numbers.",
    "前两例分别等待30和40秒，不是通用“一秒后重试”。停止任务仍有待处理行，需要操作员结论；这些教学数字不能用来推算平台真实容量。"
  ],
  "accept": [
    "Approve only when retry timing, bounded termination, checkpoint ownership and pending-row counts are inspectable. A final 200 for one request does not prove the whole synchronisation completed.",
    "重试时间、有界结束、断点归属及待处理数均可检查后才批准；一个请求最终200不证明整批同步完成。"
  ],
  "limit": [
    "No external API requests, waits or account expansion were performed. Exact limits, safe retries and idempotency remain provider- and operation-specific.",
    "没有执行外部API请求、等待或扩容；真实限额、安全重试及幂等性仍依平台和操作决定。"
  ]
}
