AGC 壳通知计数按线程隔离,修掉跨用例后台广播串台

- runtime_driver/entrypoints.rs:测试通知计数从进程级 AtomicU64 改成线程作用域 Cell,只统计本测试线程发出的通知
- runtime_driver/entrypoints.rs:`--test-threads=1` 只串行测试线程,前一个用例放行留下的后台回合仍在宿主 async runtime 工作线程上广播「运行中的项目」通知,不再是断言的取样来源
- thread_manager/mod.rs:同步用例注释,说明计数为何按线程隔离,断言语义(放行 1 / 内容变化 1 / 重复进度 0 / 收口 1)不变
- pitfalls:记录现场、根因、现行口径与验证(修复前 5 次红 3 次,修复后 CI 那一片连跑 18 次全绿)
This commit is contained in:
2026-10-01 16:42:02 +08:00
parent b51bf03854
commit c177dde5c3
3 changed files with 21 additions and 4 deletions
@@ -4,7 +4,14 @@ pub(crate) const DIRECT_ACTIVE_TURNS_CHANGED_EVENT: &str =
"game-creator-direct-active-turns-changed";
static DIRECT_ACTIVE_TURNS_EVENT_REVISION: AtomicU64 = AtomicU64::new(0);
#[cfg(test)]
static DIRECT_ACTIVE_TURNS_EVENT_TEST_COUNT: AtomicU64 = AtomicU64::new(0);
thread_local! {
/// 只统计**当前线程**发出的通知。`--test-threads=1` 只串行测试线程,宿主
/// `tauri::async_runtime` 的后台回合仍在自己的工作线程上跑(放行任务随
/// `TurnReservation::drop` 起整轮,见 `thread_manager::dispatch`),并会在任意时刻广播
/// 「运行中的项目」变了。断言要观测的是本测试自己触发的通知,不该被别的后台广播串台。
static DIRECT_ACTIVE_TURNS_EVENT_TEST_COUNT: std::cell::Cell<u64> =
const { std::cell::Cell::new(0) };
}
const GAME_CREATOR_MANIFEST_INVALIDATION_RELAY_MAX_BYTES: u64 = 64 * 1024;
const GAME_CREATOR_MANIFEST_INVALIDATION_EVENT_SINK_MAX: usize = 16;
@@ -30,7 +37,7 @@ pub(crate) fn set_game_creator_agent_runtime_update_app_handle(app: tauri::AppHa
pub(crate) fn emit_direct_active_turns_changed() {
let revision = DIRECT_ACTIVE_TURNS_EVENT_REVISION.fetch_add(1, Ordering::AcqRel) + 1;
#[cfg(test)]
DIRECT_ACTIVE_TURNS_EVENT_TEST_COUNT.fetch_add(1, Ordering::AcqRel);
let _ = DIRECT_ACTIVE_TURNS_EVENT_TEST_COUNT.try_with(|count| count.set(count.get() + 1));
let Some(app) = GAME_CREATOR_AGENT_RUNTIME_UPDATE_APP_HANDLE.get() else {
return;
};
@@ -42,7 +49,7 @@ pub(crate) fn emit_direct_active_turns_changed() {
#[cfg(test)]
pub(crate) fn direct_active_turns_event_test_count() -> u64 {
DIRECT_ACTIVE_TURNS_EVENT_TEST_COUNT.load(Ordering::Acquire)
DIRECT_ACTIVE_TURNS_EVENT_TEST_COUNT.with(std::cell::Cell::get)
}
pub(crate) fn emit_direct_game_creator_progress(root: &Path, stage: &str, message: &str) {
@@ -1791,7 +1791,8 @@ mod tests {
/// 首页快照的变更通知必须跟着快照自己的事实源走:放行(登记占用)、进度内容变化、收口各通知一次,
/// 状态与活动都没变的重复进度不重复通知;入队与取消只改队列,不进快照,不通知。
///
/// 计数器是进程级的,因此本用例与仓库既有的 Rust 定向命令一样按 `--test-threads=1` 跑。
/// 计数器按线程隔离:`--test-threads=1` 只串行测试线程,前一个用例放行留下的后台回合仍会在
/// 宿主 async runtime 的工作线程上广播通知(见 `direct_active_turns_event_test_count` 的说明)。
#[test]
fn active_turn_changes_publish_one_notification_per_real_change() {
let thread_id = format!("/tmp/事件项目-{}", Uuid::new_v4());