Repository navigation
fix(events): 运行时按帧的顺序接收 emit 的回复,order-across-fast-path 第 2 步不再依赖时序 - #513
Merged
Merged
Conversation
§5.5:经宿主发出的 emit 得到回复之前,同名的后续 emit 继续经宿主。各运行时 原先在读到回复之后异步记下它(Go 的 goroutine、Node/Bun 的 Promise、Python 的 done callback、Kotlin 的线程、Swift 的 Task),宿主对排队中的 emit 还以 future 回复,所以宿主已回复、随后才到达的调用发出的 emit 仍可能经宿主, 用例第 2 步 viaHost: false 依赖时序。 - 设计:回复是普通值,宿主在各调用开始之后写出;运行时像 events.elsewhere 一样就地、按帧的顺序接收(两份设计文档,中英文)。 - 宿主:emit 的 events.dispatch 以 future 结果时先等它再回复; Dispatch::replied 在写出回复后通知测试钩子。 - 运行时:Go(peer.SendAnswered)、Node 与 Bun(session.invokeAnswered)、 Python(Peer.request_answered)、Kotlin(Peer.sendAnswered)、 Swift(Peer.sendAnswered)在读到回复帧时记下 emit 已得到回复。 - 规格:新期望 answered(运行器等宿主对收到的每个 events.dispatch 都写出 回复),emit/order-across-fast-path 第 0 步使用它。
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.
问题
#511 修好了
emit/order-across-fast-path第 0 步(viaHost: true)的偶发失败。验证时发现第 2 步(b 卸载后viaHost: false)还依赖时序:在宿主会话的有序任务开头临时加 2 ms 延迟,第 2 步每次都失败(viaHost: expected false, 1 events.dispatch arrived)。按 §5.5,经宿主发出的 N 的 emit 得到回复之前,N 的后续 emit 继续经宿主,Go 那时走宿主是对的。但“得到回复”在运行时里没有确定的时刻:
then里,Python 在 future 的 done callback 里(call_soon),Kotlin 在单独的线程里,Swift 在Task里。所以即使宿主已经回复,之后才到达的一帧(第 2 步对发出方服务的调用)里发出的 emit 仍可能看到“未回复”。用例只靠第 1 步卸载 b 的耗时盖过了这个窗口,并没有等待一个设计保证的条件。
修改
设计(
design-events-protocol-2026-10-18§5.5 与 §13.2,design-events-2026-10-18第 1 节,中英文):emit 的回复是普通值,宿主在各调用开始之后写出它。运行时像处理events.elsewhere(§4.1)一样就地、按帧的顺序接收:读到回复帧时就把这次 emit 记为已得到回复,再读下一帧。规格新增期望answered。宿主(rutis-bridge):
events.dispatch结果是 future 时,宿主先等它完成再回复普通值,不再回 future。Dispatch::replied(默认空实现,经 peer 的Operations、Handler、Routed转发到Imports)在写出事件操作的回复后调用,测试钩子在这里统计已回复的 dispatch。Tap::answered等到宿主对收到的每个events.dispatch都写出回复。运行时:都在读到回复帧时记下 emit 已得到回复,回复如果仍是 future(较旧的宿主),等它完成后再记:
peer.SendAnswered,回调在读 goroutine 上执行。rutis-runtime)与 Bun:session.invokeAnswered/callAnswered,在receive里同步回调;events.mjs三份副本相同。Peer.request_answered,在帧处理中直接回调。Peer.sendAnswered,回调在发出帧之前挂到等待者上,由读线程完成。Peer.sendAnswered,Pending.resolve在读到回复时回调。Rust 侧:宿主的 Rust 插件(含 dylib)总是自己在整张表上分发,节点连接也一样,没有快速路径,也没有“未回复的 emit”状态;叶子运行时的 emit 只在本进程里。所以 Rust 侧没有对应的改动。
用例:
emit/order-across-fast-path第 0 步加"answered": true。运行器在进入第 1 步之前等宿主写出回复;之后发给 Go 的帧都排在回复之后,Go 按帧的顺序接收,第 2 步一定走本地。验证
RUTIS_EVENTS_PLACEMENTS=sampled RUTIS_EVENTS_SETTLE_SCALE=2跑完整的events_conformance7 列,全部通过。go test ./...;node --test(node/rutis-runtime129 项,node/rutis100 项);bun test;pytest(websocket 有一项失败,与本修改无关);./gradlew build;swift run RutisSelfTest;cargo test -p rutis-bridge --features testing,node,python;clippy、fmt。