Files
yms-daemon/internal/transaction/model.go
T
2026-08-17 10:10:14 +08:00

109 lines
5.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 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)。
}