f536987a7e
- doc: add comment
109 lines
5.9 KiB
Go
109 lines
5.9 KiB
Go
// Package transaction 实现服务端更新请求的事务状态机与持久化层。
|
||
//
|
||
// 该包负责把一次单机更新请求建模为一个持久化的事务记录,并通过严格的
|
||
// 状态机约束其生命周期:从 CREATED 一路推进到 COMMITTED,或进入
|
||
// ROLLING_BACK/ROLLED_BACK/FAILED 等终态。事务的执行遵循“先记录意图、
|
||
// 再执行外部副作用、最后 inspect 核对”的协议,以保证进程崩溃后能够安全恢复。
|
||
//
|
||
// 包内数据统一存储在单个本地 SQLite 数据库中(见 store.go),Coordinator
|
||
// 负责在进程内串行化执行并驱动外部步骤,其余类型则定义了贯穿全局的数据模型、
|
||
// 状态、事件与错误约定。
|
||
package transaction
|
||
|
||
import (
|
||
"encoding/json"
|
||
"time"
|
||
)
|
||
|
||
// Transaction 一次更新请求的服务端持久化快照。
|
||
//
|
||
// 它同时承担幂等控制与状态推进两个职责:IdempotencyKey 唯一标识一次客户端
|
||
// 重试,Version 用于乐观锁防止并发覆盖,State 记录当前状态机位置。除终态外,
|
||
// 数据库中同时最多只允许存在一条未结束的事务(由单活动事务索引保证)。
|
||
type Transaction struct {
|
||
ID string // 事务唯一标识,为空时由存储层自动生成。
|
||
IdempotencyKey string // 幂等键,重复请求据此返回同一事务。
|
||
Source string // 请求来源,如 ymsctl 或守护进程。
|
||
Service string // 目标服务名,如 backend。
|
||
Request json.RawMessage // 原始请求载荷,仅作快照保存。
|
||
State State // 当前状态机状态。
|
||
Version int64 // 乐观锁版本号,每次状态变化自增。
|
||
CreatedAt time.Time // 事务首次创建时间(UTC)。
|
||
UpdatedAt time.Time // 最近一次变更时间(UTC)。
|
||
}
|
||
|
||
// ListFilter ymsctl list 命令查询历史记录时使用的过滤条件。
|
||
//
|
||
// 所有字段均按精确值匹配,服务端不会对过滤条件做任何推断或模糊处理。
|
||
type ListFilter struct {
|
||
Limit int // 最多返回的记录条数,必须在 1 到 1000 之间。
|
||
Service string // 按服务名精确过滤,为空表示不过滤。
|
||
State State // 按状态精确过滤,为空表示不过滤。
|
||
}
|
||
|
||
// CreateRequest 包含创建事务所需的不可变请求信息。
|
||
//
|
||
// 该结构体是 CreateTransaction 的入参,其中的 Request 必须是合法的 JSON,
|
||
// 否则创建会被拒绝;空请求会被规范化为空对象 {}。
|
||
type CreateRequest struct {
|
||
ID string // 事务唯一标识,允许留空由存储层生成。
|
||
IdempotencyKey string // 幂等键,必填且不能为空白。
|
||
Source string // 请求来源,必填且不能为空白。
|
||
Service string // 目标服务名,必填且不能为空白。
|
||
Request json.RawMessage // 原始请求载荷,必须是合法 JSON。
|
||
}
|
||
|
||
// StepStatus 外部步骤的持久化执行状态。
|
||
//
|
||
// 它描述了单个外部副作用在“记录意图 -> 执行 -> 核对”协议中所处的阶段,
|
||
// 只有 SUCCEEDED 与 FAILED 是最终状态,INTENT_RECORDED 表示仍需执行或核对。
|
||
type StepStatus string
|
||
|
||
const (
|
||
StepIntentRecorded StepStatus = "INTENT_RECORDED" // 已记录意图,尚未确定最终结果。
|
||
StepSucceeded StepStatus = "SUCCEEDED" // 外部副作用已确认成功发生。
|
||
StepFailed StepStatus = "FAILED" // 外部副作用已确认未成功发生。
|
||
)
|
||
|
||
// Step 记录一次外部副作用的意图和最终核对结果。
|
||
//
|
||
// 一条步骤在事务生命周期内由 step_key 唯一标识,意图(Intent)在副作用执行前
|
||
// 必须已经落库,结果(Result)则在 inspect 核对后写入,用于崩溃恢复时判断
|
||
// 副作用是否真实发生,从而避免重复执行或丢失执行。
|
||
type Step struct {
|
||
TransactionID string // 所属事务的 ID。
|
||
Key string // 步骤在事务内的唯一键。
|
||
Name string // 步骤的语义名称,用于日志与事件展示。
|
||
Status StepStatus // 步骤当前状态。
|
||
Intent json.RawMessage // 执行前持久化的意图载荷。
|
||
Result json.RawMessage // 核对后持久化的结果载荷,可为空。
|
||
Error string // 步骤失败时的错误信息,成功时为空字符串。
|
||
CreatedAt time.Time // 步骤意图首次记录时间(UTC)。
|
||
UpdatedAt time.Time // 步骤最近一次变更时间(UTC)。
|
||
}
|
||
|
||
// StepIntent 执行外部操作前必须先持久化的内容。
|
||
//
|
||
// 它描述了将要执行的外部副作用,只有先把它成功写入数据库,Coordinator 才会
|
||
// 真正调用 Operation.Apply,从而保证任何时刻都能回答“这一步是否已执行过”。
|
||
type StepIntent struct {
|
||
Key string // 步骤在事务内的唯一键,用于去重与恢复定位。
|
||
Name string // 步骤的语义名称。
|
||
Intent json.RawMessage // 执行该步骤所需的参数载荷。
|
||
}
|
||
|
||
// Event 供查询和 WSS 断联恢复使用的顺序事件。
|
||
//
|
||
// 每个事务状态变化或步骤意图/结果变化都会追加一条有序事件,Sequence 在事务
|
||
// 内单调递增。客户端据此实现断线后的增量拉取(EventsAfter),重放遗漏的事件。
|
||
type Event struct {
|
||
Sequence int64 // 全局递增的事件顺序号。
|
||
TransactionID string // 事件所属事务的 ID。
|
||
StepKey string // 关联的步骤键,事务级事件为空字符串。
|
||
Kind string // 事件类型,如 TRANSACTION_CREATED、STEP_SUCCEEDED。
|
||
FromState State // 变化前的状态,非状态类事件为空。
|
||
ToState State // 变化后的状态,非状态类事件为空。
|
||
Message string // 附加的人类可读信息。
|
||
CreatedAt time.Time // 事件产生时间(UTC)。
|
||
}
|