fix(游戏共创): 合并后修正 game_distribution_game 列顺序(master 的 price_mud_points 回到第 26 位)
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
CI(Backend tests 与 Repository checks)在 `check:spacetime-schema` 红: 「SpacetimeDB 表 game_distribution_game 的第 26 个字段从 price_mud_points 变为 fork_authorization,疑似字段顺序被调整」。 根因:本次合并把两侧各自「在表尾追加」的列并成了「我们的列在 master 的列之前」——schema guard 对表的字段 相对顺序是按 index 逐位比对的(只允许在结构体末尾追加)。 - `game_distribution_game` 表:`price_mud_points`(master 先追加,第 26 位)回到原位,本分支的 `fork_authorization` 追加在它**之后**(表尾); - `GameDistributionGameSnapshot` 按同一纪律排(同一 game 行的 RPC 形状,避免表与快照两套顺序); - 重新生成绑定:`module_bindings/game_distribution_game_type.rs`、`..._game_snapshot_type.rs` (列顺序属 wire format,客户端绑定必须与模块同步); - 两处结构体注释写明该纪律(master 的列保持 index、我们的列追加在后),避免下一次合并再踩; - 文档:`docs/project-memory/shared-memory/pitfalls.md` 增一条「合并 master 后 schema guard 的基线盲区」—— 本地守卫默认基线是 `git merge-base HEAD origin/master`,**merge 提交尚未建立时看不见**这类重排, 因此合并后必须用 `SPACETIME_SCHEMA_BASE_REF=<PR base>` 复跑。 门禁:`SPACETIME_SCHEMA_BASE_REF=9f4c7d76 npm run check:spacetime-schema` 0(98 表);wasm build 0; `cargo check --all-targets` 0;`cargo test -p module-game-distribution` 113 passed;`cargo test -p api-server game_distribution` 101 passed;`cargo test -p module-runtime` 0;`cargo test -p spacetime-client` 43 passed; `cargo test -p spacetime-module` 294 passed / 1 ignored;DTO parity 0(62 组 / 17 构建器 / 15 手拼类型); `check:project-bundle-policy-parity` OK;`check:production-ops` OK;`check:doc-index` OK(261 份);`check:encoding` 0(5525 files);`cargo fmt --all --manifest-path server-rs/Cargo.toml -- --check` 0;`git diff --check` 0。
This commit is contained in:
@@ -6545,3 +6545,12 @@ Cocos Creator 根目录由 `package.json.creator.version` 与普通 `assets/`
|
||||
- **CPU 边界**:发行网关是公开无鉴权端点,压缩按请求实时算。release 构建实测 level 6 为 1.3 MiB→10 ms、8 MiB→59 ms、64 MiB(单文件上限)→522 ms 纯 CPU,因此在 `RELEASE_COMPRESSION_FAST_ABOVE_BYTES`(2 MiB)以上改用 level 1(zlib 端实测 level 1 约为 level 6 的 1/3 耗时、压缩比只差约 3%)。若后续要再做减法,优先把压缩结果按 `(对象键, 资源路径)` 缓存,而不是放宽级别。
|
||||
- **验证**:`cargo test -p api-server --bin api-server -- game_distribution`(新增 ETag 作用域、`If-None-Match` 列表/弱校验命中、`gzip;q=0` 拒绝、文本压缩与二进制/小文件不压、304 无正文、`*` 对包内缺失路径仍 404 等用例);`npx vitest run packages/shared/src/components/PlatformGameLoadingSurface.test.tsx`、`src/components/game-distribution/GameDistributionPages.test.tsx`、`apps/admin-web/src/pages/AdminGameDistributionReviewPage.test.tsx`;`npm run check:game-distribution-ops-rollback-e2e` 47 项通过(含压缩/Vary/ETag/304/不接受 gzip 四条新断言)。真实栈同链路复跑:`phaser.min.js` 1,375,976 B → 353,336 B(gzip,4 Mbps 下 2724 ms → 774 ms),用户端游戏画面 3298 ms → 1543 ms、后台试玩 4587 ms → 2694 ms。
|
||||
- **关联**:`packages/shared/src/components/PlatformGameLoadingSurface.tsx`、`src/components/game-distribution/GamePlayPage.tsx`、`apps/admin-web/src/pages/AdminGameDistributionReviewPage.tsx`、`server-rs/crates/api-server/src/modules/game_distribution.rs`、`deploy/nginx/README.md`。
|
||||
|
||||
## 2026-10-06 合并 master 后 schema guard 的基线盲区:本地全绿、CI 红(表字段相对顺序)
|
||||
|
||||
- **现象**:合并 master(merge 提交 `eeb101458`,PR base `9f4c7d76`)后本地整套门禁全绿,CI 的 **Backend tests** 与 **Repository checks** 却都在 `check:spacetime-schema` 红:`表 game_distribution_game 的第 26 个字段从 price_mud_points 变为 fork_authorization,疑似字段顺序被调整`。
|
||||
- **原因**:schema guard 对**表的字段相对顺序**是按 index 逐位比对的(`baseTable.fields[index]` vs `currentTable.fields[index]`);而**不显式给基线时它取 `git merge-base HEAD origin/master`**——merge 提交还没建时那还是**旧 merge-base**,于是「两侧各自在表尾追加」被并成「我们的列插到了 master 的列前面」这件事本地完全看不见;merge 提交一建,基线变成 PR base,CI 立刻红。
|
||||
- **处理(现行口径)**:合并 master 后**先建 merge 提交**,再用 PR base 复跑 `SPACETIME_SCHEMA_BASE_REF=<PR base> npm run check:spacetime-schema`。列顺序规则:**master 先追加的列保持原 index,我们的追加排它之后**(`price_mud_points` 第 26 位、`fork_authorization` 表尾);对应的 `SpacetimeType` 快照(`GameDistributionGameSnapshot`)按同一条纪律排,避免只改表不改快照。
|
||||
- **别踩**:`migration.rs` 白名单、DTO parity 成员、nginx SPA 路由、Pingora 路由清单都是**集合/无序**判定(各脚本内部 `Set`/`difference`),只有 **SpacetimeDB 表字段顺序**(以及同步生成的 `module_bindings/*` 里的 wire 顺序)对相对顺序敏感;改列序后必须重跑 `spacetime generate` 并只回写受影响文件。
|
||||
- **判据/取证**:`SPACETIME_SCHEMA_BASE_REF=9f4c7d76 npm run check:spacetime-schema`(exit 0)、`cargo check --all-targets` 0、`cargo test -p api-server game_distribution`(101 passed)、`cargo test -p spacetime-module`(294 passed)。
|
||||
- **关联**:`server-rs/crates/spacetime-module/src/game_distribution.rs`(game 表与 game 快照的列序注释)、`server-rs/crates/spacetime-client/src/module_bindings/game_distribution_game_{type,snapshot_type}.rs`、`scripts/check-spacetime-schema-guard.mjs`、`scripts/check-repository-ci.sh`(CI 侧基线传法)。
|
||||
|
||||
+1
-1
@@ -31,8 +31,8 @@ pub struct GameDistributionGameSnapshot {
|
||||
pub local_project_id: Option<String>,
|
||||
pub cover_object_key: Option<String>,
|
||||
pub screenshots_json: Option<String>,
|
||||
pub fork_authorization: String,
|
||||
pub price_mud_points: u64,
|
||||
pub fork_authorization: String,
|
||||
}
|
||||
|
||||
impl __sdk::InModule for GameDistributionGameSnapshot {
|
||||
|
||||
+3
-3
@@ -32,8 +32,8 @@ pub struct GameDistributionGame {
|
||||
pub cover_object_key: Option<String>,
|
||||
pub screenshots_json: Option<String>,
|
||||
pub deleted_at: Option<__sdk::Timestamp>,
|
||||
pub fork_authorization: String,
|
||||
pub price_mud_points: u64,
|
||||
pub fork_authorization: String,
|
||||
}
|
||||
|
||||
impl __sdk::InModule for GameDistributionGame {
|
||||
@@ -69,8 +69,8 @@ pub struct GameDistributionGameCols {
|
||||
pub cover_object_key: __sdk::__query_builder::Col<GameDistributionGame, Option<String>>,
|
||||
pub screenshots_json: __sdk::__query_builder::Col<GameDistributionGame, Option<String>>,
|
||||
pub deleted_at: __sdk::__query_builder::Col<GameDistributionGame, Option<__sdk::Timestamp>>,
|
||||
pub fork_authorization: __sdk::__query_builder::Col<GameDistributionGame, String>,
|
||||
pub price_mud_points: __sdk::__query_builder::Col<GameDistributionGame, u64>,
|
||||
pub fork_authorization: __sdk::__query_builder::Col<GameDistributionGame, String>,
|
||||
}
|
||||
|
||||
impl __sdk::__query_builder::HasCols for GameDistributionGame {
|
||||
@@ -114,8 +114,8 @@ impl __sdk::__query_builder::HasCols for GameDistributionGame {
|
||||
cover_object_key: __sdk::__query_builder::Col::new(table_name, "cover_object_key"),
|
||||
screenshots_json: __sdk::__query_builder::Col::new(table_name, "screenshots_json"),
|
||||
deleted_at: __sdk::__query_builder::Col::new(table_name, "deleted_at"),
|
||||
fork_authorization: __sdk::__query_builder::Col::new(table_name, "fork_authorization"),
|
||||
price_mud_points: __sdk::__query_builder::Col::new(table_name, "price_mud_points"),
|
||||
fork_authorization: __sdk::__query_builder::Col::new(table_name, "fork_authorization"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -765,14 +765,20 @@ pub struct GameDistributionGame {
|
||||
/// 版本行、发行包对象与冻结资料保持不可变,删除只改游戏行的可见性状态。
|
||||
#[default(None::<Timestamp>)]
|
||||
pub(crate) deleted_at: Option<Timestamp>,
|
||||
/// 作品级共创(Fork)授权档位:`forbidden` / `nonCommercial` / `full`。
|
||||
/// 只允许单向提升开放度;旧行按默认「禁止共创」解释。
|
||||
#[default("forbidden")]
|
||||
pub(crate) fork_authorization: String,
|
||||
/// 买断制价格(泥点):`0` 表示免费。只在审核通过时随版本冻结资料整体生效,
|
||||
/// 因此未通过审核的价格不会改变当前公开价格。必须保持在结构体末尾。
|
||||
/// 因此未通过审核的价格不会改变当前公开价格。
|
||||
///
|
||||
/// **列序是 wire format 的一部分**:这一列是 master 侧先追加的(第 26 位),序号必须保持不变;
|
||||
/// 本分支后追加的 `fork_authorization` 必须排它**之后**——`check:spacetime-schema` 只允许在
|
||||
/// 结构体末尾追加,任何相对顺序变化都会被判成字段重排(合并时正是踩了这一条)。
|
||||
#[default(0u64)]
|
||||
pub(crate) price_mud_points: u64,
|
||||
/// 作品级共创(Fork)授权档位:`forbidden` / `nonCommercial` / `full`。
|
||||
/// 只允许单向提升开放度;旧行按默认「禁止共创」解释。
|
||||
///
|
||||
/// 本分支较 master 后追加,因此留在表尾(见上一列的注释)。
|
||||
#[default("forbidden")]
|
||||
pub(crate) fork_authorization: String,
|
||||
}
|
||||
|
||||
/// 作品之间的改编(Fork)血缘:一个作品最多有一个父,主键即子作品 ID。
|
||||
@@ -1572,10 +1578,13 @@ pub struct GameDistributionGameSnapshot {
|
||||
pub local_project_id: Option<String>,
|
||||
pub cover_object_key: Option<String>,
|
||||
pub screenshots_json: Option<String>,
|
||||
/// 买断制价格(泥点);`0` 表示免费。
|
||||
///
|
||||
/// 与表同一条纪律:这一列是 master 侧先追加的,序号保持不变;本分支的
|
||||
/// `fork_authorization` 追加在它**之后**(客户端绑定与之同步生成)。
|
||||
pub price_mud_points: u64,
|
||||
/// 作品级共创授权档位;旧行由表默认值补齐为 `forbidden`。
|
||||
pub fork_authorization: String,
|
||||
/// 买断制价格(泥点);`0` 表示免费。
|
||||
pub price_mud_points: u64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)]
|
||||
|
||||
Reference in New Issue
Block a user