Merge branch 'codex/cache-view-procedure-hotpaths'

This commit is contained in:
kdletters
2026-05-17 21:18:07 +08:00
175 changed files with 7495 additions and 1891 deletions

View File

@@ -95,9 +95,33 @@
- 现象:`/api/runtime/puzzle/gallery` 每个请求都走 `spacetime-client.list_puzzle_gallery()` 调用 SpacetimeDB procedure导致 SpacetimeDB WASM 侧重复组装全量列表,客户端再映射一遍;历史实现还出现过 procedure JSON 字符串往返。
- 原因:`api-server` 的服务器端 `spacetime-client` 没有订阅可公开读取的 gallery 投影,虽然 SDK 支持 client cache但请求路径仍把列表读取当作 procedure 调用。
- 处理:`spacetime-module` 中用 public view `puzzle_gallery_view` 暴露已发布拼图作品;`spacetime-client` 建连接后订阅 `SELECT * FROM puzzle_gallery_view``SELECT * FROM public_work_play_daily_stat WHERE source_type = 'puzzle'` 并等待 `on_applied`HTTP gallery 只从 `connection.db().puzzle_gallery_view().iter()` 本地 cache 读取和排序,再用已同步的 `public_work_play_daily_stat` 在本地聚合 7 日播放数。旧 `list_puzzle_gallery` procedure 只作兼容,不再作为 HTTP gallery 主路径。
- 验证:搜索 `server-rs/crates/spacetime-client/src/puzzle.rs` 不应再出现 gallery 主路径调用 `list_puzzle_gallery_then`执行 `cargo check --manifest-path server-rs/Cargo.toml -p spacetime-client``cargo check --manifest-path server-rs/Cargo.toml -p api-server` 和 schema/runtime access 检查。
- 关联:`server-rs/crates/spacetime-module/src/puzzle.rs``server-rs/crates/spacetime-client/src/lib.rs``server-rs/crates/spacetime-client/src/puzzle.rs``/api/runtime/puzzle/gallery`
- 处理:`spacetime-module` 中用 public view `puzzle_gallery_card_view` 暴露已发布拼图作品的列表卡片字段,不携带 `levels` / `anchor_pack` 等详情级载荷`spacetime-client` 建连接后订阅 `SELECT * FROM puzzle_gallery_card_view``SELECT * FROM public_work_play_daily_stat WHERE source_type = 'puzzle'` 并等待 `on_applied`HTTP gallery 通过 `PuzzleGalleryCache` 缓存最终 `PuzzleGalleryResponse` DTO`items` 返回前 10 个完整卡片,`previewRefs` 返回后 10 个作品号引用cache miss / TTL 过期时单飞重建,后台 cleanup task 周期清理旧响应。旧 `list_puzzle_gallery` procedure 只作兼容,不再作为 HTTP gallery 主路径。
- 验证:搜索 `server-rs/crates/spacetime-client/src/puzzle.rs` 不应再出现 gallery 主路径调用 `list_puzzle_gallery_then`搜索 `server-rs/crates/spacetime-client/src/lib.rs` 应订阅 `puzzle_gallery_card_view`;执行 `npm run spacetime:generate``cargo check --manifest-path server-rs/Cargo.toml -p spacetime-client``cargo check --manifest-path server-rs/Cargo.toml -p api-server` 和 schema/runtime access 检查。
- 关联:`server-rs/crates/spacetime-module/src/puzzle.rs``server-rs/crates/spacetime-client/src/lib.rs``server-rs/crates/spacetime-client/src/puzzle.rs``server-rs/crates/api-server/src/puzzle_gallery_cache.rs``/api/runtime/puzzle/gallery`
## Windows 本地直连高 VU 压测不要误判成业务内存泄漏
- 现象:本地 Windows release `api-server` 直连 K6 压测时250 RPS、`PREALLOCATED_VUS=300` 能把进程 private memory 瞬时推到约 7GB同样配置打 `/healthz` 小响应也能复现,压测结束后回落到 100MB 级。
- 原因:高水位主要来自本机直连的 K6 VU / 长连接 / Hyper 发送链路和 Windows 连接缓冲,不是 SpacetimeDB procedure、拼图 JSON 缓存或 OTEL exporter。降低到接近真实并发的 VU 后,同样 250 RPS 拼图广场 p95 约 9ms峰值约 600MB。
- 处理:本地容量判断时让 `PREALLOCATED_VUS` / `MAX_VUS` 接近真实并发,不要把过高 VU 预分配当作默认吞吐测试;同时观察 `process.memory.*``process.windows.handle.count``genarrative.http.server.response_bodies.in_flight``genarrative.http.server.request_permits.available``genarrative.puzzle_gallery.cache.*``genarrative.spacetime.read.*`。如果内存高但 body in-flight、背压 permit、cache rebuild 和 SpacetimeDB read 都不显示积压,优先按连接 / 发送链路高水位处理。
- 验证:对照打 `/api/runtime/puzzle/gallery``/healthz`;对比 `PREALLOCATED_VUS=300 MAX_VUS=800``PREALLOCATED_VUS=20 MAX_VUS=40`;压测结束后继续采样 10 秒确认 private memory 回落。
- 关联:`scripts/loadtest/README.md``docs/【开发运维】本地开发验证与生产运维-2026-05-15.md``server-rs/crates/api-server/src/process_metrics.rs``server-rs/crates/api-server/src/telemetry.rs`
## 多玩法公开广场列表优先订阅 public view / read model
- 现象:抓大鹅、方洞挑战、视觉小说、大鱼吃小鱼等公开列表如果沿用 `list_*_works` procedure即使只读已发布作品也会在每个 HTTP 请求里回到 SpacetimeDB WASM 侧扫描、反序列化配置并组装列表50RPS 以上容易变成热点。
- 原因:个人作品列表和公开广场列表复用了同一套 procedure 输入,导致公开列表为了通过 owner 校验传固定占位 owner并把可长期同步的公开读模型当成请求期查询。
- 处理:每个公开广场新增或复用专用 public view / public read model`match_3_d_gallery_view``square_hole_gallery_view``visual_novel_gallery_view``big_fish_gallery_view``spacetime-client` 建连接后订阅这些 view 和对应 `public_work_play_daily_stat` source_type 桶HTTP gallery 只读本地 cache。个人作品列表、详情、发布、点赞、游玩记录和 Remix 仍走原有 procedure / reducer。
- 验证:搜索 `server-rs/crates/spacetime-client/src/{match3d,square_hole,visual_novel,big_fish}.rs`,公开 gallery 主路径应读取 `connection.db().*_gallery_view()`,不应调用 `list_*_works_with_input`;执行 `npm run spacetime:generate``cargo check -p spacetime-client --manifest-path server-rs/Cargo.toml``cargo check -p api-server --manifest-path server-rs/Cargo.toml``npm run check:spacetime-schema`
- 关联:`server-rs/crates/spacetime-module/src/match3d/mod.rs``server-rs/crates/spacetime-module/src/square_hole/mod.rs``server-rs/crates/spacetime-module/src/visual_novel.rs``server-rs/crates/spacetime-module/src/big_fish/session.rs``docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`
## 自定义世界广场和创作入口配置不要每次 HTTP 请求调用只读 procedure
- 现象:`/api/runtime/custom-world-gallery` 每次请求调用 `list_custom_world_gallery_entries` procedure入口熔断中间件每个玩法请求调用 `get_creation_entry_config` procedure50RPS 以上会把 SpacetimeDB procedure 调用变成热点。
- 原因:`custom_world_gallery_entry``creation_entry_config``creation_entry_type_config` 已经是可订阅读模型或配置表,但 HTTP 路径仍按“请求到来再查 procedure”处理。
- 处理:`spacetime-client` 长连接订阅 `custom_world_gallery_entry``public_work_play_daily_stat``custom-world` 桶、`creation_entry_config``creation_entry_type_config`custom-world gallery 从本地 cache 排序并聚合 7 日播放数;入口配置优先读订阅 cachecache 缺失时用最近一次成功内存快照,再兜底调用 `get_creation_entry_config` 完成旧库兼容。旧 `list_custom_world_gallery_entries` procedure 只允许作为旧库缺少 gallery 行时的一次性同步兜底。
- 验证:搜索 `server-rs/crates/spacetime-client/src/custom_world.rs`gallery 主路径应是 `read_after_connect` 读取 `custom_world_gallery_entry()`;搜索 `server-rs/crates/spacetime-client/src/runtime.rs``get_creation_entry_config` 应优先读取 `creation_entry_config()``creation_entry_type_config()`。执行 `cargo check -p spacetime-client --manifest-path server-rs/Cargo.toml``cargo check -p api-server --manifest-path server-rs/Cargo.toml`
- 关联:`server-rs/crates/spacetime-client/src/lib.rs``server-rs/crates/spacetime-client/src/custom_world.rs``server-rs/crates/spacetime-client/src/runtime.rs``docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`
## 陶泥儿 logo 生图慢请求先缩短 prompt 并单张串行