Skip to content

[Priority: High] [Architecture] 评估并推进从 InMemory Store 到 Database Store 的迁移 #304

@liujuanjuan1984

Description

@liujuanjuan1984

背景

参考外部 issue:liujuanjuan1984/codex-a2a#134

当前仓库的需求同样成立,而且范围应比“只替换一个 InMemoryTaskStore”更明确:

  • 目前 src/opencode_a2a/server/application.pycreate_app() 中直接实例化 InMemoryTaskStore
  • 这意味着 tasks/gettasks/canceltasks/resubscribe 仍然只依赖单进程内存态
  • 服务重启、滚动发布、横向扩容后,任务查询与重订阅无法稳定延续
  • 除了 task store,仓库内还存在几类明确的业务状态目前仍放在内存字典/TTL cache 中,后续应评估是否统一进入数据库持久化

当前实现现状

Server 侧当前在内存中的业务状态

  1. Task records
  • 来源:InMemoryTaskStore
  • 位置:src/opencode_a2a/server/application.py
  • 影响接口:tasks/gettasks/canceltasks/resubscribe、流式执行后的 task replay
  • 这是最明确、最优先需要落库的数据
  1. Session binding / ownership state
  • 位置:src/opencode_a2a/execution/session_manager.py
  • 当前内存态包含:
    • (identity, context_id) -> session_id 绑定关系
    • session_id -> identity owner 关系
    • pending preferred session claims
  • 这些状态决定 session extension / session control 的行为,至少前两类属于业务态,不应永久依赖单进程内存

Client / upstream 协调侧当前在内存中的业务状态

  1. Interrupt request bindings
  • 位置:src/opencode_a2a/opencode_upstream_client.py
  • 当前内存态包含:
    • request_id -> {session_id, interrupt_type, identity, task_id, context_id, expires_at}
    • interrupt tombstones
  • 这部分直接影响 interrupt callback / reply 流程,若服务重启会丢失 request 关联关系

不建议作为首批落库对象的状态

以下更像运行时缓存或并发控制对象,不建议作为本 issue 的首批数据库目标:

  • A2AClientManager 的 outbound client cache
  • SessionManager 的 in-flight create tasks / asyncio locks
  • streaming 过程中的临时聚合状态、事件队列、TTL 临时缓存

这些状态需要的是进程内协调,不是数据库持久化。

问题复现 / 现状缺陷

  1. 启动服务并发起一个会生成 task 的请求
  2. 通过 tasks/gettasks/resubscribe 可以正常查询/重订阅
  3. 重启服务进程后再次查询同一 task / interrupt / session 绑定相关状态
  4. 当前结果:内存态丢失,行为退化为“查不到”或“无法继续原流程”

预期行为

  • Task 状态在服务重启后仍可查询和重订阅
  • Session binding / owner 关系至少具备明确的持久化抽象,不再硬编码为进程内 TTL cache
  • Interrupt request binding 具备可持久化的 registry 抽象,避免 callback/reply 因重启而断链
  • app 装配层不应直接硬编码某个 in-memory implementation

实施建议

第一阶段:最小可交付

  1. 为 task store 引入 backend 配置,而不是在 create_app() 内硬编码 InMemoryTaskStore
  2. 优先支持最小可运行 profile:SQLite
  3. 保持 request handler 只依赖 task store 抽象,不感知具体实现
  4. 保持现有 tasks/gettasks/canceltasks/resubscribe 对外 contract 不变

第二阶段:业务态落库抽象继续收口

  1. 为 session binding / owner state 抽象 repository
  2. 为 interrupt request registry 抽象 repository
  3. 明确哪些字段需要 TTL / expires_at,哪些是业务主记录
  4. 允许开发环境继续使用 in-memory backend,但不要让业务逻辑直接绑定它

验收标准

  • Settings 中存在显式 store backend 配置,app 装配层不再硬编码 InMemoryTaskStore
  • 至少提供一个 database-backed task store profile(优先 SQLite)
  • tasks/gettasks/canceltasks/resubscribe 在内存与数据库后端下行为一致
  • 补最小重启场景验证:重建 app 后仍可查询既有 task
  • session binding / owner state 的持久化方案被明确设计(本 issue 可先实现抽象或首批落地)
  • interrupt request binding / tombstone 的持久化方案被明确设计(本 issue 可先实现抽象或首批落地)
  • 文档补充 backend 配置与本地 SQLite 示例

相关 issue

Git snapshot

  • git rev-parse HEAD: e2eaf3922ea3d50d17fc8eb3d7a4985105a2a7cc

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions