fix(sync): 限流检测漏掉了它真实的样子
上一版加了 429 识别,但点同步按钮报的还是 JSONDecodeError——因为检测
只看 `e.response.status_code` 和异常消息,而真实到达我们手里的异常两样
都不满足:garth 对着 429 调 .json(),抛出的 JSONDecodeError 里状态码已经
丢了,消息是无用的 "Expecting value: line 1 column 1"。
响应体「Rate limited」唯一幸存的地方是异常的 `doc` 属性,改为从那里取。
同时改正上一版的测试:它用 ValueError("Rate limited") 构造,那个形态现实中
根本不会出现,所以测试通过、检测却漏掉了每一个真实的限流。现在用真的
json.JSONDecodeError 构造,并先断言「光看消息不够」。
实测同步现在返回:
RateLimited: Garmin 暂时限制了请求频率…令牌本身没有失效
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -111,11 +111,20 @@ def _note_rate_limit(user_id):
|
||||
|
||||
|
||||
def _is_rate_limited(e):
|
||||
"""429 from Garmin, however it happens to be dressed."""
|
||||
"""429 from Garmin, however it happens to be dressed.
|
||||
|
||||
Usually it arrives as a JSONDecodeError, because garth calls .json() on a
|
||||
429 whose body is the plain text "Rate limited" — the status code is gone
|
||||
by the time the exception reaches us, and the message is the useless
|
||||
"Expecting value: line 1 column 1". What survives is the body itself, on
|
||||
the exception's `doc` attribute, so that is where to look.
|
||||
"""
|
||||
response = getattr(e, "response", None)
|
||||
if response is not None and getattr(response, "status_code", None) == 429:
|
||||
return True
|
||||
return "rate limit" in str(e).lower()
|
||||
|
||||
haystacks = [str(e), str(getattr(e, "doc", "") or "")]
|
||||
return any("rate limit" in h.lower() for h in haystacks)
|
||||
|
||||
|
||||
class MFARequired(RuntimeError):
|
||||
|
||||
Reference in New Issue
Block a user