From 82f24ded1bd6e490f5e5722cce70972bba85c119 Mon Sep 17 00:00:00 2001 From: kdletters <61648117+kdletters@users.noreply.github.com> Date: Thu, 28 May 2026 04:27:51 +0800 Subject: [PATCH] fix: restore match3d indexed visibility reads --- ...】server-rs与SpacetimeDB数据契约-2026-05-15.md | 4 +- .../crates/spacetime-module/src/match3d.rs | 39 +++++++++---------- .../spacetime-module/src/match3d/tables.rs | 2 +- .../crates/spacetime-module/src/migration.rs | 6 +-- .../src/runtime/admin_work_visibility.rs | 12 +++--- 5 files changed, 32 insertions(+), 31 deletions(-) diff --git a/docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md b/docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md index 106c0edd..5bf2a3e2 100644 --- a/docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md +++ b/docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md @@ -472,10 +472,12 @@ npm run check:server-rs-ddd - Rust 结构体:`Match3DRuntimeRunRow` - 源码:`server-rs/crates/spacetime-module/src/match3d/tables.rs` -### `match3d_work_profile` +### `match_3_d_work_profile` - Rust 结构体:`Match3DWorkProfileRow` +- Rust accessor:`match_3_d_work_profile` - 源码:`server-rs/crates/spacetime-module/src/match3d/tables.rs` +- 兼容说明:dev 现有 SpacetimeDB 元数据中的真实表名 / 索引名为 `match_3_d_work_profile` 与 `match_3_d_work_profile_*_idx_btree`。module 内部 accessor 必须与该 canonical name 对齐,避免 Rust SDK 在 `index_id_from_name` 初始化二级索引时查找 `match3d_work_profile_*` 并触发 `No such index` panic。`migration.rs` 仍兼容旧迁移包中的 `match3d_work_profile` 表名补默认字段。 ### SpacetimeDB view:`match_3_d_gallery_view` diff --git a/server-rs/crates/spacetime-module/src/match3d.rs b/server-rs/crates/spacetime-module/src/match3d.rs index 272c430e..649c6f8d 100644 --- a/server-rs/crates/spacetime-module/src/match3d.rs +++ b/server-rs/crates/spacetime-module/src/match3d.rs @@ -23,13 +23,13 @@ use spacetimedb::AnonymousViewContext; /// 抓大鹅公开广场列表投影。 /// -/// `match3d_work_profile` 是玩法源表,HTTP gallery 只订阅这个轻量 view, +/// `match_3_d_work_profile` 是玩法源表,HTTP gallery 只订阅这个轻量 view, /// 避免每个公开列表请求重新调用 procedure 扫描和组装全量列表。 #[spacetimedb::view(accessor = match3d_gallery_view, public)] pub fn match3d_gallery_view(ctx: &AnonymousViewContext) -> Vec { let mut items = ctx .db - .match3d_work_profile() + .match_3_d_work_profile() .by_match3d_work_publication_status() .filter(MATCH3D_PUBLICATION_PUBLISHED) .filter(|row| row.visible) @@ -501,7 +501,7 @@ fn compile_match3d_draft_tx( validate_config(&config)?; let existing_work = ctx .db - .match3d_work_profile() + .match_3_d_work_profile() .profile_id() .find(&input.profile_id) .filter(|row| row.owner_user_id == input.owner_user_id); @@ -695,15 +695,14 @@ fn list_match3d_works_tx( ) -> Result, String> { let rows = if input.published_only { ctx.db - .match3d_work_profile() - .iter() - // 中文注释:列表页优先稳定性,避免二级索引 filter 初始化异常直接打爆模块实例。 - .filter(|row| row.publication_status == MATCH3D_PUBLICATION_PUBLISHED) + .match_3_d_work_profile() + .by_match3d_work_publication_status() + .filter(MATCH3D_PUBLICATION_PUBLISHED) .collect::>() } else { require_non_empty(&input.owner_user_id, "match3d owner_user_id")?; ctx.db - .match3d_work_profile() + .match_3_d_work_profile() .iter() .filter(|row| row.owner_user_id == input.owner_user_id) .collect::>() @@ -727,14 +726,14 @@ fn get_match3d_work_detail_tx( ) -> Result { let row = ctx .db - .match3d_work_profile() + .match_3_d_work_profile() .profile_id() .find(&input.profile_id) .filter(|row| { row.owner_user_id == input.owner_user_id || row.publication_status == MATCH3D_PUBLICATION_PUBLISHED }) - .ok_or_else(|| "match3d_work_profile 不存在".to_string())?; + .ok_or_else(|| "match_3_d_work_profile 不存在".to_string())?; build_work_snapshot(&row) } @@ -744,7 +743,7 @@ fn delete_match3d_work_tx( ) -> Result, String> { let work = find_owned_work(ctx, &input.profile_id, &input.owner_user_id)?; ctx.db - .match3d_work_profile() + .match_3_d_work_profile() .profile_id() .delete(&work.profile_id); for run in ctx @@ -782,14 +781,14 @@ fn start_match3d_run_tx( } let work = ctx .db - .match3d_work_profile() + .match_3_d_work_profile() .profile_id() .find(&input.profile_id) .filter(|row| { row.owner_user_id == input.owner_user_id || row.publication_status == MATCH3D_PUBLICATION_PUBLISHED }) - .ok_or_else(|| "match3d_work_profile 不存在".to_string())?; + .ok_or_else(|| "match_3_d_work_profile 不存在".to_string())?; let started_at_ms = if input.started_at_ms > 0 { input.started_at_ms } else { @@ -966,11 +965,11 @@ fn find_owned_work( require_non_empty(profile_id, "match3d profile_id")?; require_non_empty(owner_user_id, "match3d owner_user_id")?; ctx.db - .match3d_work_profile() + .match_3_d_work_profile() .profile_id() .find(&profile_id.to_string()) .filter(|row| row.owner_user_id == owner_user_id) - .ok_or_else(|| "match3d_work_profile 不存在".to_string()) + .ok_or_else(|| "match_3_d_work_profile 不存在".to_string()) } fn find_owned_run( @@ -1260,17 +1259,17 @@ fn click_result( fn upsert_work(ctx: &ReducerContext, work: Match3DWorkProfileRow) { if ctx .db - .match3d_work_profile() + .match_3_d_work_profile() .profile_id() .find(&work.profile_id) .is_some() { ctx.db - .match3d_work_profile() + .match_3_d_work_profile() .profile_id() .delete(&work.profile_id); } - ctx.db.match3d_work_profile().insert(work); + ctx.db.match_3_d_work_profile().insert(work); } fn replace_session( @@ -1291,10 +1290,10 @@ fn replace_work( next: Match3DWorkProfileRow, ) { ctx.db - .match3d_work_profile() + .match_3_d_work_profile() .profile_id() .delete(¤t.profile_id); - ctx.db.match3d_work_profile().insert(next); + ctx.db.match_3_d_work_profile().insert(next); } fn clone_session(row: &Match3DAgentSessionRow) -> Match3DAgentSessionRow { diff --git a/server-rs/crates/spacetime-module/src/match3d/tables.rs b/server-rs/crates/spacetime-module/src/match3d/tables.rs index bd584074..bc7d131a 100644 --- a/server-rs/crates/spacetime-module/src/match3d/tables.rs +++ b/server-rs/crates/spacetime-module/src/match3d/tables.rs @@ -37,7 +37,7 @@ pub struct Match3DAgentMessageRow { } #[spacetimedb::table( - accessor = match3d_work_profile, + accessor = match_3_d_work_profile, index(accessor = by_match3d_work_owner_user_id, btree(columns = [owner_user_id])), index(accessor = by_match3d_work_publication_status, btree(columns = [publication_status])) )] diff --git a/server-rs/crates/spacetime-module/src/migration.rs b/server-rs/crates/spacetime-module/src/migration.rs index 994f24e6..a3012213 100644 --- a/server-rs/crates/spacetime-module/src/migration.rs +++ b/server-rs/crates/spacetime-module/src/migration.rs @@ -16,7 +16,7 @@ use crate::jump_hop::tables::{ jump_hop_agent_session, jump_hop_event, jump_hop_runtime_run, jump_hop_work_profile, }; use crate::match3d::tables::{ - match3d_agent_message, match3d_agent_session, match3d_runtime_run, match3d_work_profile, + match3d_agent_message, match3d_agent_session, match3d_runtime_run, match_3_d_work_profile, }; use crate::puzzle::{ puzzle_agent_message, puzzle_agent_session, puzzle_event, puzzle_leaderboard_entry, @@ -238,7 +238,7 @@ macro_rules! migration_tables { bark_battle_personal_best_projection, match3d_agent_session, match3d_agent_message, - match3d_work_profile, + match_3_d_work_profile, match3d_runtime_run, jump_hop_agent_session, jump_hop_work_profile, @@ -1324,7 +1324,7 @@ fn normalize_migration_row(table_name: &str, value: &serde_json::Value) -> serde .or_insert_with(|| serde_json::Value::Bool(true)); } } - if table_name == "match3d_work_profile" { + if table_name == "match_3_d_work_profile" || table_name == "match3d_work_profile" { if let Some(object) = next_value.as_object_mut() { // 中文注释:作品可见性字段晚于首版作品表加入,旧迁移包按默认显示兼容。 object diff --git a/server-rs/crates/spacetime-module/src/runtime/admin_work_visibility.rs b/server-rs/crates/spacetime-module/src/runtime/admin_work_visibility.rs index 77524773..fd7e3249 100644 --- a/server-rs/crates/spacetime-module/src/runtime/admin_work_visibility.rs +++ b/server-rs/crates/spacetime-module/src/runtime/admin_work_visibility.rs @@ -349,9 +349,9 @@ fn wooden_fish_work_visibility_snapshot( fn list_match3d_work_visibility(ctx: &ReducerContext) -> Vec { ctx.db - .match3d_work_profile() - .iter() - .filter(|row| row.publication_status == MATCH3D_PUBLICATION_PUBLISHED) + .match_3_d_work_profile() + .by_match3d_work_publication_status() + .filter(MATCH3D_PUBLICATION_PUBLISHED) .map(|row| match3d_work_visibility_snapshot(&row)) .collect() } @@ -363,7 +363,7 @@ fn update_match3d_work_visibility( ) -> Result { let row = ctx .db - .match3d_work_profile() + .match_3_d_work_profile() .profile_id() .find(&profile_id.to_string()) .ok_or_else(|| "抓大鹅作品不存在".to_string())?; @@ -374,10 +374,10 @@ fn update_match3d_work_visibility( let snapshot = match3d_work_visibility_snapshot(&next); let profile_id = next.profile_id.clone(); ctx.db - .match3d_work_profile() + .match_3_d_work_profile() .profile_id() .delete(&profile_id); - ctx.db.match3d_work_profile().insert(next); + ctx.db.match_3_d_work_profile().insert(next); Ok(snapshot) }