Repository navigation
fix(bridge): 事件测试钩子在读到 events.dispatch 时计数,修复 order-across-fast-path 偶发失败 - #511
Merged
Merged
Conversation
宿主读到 events.* 帧后放进会话的有序任务里执行,读线程接着读下一帧。 测试钩子原先在有序任务执行 events.dispatch 时才计数,于是运行时在 dispatch 之后发出的回复(发出方 emit 的返回)可能先被读到,套件读计数时 这次 dispatch 还没算上,emit/order-across-fast-path 偶发报 viaHost: expected true, 0 events.dispatch arrived。 现在读线程接纳事件操作时调用 Dispatch::arrived(经 peer 的 Operations、 Handler 与 Routed 转发到 Imports),钩子在这里计数;hold 仍在执行时等待。
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.
问题
PR #503 的 network-macos(job 118970595241)在
crates/rutis-loader/tests/events_conformance.rs的events_with_x_a_go_plugin失败:#503 只改 Swift,与它无关。本地单跑这个用例(
RUTIS_EVENTS_PLACEMENTS=all RUTIS_EVENTS_CASE=emit/order-across-fast-path)同样偶发,Y 为 bun、python 都出现过。根因
不是 Go SDK 的快速路径,也不是监听器表推送的竞争。在 Go 运行时里加跟踪后,失败的那一次里 Go 在 emit 前已经收到
events.elsewhere {add: [t/switch]},判断为经宿主(via=true),并在回复发出方的调用之前发出了events.dispatch。帧的顺序完全符合设计(§4.4、§5.2)。问题在宿主的测试钩子计数的时机:
events.*帧后,把它放进会话的有序任务(run_ordered,在执行器上运行),然后接着读下一帧。事件操作之间保持顺序,但它们与其他帧(比如回复)之间不保证先后(这是有意的:读线程不运行插件代码)。Tap::dispatches原先在有序任务执行events.dispatch时(SessionEvents::invoke)才加一。events.dispatch后回复emitter-e.dispatch。读线程先读到 dispatch 帧,放进有序任务;再读到回复,套件的调用随即返回,读取计数。有序任务还没轮到时,计数仍是 0。所以钩子测的是“宿主已开始执行”,而它声称、套件也需要的是“宿主已收到”。
修改
session::Dispatch增加带默认空实现的arrived(peer, method):读线程接纳一个事件操作时、读下一帧之前调用,不得阻塞。peer::Handler(默认空实现)、Operations(按族找到处理者)、runtime::access::Routed,到Imports,再到SessionEvents::arrived。SessionEvents::arrived里对events.dispatch计数(TapState::received);hold仍在执行前等待(TapState::starting),读线程不会被它阻塞。产品行为不变:没有
testing特性时arrived什么也不做。测试没有放宽:viaHost: true仍要求发出方在返回之前已经把events.dispatch发给宿主,viaHost: false反而更严格(经宿主的 dispatch 在读到时就计入,不会因为执行晚而漏算)。其他语言:钩子在宿主侧,Node、Bun、Python、Swift、Kotlin 的
viaHost检查走同一个计数,一并修好。它们的快速路径与 Go 相同,都是在回复之前把events.dispatch按序发出,没有发现同样的竞争。验证
只跑这个用例的 5 种放置(
RUTIS_EVENTS_PLACEMENTS=all RUTIS_EVENTS_CASE=emit/order-across-fast-path,events_with_x_a_go_plugin):step 0 (emit from e): viaHost: expected true, 0 events.dispatch arrived,与 CI 的报错一致;加上本修改后 10 次运行里 step 0 全部通过。RUTIS_EVENTS_PLACEMENTS=sampled RUTIS_EVENTS_SETTLE_SCALE=2跑完整的events_conformance(X = node-leaf、bun、go、cordis、python):全部通过。cargo test -p rutis-bridge --features testing,node,python --lib --tests、cargo clippy -p rutis-bridge --all-features --all-targets、cargo fmt --check:通过。附带观察:加 2 ms 延迟时,修改后的 step 2(
viaHost: false)会失败,因为宿主对 step 0 那次 emit 的回复晚于 b 的卸载,Go 按 §5.5 在回复之前继续经宿主发出。这符合设计;不加延迟时卸载一行远慢于宿主回复,没有出现过。