修复 inline 路径修复性回读缺少绝对 deadline
Project CI / Repository checks (pull_request) Successful in 1m6s
Project CI / Native shell tests (pull_request) Successful in 2m28s
Project CI / Backend tests (pull_request) Successful in 3m30s
Project CI / Frontend tests (pull_request) Successful in 1m14s

上一轮把修复性回读绑到外层 request_deadline,但 with_external_call_deadline
只在队列 worker 与 openai_image_generation 两处调用,inline HTTP 请求的
RequestContext 默认 external_call_deadline=None,于是 download_deadline 传下去
仍是 None,走无界 download.await——该修复实际只对队列模式生效。

守卫改为在 request_deadline 缺失时自行以 Instant::now() +
EDITOR_PIXEL_ART_MAX_PROCESSING_DURATION 重新计时派生上界,两种模式下都不再
出现无界 GET。结构断言同时要求出现 unwrap_or_else 兜底与该常量。

同时修正决策记录里「最多增加一次 OSS GET」的措辞:约束是不重复读取已成功
取得的对象,而非整个请求至多一次 GET;第一次回读失败或被像素预算掐断时
允许第二次也是最后一次尝试,不视为违规。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-29 13:12:21 +00:00
parent 9a37deeaf0
commit bc28f00c2d
2 changed files with 23 additions and 6 deletions
@@ -24,7 +24,9 @@
- 影响范围:`server-rs/crates/api-server/src/editor_project.rs` 的角色与图标像素规整降级路径;不改变成功路径、OSS PUT 次数、资源类型、画布项或前端契约,OSS GET 仍只在尺寸漂移时发生。
- 验证方式:`pixel_art_degrade_paths_guard_postprocessed_delivery_dimensions` 结构断言固定"降级分支不得返回 `(postprocessed, None, …)`"与守卫的委托实现;运行 `cargo test -p api-server editor_project --manifest-path server-rs/Cargo.toml``npm run check:rustfmt``npm run check:encoding``git diff --check`
- 关联文档:本文件「2026-07-29 角色带背景原图与透明图统一交付尺寸」与「2026-07-28 图片生成风格使用可扩展字段并以纯内存像素规整首发」。
- 补充(同日):守卫的回读必须分两类处理,否则会把「最多增加一次 OSS GET」放大成两次、且第二次无界。已取得 provider 原图的四条降级分支(permit 获取失败、worker 内 deadline、join 异常、worker 超时)改走纯内存守卫 `degrade_editor_pixel_art_with_provider_source`,零额外 GET;尚未取得原图的三条分支(进函数即预算耗尽、第一次回读失败、第一次回读超时)才走会回读的守卫,且该次 GET 以**外层请求 deadline**(而非已耗尽的像素预算)为绝对上界——用像素预算绑会让修复必然失败,不绑则突破预算。`apply_editor_postprocessed_alpha_from_persisted_provider_source_or_original` 因此新增可选 `download_deadline`,非像素路径传 `None` 保持既有语义不变。计数断言固定「回读守卫 3 处、内存守卫 4 处」,防止后续新增分支时误用回读版本。
- 补充(同日):守卫的回读必须分两类处理。已取得 provider 原图的四条降级分支(permit 获取失败、worker 内 deadline、join 异常、worker 超时)改走纯内存守卫 `degrade_editor_pixel_art_with_provider_source`,零额外 GET;尚未取得原图的三条分支(进函数即预算耗尽、第一次回读失败、第一次回读超时)才走会回读的守卫。计数断言固定「回读守卫 3 处、内存守卫 4 处」,防止后续新增分支时误用回读版本。
- OSS 回读口径(修正此前「最多增加一次 OSS GET」的措辞):约束是**不重复读取已经成功取得的对象**,而不是"整个请求至多一次 GET"。仅在尺寸漂移且尚未持有原图时才发起最多一次修复性回读,失败后不再重试;因此第一次回读失败或被像素预算掐断时,允许存在第二次、也是最后一次尝试——第一次超时往往并非 OSS 异常,而是被 30 秒像素预算切断,此时对象通常可正常读取,放弃修复反而会让角色更频繁地退化为原图单产物。
- 回读上界:修复性回读必须始终有绝对 deadline。优先取外层 `request_deadline`,但它只在队列 worker 路径上有值——inline HTTP 请求的 `RequestContext` 默认 `external_call_deadline = None`,此时守卫自行以 `Instant::now() + EDITOR_PIXEL_ART_MAX_PROCESSING_DURATION` 重新计时派生上界,不得退化为无界 `download.await``apply_editor_postprocessed_alpha_from_persisted_provider_source_or_original` 的可选 `download_deadline` 只对像素守卫传值,非像素路径继续传 `None` 保持既有语义不变。结构断言固定守卫内必须同时出现 `request_deadline.unwrap_or_else(``EDITOR_PIXEL_ART_MAX_PROCESSING_DURATION`,防止兜底上界被移除后静默退回无界。
---