运维事件与 Ops Explorer
OceanWay Outbox Publisher、运维读模型、Admin 查询边界与首期交付范围
本目录把“领域事实已经写入 Outbox”推进为一条可交付的诊断链:事件可靠离开业务事务、消费者幂等生成运维投影、管理员在明确权限下按稳定 ID 查询,并能区分事实、观测、遥测和未知状态。
当前状态:以下内容是已采用的目标架构,运行时尚未实现。现有能力只到受控 Admission、Run/credits Reservation 与事务内 Outbox Append;Public Admission 继续保持
disabled。
它落实 ADR-030,并补充共享内核与资源图、API、数据与基础设施和管理员平台与运维控制面。管理员平台文档定义操作员应该看到什么;本目录定义这些数据怎样产生、谁拥有、如何投递、如何授权查询以及如何证明结果完整。
正式边界
| 能力 | 唯一 Owner | 首期部署位置 | 明确不负责 |
|---|---|---|---|
| Transactional Outbox 业务事件 | 对应 Core 领域模块 | oceanway-core PostgreSQL | 外部 Broker 状态、页面查询 |
| Outbox Dispatcher | Core Operations | oceanway-core 独立 Worker Role | 修改领域事实、执行业务补偿 |
| Event Consumer / Projector | Core Operations | oceanway-core 独立 Worker Role | 通过 Domain Query 拼装缺失事件字段 |
| Operations Read Model | Core Operations | Core 拥有的 PostgreSQL Schema | 成为 Run、Wallet、Asset 或 Gateway 的新事实源 |
| Operations Query API | Core Operations | Core Internal Service Contract | 客户公开查询、任意 SQL 或跨租户枚举 |
| Workforce Query BFF 与 UI | oceanway-admin | admin.oceanway.tech | 拥有投影、直连 Core/Gateway 数据库或更改业务状态 |
| Edge Operational Observation | API Edge 产生,Core Operations 接收 | 受控内部 Intake | 替代领域事件、保证每次请求必达 |
Core Operations 是 Dispatcher、Consumer、Projection 和 Query 的唯一 Owner。Admin 只是 Workforce 面向的 BFF/UI;即使未来将进程独立扩缩容,也不改变仓库与数据所有权,不额外创建零散服务仓。
首期拓扑
首期只使用 PostgreSQL Outbox 与 Core 独立 Worker Role,不引入 Kafka、NATS、Redis Streams 或其他外部 Broker。Dispatcher 仍通过传输接口与消费者边界工作;只有当独立消费者数量、吞吐、保留、跨区域或故障域证据证明 PostgreSQL 模式不再满足目标时,才另立决策引入 Broker。
可靠性语义
- 领域事实、不可变 Event Envelope、冻结的
deliverySetVersion和该版本全部 Mandatory Delivery Row 在同一事务提交;不存在“先写事件、稍后才发现应该投给谁”的窗口。 - 投递语义是 at-least-once,不是 exactly-once;崩溃和超时可以造成安全重投。
- Dispatcher 使用有界、配置化批次做短事务 Claim;外部处理期间不占用 Claim 事务。
- Lease Token 参与所有完成、失败和续租更新,旧 Worker 不能覆盖新 Owner 的结果。
- Consumer Receipt 与 Projection Mutation 在同一事务提交;完整性由一致性快照下的集合反连接与未解决异常共同证明。
- 顺序只保证单个 Aggregate 的
aggregateRevision;不存在全局事件顺序承诺。 - Event Payload 永不修改;投递状态、尝试、隔离和消费回执使用独立表表达。
- Read Model 统一使用
domain_fact | operational_observation | operations_runtime | telemetry_reference | derived_summary五种evidenceKind,并显示投影版本、新鲜度和完整性;“未观测”不等于“没有发生”。 - Dispatcher 的 Delivery、Attempt、Receipt、Quarantine 与投影运行状态属于
operations_runtime,由 Core Query 直接组合,禁止再递归发布“Publisher 发布了事件”一类事件。
批次大小、Lease、心跳、退避、最大尝试、隔离策略、保留期、告警阈值和容量目标都来自部署配置、SLO 与容量验证。本架构不写无证据的固定秒数、次数或批量常数。
当前基线与本阶段目标
截至受控准入基线,Core 已在 Run Admission 事务中原子写入 run.created@1.0 与 wallet.reserved@1.0,Outbox 表和未发布索引已经存在;但当前没有正式 Publisher、Dispatcher Lease、投递尝试、Consumer、Operations Projection 或 Query API。API Edge 的准入前失败与幂等重放也只存在最小脱敏日志,不能声称可从 Outbox 完整还原。
| 能力 | 当前状态 | 准确含义 |
|---|---|---|
| Canonical Event Envelope | 已发布于 Contracts 0.2.0 | 可严格校验现有事件,不代表已有投递 |
| Run Admission Outbox Append | 已验收 | 成功准入在同一事务写入两条待发布事件 |
published_at | 字段存在、没有生产代码更新 | 当前事件仍未正式发布 |
基础 event_receipts | 表与独立 Claim 原语存在 | 不能作为“投影已应用”的回执;先 Claim 后投影会产生崩溃漏应用窗口 |
| Run/Wallet v2 / Observation / Query Contracts | 已采用设计、待发布 | 不能把文档字段写成当前 0.2.0 已有能力;两个 v1 保持原 Schema |
| Dispatcher / Delivery Lease / Quarantine | 待实施 | 当前没有 Worker 或可靠投递状态机 |
| Operations Projector / Read Model | 待实施 | 当前不能按运维投影查询 |
| Admin Run Explorer | 已文档化、待实施 | 目前没有可用页面或 BFF |
本阶段将补齐:
- 发布配对的 Tenant-aware
run.created@2.0 + wallet.reserved@2.0低敏、自包含准入事件;首个 Producer 仍只允许 Organization。两个 v1 保持原 Schema,仅作为 Legacy/Partial 消费。 - 建立不可变事件与独立投递状态模型、Dispatcher 和幂等 Consumer。
- 建立 Versioned Operations Projection 与 Shadow Rebuild。
- 建立 Edge Observation Intake,明确 best-effort、已接受记录范围和已知健康窗口;不声称请求覆盖完整或能检测丢失 Observation。
- 向 Admin 提供只读、精确 ID 检索和授权后的 Operation Timeline。
这仍不包含 Gateway 执行、模型输出、Asset 登记、Metering、Settlement 或公网开放。PUBLIC_ADMISSION_MODE 继续保持 disabled,直到后续全部公开切流门禁通过。
文档导航
- 事件与 Observation 契约:领域事件版本、低敏载荷与 Edge 观测边界。
- Outbox Publisher:Claim、Lease、投递、回执、隔离与重建语义。
- Operations Read Model:投影结构、搜索、时间线、授权与 Shadow Rebuild。
- 可观测性与错误链:事实、Observation、Telemetry、Error 与 Incident 的关系。
- 实施计划与验收:Contracts、Core、Admin 与 Infrastructure 的固定交付顺序。