Repository navigation
fix(relay-runtime-workers): 撤销重判次数耗尽改为拒绝升级,控制对象异常不再让 jti 永久被拒 - #198
Merged
Merged
Conversation
Owlbay
force-pushed
the
fix/workers-revocation
branch
from
November 2, 2026 21:08
e885302 to
0c3ee8c
Compare
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.
变更摘要 / Summary
中文:Workers 中继撤销判断的两处失败方向(审计 BA-56、BA-57)。
edgeUpgrade的重判循环retry < 2用完后即使epoch !== revocationEpoch也退出循环,按最后一次可能过期的判定登记连接;isRevoked在第 3 次仍过期时返回「未撤销」。现在循环结束后 epoch 仍变了就放掉名额并拒绝本次升级(4401relay_token_invalid,客户端重连即可);isRevoked次数耗尽时按已撤销处理且不写缓存。controlStub().isRevoked抛异常时 catch 里revoked = true并写入缓存,而命中revoked缓存不看 TTL,一次瞬时失败让该 jti 永久被拒(直到下一次invalidate()或缓存清空)。现在异常仍按已撤销处理,但不写缓存。English: Two fail-direction fixes in the Workers relay revocation check (audit BA-56, BA-57).
retry < 2ran out,edgeUpgradeleft the loop even thoughepoch !== revocationEpochand admitted the connection on a possibly stale decision;isRevokedreturned "not revoked" on a stale third attempt. Now, if the epoch still changed after the loop, the slot is released and the upgrade refused (4401relay_token_invalid, the client reconnects);isRevokedtreats exhausted re-checks as revoked and does not cache it.controlStub().isRevokedthrew, the catch cachedrevoked = true, and a cachedrevokedentry ignores the TTL, so one transient failure rejected the jti until the nextinvalidate()or cache purge. Errors are still treated as revoked but are no longer cached.关联 issue / Related issues
Closes #192
改动范围 / Scope
packages/relay-runtime-workers)契约与协议变化 / Contract and protocol changes
无 / None
数据库迁移 / Database migrations
无 / None
测试 / Testing
新增
packages/relay-runtime-workers/test/revocation.test.ts(4 条),修复前 3 条失败(控制对象异常后 jti 仍被拒、次数耗尽放行、升级重判耗尽仍登记),修复后全过。 / Newtest/revocation.test.ts(4 cases); 3 failed before the fix (jti still rejected after a transient error, exhausted re-check admits, exhausted upgrade re-decision still registers) and all pass after.pnpm test):relay-runtime-workers 65 passed、relay-workers 3 passedpnpm check、pnpm go:check(未动 Go,用一次性 PostgreSQL / Redis 容器跑通)检查清单 / Checklist
CHANGELOG.md的 Unreleased / Recorded under Unreleased inCHANGELOG.md(与 fix(relay): 边缘写队列加上限、慢读客户端被断开,空闲判定计入未收齐的帧,节点间写侧溢出立即断开 #196、fix(cloud): 落盘前把路由表里在线的主机记成此刻在线,最近在线与核心版本随落盘前进 #197 同在顶部的## Unreleased,合并后一方可能需要解冲突,保留各自的条目即可 / the## Unreleasedheading at the top is shared with fix(relay): 边缘写队列加上限、慢读客户端被断开,空闲判定计入未收齐的帧,节点间写侧溢出立即断开 #196 and fix(cloud): 落盘前把路由表里在线的主机记成此刻在线,最近在线与核心版本随落盘前进 #197; whoever merges last keeps every bullet)需要维护者提供的外部条件 / External prerequisites
无 / None(Workers 部署由维护者执行 / Workers deployment is done by maintainers)
已知限制 / Known limitations
测试通过替换对象内部的
controlStub/policy注入失败,没有走真实的并发撤销。 / The tests inject failures by replacing the object'scontrolStub/policy, not through real concurrent revocations.