fix(czdev): 网络截断时重试,不再直接 traceback - #19
Closed
eggfly wants to merge 1 commit into
Closed
Conversation
A publish died with `http.client.IncompleteRead(4813 bytes read, 1558 more expected)` from inside `json.loads(resp.read().decode())`: the connection to api.github.com was cut three quarters of the way through a 6 KB response, which a proxy or a flaky uplink does routinely. Every API call was a single unguarded attempt, so any hiccup surfaced as a Python traceback with no hint of what went wrong. Route every call through `_fetch()`, which reads the body defensively and retries with exponential backoff on truncated reads, socket errors and the statuses GitHub uses to say "not my final answer" (429, 5xx, honouring Retry-After). Only GETs are replayed after a network failure -- a POST that died mid-response may still have been applied, and re-sending it could create a second commit, ref or pull request. Asset uploads get their own retry loop: they are the most likely thing to break on a slow link (a 72 MB .deb over the API's timeout), and they can be replayed safely as long as a half-uploaded asset is deleted first, which now happens on every round. Replies that are not JSON at all -- an HTML rate-limit page, a captive portal, an empty body -- now raise GitHubError carrying the status, content type and a body snippet, and `main()` prints it as a plain error instead of a traceback. Mirrors what #18 did for the device-flow login. Co-authored-by: Cursor <cursoragent@cursor.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
起因
同事跑
czdev publish传一个 72.6 MB 的 deb,预检全过之后崩在这里:这是
GET /repos/CardputerZero/packages。响应头声明 6371 字节,连接在读到 4813 字节时断了。同一个接口我这边实测返回content-length: 6286,稳定正常,所以是他那条链路(代理 / VPN / 网关)把连接掐了。问题在于
_request()每个调用都是一次性、无防护的尝试,任何抖动都会变成一个看不出所以然的 Python traceback。他上午那次czdev login的JSONDecodeError是同一类问题,已经在 #18 修过auth.py;这个 PR 把github_client.py也补齐。改了什么
_fetch():小心地读完 body,对截断读取、socket 错误、以及 GitHub 明示可重试的状态码(429、5xx,遵守Retry-After)做指数退避重试。GitHubError,带上状态码、content-type 和 body 前 200 字;main()捕获后打印成一行普通错误,不再吐 traceback。Ctrl-C 也一样。HTTPError语义:check_permission靠 404/403、ensure_release靠 404 分支判断,这些行为不变,只是错误信息里现在带上了响应 body。验证
需要说明的
重试只能扛住抖动。如果他那条链路是稳定地截断,重试 4 次一样会失败,只不过现在的报错会直接说清是网络断了。让他先跑这个确认(正常应该每次都是
200 6286B):Made with Cursor