feat: persist workflow timers and bounded poll rounds

This commit is contained in:
2026-09-18 03:03:31 +08:00
parent f602a5ee05
commit e2baffbe37
21 changed files with 1201 additions and 28 deletions

View File

@@ -13,7 +13,7 @@ import (
weave "git.yuntuo.hk/k2safe/orbit/weave/model"
)
// WorkflowRuntime 消费持久化结果与根推进检查点;不持有业务执行租约或调用业务系统。
// WorkflowRuntime 消费持久化结果、根推进与等待时钟检查点;不持有业务执行租约或调用业务系统。
// 每个候选独立短事务,数据库行锁决定唯一推进权,节点内存不保存恢复游标。
type WorkflowRuntime struct {
db *sql.DB
@@ -30,7 +30,7 @@ func NewWorkflowRuntime(db *sql.DB, node core.ID) (*WorkflowRuntime, error) {
type WorkflowRuntimeStats struct {
Examined int // Examined 本批取出的持久化候选数,包含被其他节点先处理或跳过的记录。
Consumed int // Consumed 已提交确认或隔离的内部结果数,事务回滚不计入。
Advanced int // Advanced 已提交推进的根检查点数,不等于业务任务执行次数。
Advanced int // Advanced 已提交推进的根或等待检查点数,不等于业务任务执行次数。
}
type workflowCandidate struct {
@@ -129,12 +129,16 @@ func (r *WorkflowRuntime) process(ctx context.Context, c workflowCandidate, skip
if due.After(now) {
return nil
}
var checkpoint struct {
SchemaVersion uint32 `json:"schema_version"`
Kind string `json:"kind"`
var checkpoint workflowCheckpoint
if json.Unmarshal(raw, &checkpoint) != nil || checkpoint.SchemaVersion != 1 {
return errors.New("workflow checkpoint invalid")
}
if checkpoint.Kind == "TIMER" || checkpoint.Kind == "POLL" {
done, err = r.advanceClock(ctx, tx, g, c, step, expected, checkpoint, allow, now)
return err
}
root := g.steps[workflowRootKey]
if json.Unmarshal(raw, &checkpoint) != nil || checkpoint.SchemaVersion != 1 || checkpoint.Kind != "ROOT" || step != root.view.ID || expected > root.view.Revision {
if checkpoint.Kind != "ROOT" || checkpoint.ActivationID != nil || step != root.view.ID || expected > root.view.Revision {
return errors.New("workflow checkpoint invalid")
}
if g.view.State.Terminal() {