Skip to content

fix(channel): 修复问答与审批续跑后的输出丢失 - #1159

Merged
qqqqqf-q merged 12 commits into
mainfrom
codex/channel-decision-continuation
Sep 6, 2026
Merged

fix(channel): 修复问答与审批续跑后的输出丢失#1159
qqqqqf-q merged 12 commits into
mainfrom
codex/channel-decision-continuation

Conversation

@qqqqqf-q

@qqqqqf-q qqqqqf-q commented Sep 5, 2026

Copy link
Copy Markdown
Member

修复 ask_user / 工具审批接受后,后台继续运行但渠道收不到后续回复的问题。答案接受后立即回执并同步问题卡片,随后转发续跑文本、附件及下一张问题卡片;接受后的输出错误与答案提交失败分开反馈。

实现

  • 按命令隔离原始输出追加日志:Memory 保存独立事件列表,Redis 使用 list + 元数据 hash,追加时不重写完整日志。仅渠道续跑启用,Web 保持原有消息投影路径。
  • 订阅通知只负责唤醒;读取者按游标从日志恢复,定期读取补偿丢失通知。共享存储的独占消费权避免并发重复命令重复转发。
  • 日志完成或显式失败后释放事件,保留消费权及终态标记至 TTL。读取失败立即退出并反馈中断。
  • 运行归属及终态检查继续复用 Session Runtime。运行归属/fence 来源为 feat(session-runtime): implement durable distributed session runtime #865(207844099),finishing/finish retry 来源为 fix(runtime): make terminal finalization crash-recoverable #1107(a23d24a1f);Backend 及通知设施来源为 feat(runtime): add session runtime foundation #800(47fd904d4)。本 PR 新增的追加日志和游标读取不属于原有 Snapshot 恢复算法。
  • 不新增 PostgreSQL migration、SQL 查询、生成数据库代码或依赖。

#1156 及部署的关系

#1156 已先合入 main(29ddb19d8),负责答案接收、按钮 fence 和停止清理。本 PR head 968bc28 已同步该 main。渠道错误处理冲突沿用已验证组合版本:提交前失败显示本地化提交错误,接受后失败显示输出中断。

Server / Channel 应协调更新;不要假定任意新旧混跑兼容。新 Channel 调用旧 Server 的 StopTurn 会返回 Unimplemented;旧 runtime owner 不支持渠道追加日志。上线及回滚均应暂停入口、处理在途输出并协调切换全部相关实例。回滚不撤销已提交答案或已取消问题。

成本和边界

每个命令最多保留 8 MiB、32768 条原始事件,超限显式中断,遗留日志沿用 Backend TTL。此日志不是持久化渠道 outbox,不承诺外部消息 exactly-once,也不承诺断线或进程重启后完整补发。Memory 进程丢失、Redis 状态丢失仍是恢复边界。

代码量自审

远端 base 29ddb19,head 968bc28,按 base...head 统计:

分类 新增 删除 净变化
全部 1386 31 +1355
测试,含注释和空行 683 2 +681
生产文件 703 29 +674
生产代码,排除纯注释和空行 575 29 +546
自动生成内容 0 0 0

没有独立批量机械变更;局部字段对齐仍计入生产行。新增生产代码主要用于两种 Backend 的追加/读取/消费权/释放、渠道日志读取、接受回执和中断处理。测试覆盖并发重试、输出突发、通知丢失、终态退出、存储失败、日志上限与释放、Web 隔离。少量问答/审批错误处理仍有重复,不为压行数扩大抽象。

自审修复:纯 Web 不再写渠道日志;并发重复提交只允许一个转发者;日志读取失败不再等待至请求超时。当前未发现新的已复现代码阻塞项。重点行为为渠道续跑、重复提交、停止等待及协调升级边界。

验证与真人 QA

组合源码 tree d1269ab 的全仓 go test ./... 通过;独立 PostgreSQL 的 fenced 问答持久化测试及既有 finishing migration 往返测试通过;独立 Redis 的通知丢失恢复、跨客户端消费权及释放测试通过。混合版本 RPC 测试确认旧 Run 兼容、新 Stop 对旧服务不兼容。本次同步 main 后,internal、cmd、db、go.mod、go.sum 与上述组合源码逐文件一致,保持这些验证的代码范围。

2026-09-06,用户在 @Memoh_test_bot 对组合版本明确确认真人 happy path 通过并提供截图:自由文字“0 点”提交后原样回复、原问题显示答案、再次提问后的选项答案与续跑回复送达。部署来源为 #1156 ec274d9 + #1159 1150071,版本 qa-1156-1159-latest。此次 main 同步保留已验证后端行为。

真人确认不覆盖 Other、多题、/stop、工具审批、群聊权限或跨实例故障恢复的完整人工验证;自动检查不替代这些人工项目。PR 最新 CI 由本次同步 main 后的检查结果单独确认。

Snapshot 只表示 session 运行状态;每个答案的原始事件改存 Backend 新增的
DecisionOutputStore(Memory 切片 / Redis list+hash),每条事件只追加一条,
不再整体重写快照。读端游标、Claimed 仲裁、终态宽限、订阅唤醒逻辑不变,
但唤醒改用 backend 原始 pub/sub,日志本身是唯一事实源。

送达完成后释放日志条目,保留 done/claimed 标记到 TTL,避免迟到的重试
再次转发。删除 hydrateSnapshotFromLedger 对合成 key 的特判。
finish 只在 Done/EOF 时置 stop,普通读取错误被调用方忽略并继续等待,
直到请求 context 过期才返回。现在任何错误都停止读取并原样返回。
@qqqqqf-q
qqqqqf-q marked this pull request as ready for review September 6, 2026 08:52
@qqqqqf-q
qqqqqf-q requested review from a team as code owners September 6, 2026 08:52
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 6, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-06T08:59:05.903684Z 968bc28 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@qqqqqf-q
qqqqqf-q merged commit 8d5dfae into main Sep 6, 2026
14 checks passed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 968bc2888f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

// Execution deduplication can return success to concurrent callers that both
// passed routing's replay check. Shared backend arbitration gives only one of
// those callers permission to forward, including across server instances.
claimed, err := m.backend.ClaimDecisionOutput(ctx, ref)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Release abandoned output claims before allowing retries

If the channel/gRPC context is canceled after this claim succeeds—such as while sending the acceptance receipt or forwarding later events—the claim remains set until TTL expiry, while ReleaseDecisionOutput is never reached and cannot clear the claim anyway. The continuation still writes its output, but a retry with the same control ID exits through the result.Replayed branch before reading the log, permanently dropping that reply. Use a renewable consumer lease or otherwise allow takeover when the original forwarder did not complete delivery.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant