From 84f6d177dcc615d9b4de672d70e60de9af47a608 Mon Sep 17 00:00:00 2001 From: Linghong Date: Sat, 1 Aug 2026 11:14:31 +0000 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E5=AE=8C=E7=BE=8E=E5=83=8F?= =?UTF-8?q?=E7=B4=A0=E5=BD=92=E5=B1=9E=E6=A0=A1=E9=AA=8C=E7=9A=84=20RPC=20?= =?UTF-8?q?=E8=AE=A1=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit e5fb51d1a 的提交说明与 decision-log 写「整段由 8 次降为 3 次(兜底 4 次)」, 实际是 8 → 4,兜底最多 5。漏数的是函数末尾恒定执行的 get_asset_object_by_location——它承担存储 taxonomy 的非静态门禁,成本与账号 规模无关,本来就明确保留,数总数时却被漏掉。 错因是把「全账号扫描削减 6 → 2」和「整段 RPC 总数」两个口径串了。改后按调用 逐条列出,不再只给一个需要口算的总数。 一并记下:兜底分支上同一个 objectKey 会被点查两次(ensure_editor_reference_ asset_object_owned 做归属校验一次、末尾存储门禁一次,参数相同),可合并但收益 远小于已削掉的全账号扫描,暂不处理。 计数错误不影响 deadline 修复、去重实现和测试守卫——守卫钉的是两处全账号扫描 各 1 次,该数正确。e5fb51d1a 的提交说明属不可变历史,未改写。 Co-Authored-By: Claude Opus 5 --- docs/project-memory/shared-memory/decision-log.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/project-memory/shared-memory/decision-log.md b/docs/project-memory/shared-memory/decision-log.md index bdecc6b77..46459ec59 100644 --- a/docs/project-memory/shared-memory/decision-log.md +++ b/docs/project-memory/shared-memory/decision-log.md @@ -5946,7 +5946,7 @@ - 缺陷:`POST /api/editor/images/pixel-art-snaps` 在合法 `assetId` 且不带 `sourceResourceId` 时,取得端点准入许可后到 OSS 下载之间会顺序执行 8 次 SpacetimeDB 调用,且全是裸 `await`,第一次真正应用 30 秒预算的是下载。其中 `list_editor_projects` + `get_editor_asset_library` 这对全账号扫描重复了三轮——`resolve_editor_reference_object_key_for_owner` 内部两个子函数各扫一轮,`resolve_editor_pixel_art_source_for_owner` 再扫第三轮,拉的是同一份数据。 - 契约澄清:预算从 handler 入口「起算」不等于「覆盖」。此前文档写成覆盖 SpacetimeDB 读取是错的:deadline 是绝对时刻,早起算只让后续余额更少,中间不检查就不会在该阶段返回 `504`,请求会一路走到下载才失败并返回下载相关文案,误导排障。同时端点准入许可全程被这些无界调用占用,把并发闸自身变成瓶颈。 -- 决策一(去重):参照抠图入口 `resolve_editor_background_removal_source` 的既有范式——扫一次,注册 ID 解析、归属校验和跨记录 `asset_kind` 收集全部交给 `_from_records` 纯函数在内存里完成。`resolve_editor_pixel_art_source_for_owner` 自行取一次 owner 快照后复用,不再调用 `resolve_editor_reference_object_key_for_owner`;该包装是给没有任何上下文的调用方用的,保持不动。归属校验命中已登记记录即短路,只有两份记录都查不到时才回落 `ensure_editor_reference_asset_object_owned` 点查。全账号 RPC 由 6 次降为 2 次,整段由 8 次降为 3 次(未登记对象兜底时 4 次)。 +- 决策一(去重):参照抠图入口 `resolve_editor_background_removal_source` 的既有范式——扫一次,注册 ID 解析、归属校验和跨记录 `asset_kind` 收集全部交给 `_from_records` 纯函数在内存里完成。`resolve_editor_pixel_art_source_for_owner` 自行取一次 owner 快照后复用,不再调用 `resolve_editor_reference_object_key_for_owner`;该包装是给没有任何上下文的调用方用的,保持不动。归属校验命中已登记记录即短路,只有两份记录都查不到时才回落 `ensure_editor_reference_asset_object_owned` 点查。全账号 RPC 由 6 次降为 2 次。整段合法 `assetId` 链由 8 次降为 4 次——`get_editor_project`、`list_editor_projects`、`get_editor_asset_library`,加上恒定执行的 `get_asset_object_by_location`(承担存储 taxonomy 的非静态门禁,成本与账号规模无关,两条路径都保留);objectKey 未登记在 owner 任何记录里时多一次 `ensure_editor_reference_asset_object_owned` 的点查,最多 5 次。该兜底分支上同一个 objectKey 会被点查两次(归属校验一次、存储门禁一次,参数相同),可合并但收益远小于已削掉的全账号扫描,暂不处理。 - 决策二(预算):`get_editor_project` 到来源解析结束整体包进 `tokio::time::timeout_at`,超时返回 `504` 且文案指向归属校验而非下载。不重复写 `Instant::now() >= deadline` 预检——紧邻的 `acquire_editor_pixel_art_snap_permit` 已做该预检,成功即意味着未超预算,且本块首个 await 是网络 IO 不会立即就绪,不构成 `timeout_at` 先 poll 再判超时的陷阱。 - 验证:顺序断言新增 `tokio::time::timeout_at(` 与超时文案;参照 `937378ab9` 的做法用 `assert_function_occurrence_count` 把 `resolve_editor_pixel_art_source_for_owner` 内的 `.list_editor_projects(` 和 `.get_editor_asset_library(` 各钉为 1 次,并用 `assert_function_not_contains` 禁止该函数重新调用取数包装。后者断言的是调用形式 `resolve_editor_reference_object_key_for_owner(state` 而非裸函数名,否则会命中生产代码里说明「老包装保持不动」的注释——该陷阱在编写时即由测试抓出。 - 关联文档:`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`。