// Package control 定义流程暂停、继续与取消的版本化操作;解除暂停不会清除核查或停止意图。 package control import ( "context" "strings" "unicode/utf8" "git.yuntuo.hk/k2safe/orbit/internal/fault" core "git.yuntuo.hk/k2safe/orbit/model" "git.yuntuo.hk/k2safe/orbit/platform/auth" "git.yuntuo.hk/k2safe/orbit/pulse/service" "git.yuntuo.hk/k2safe/orbit/weave/instance" ) const Action = "workflows:control" // Input 的稳定操作身份由方法参数传入;并发控制只使用control_revision,不与后台结果版本竞争。 type Input struct { Operation string `json:"operation"` // Operation 为PAUSE、RESUME或CANCEL;终结实例不接受新控制操作。 ExpectedControlRevision uint64 `json:"expected_control_revision,string"` // ExpectedControlRevision 调用者观察到的控制版本,必须大于0。 Reason string `json:"reason"` // Reason 必填操作原因,最多1024个Unicode字符,进入不可变审计。 } type Result struct { Instance instance.View `json:"instance"` // Instance 首次操作提交后的冻结回执;当前结果用实例Get读取。 Deduplicated bool `json:"deduplicated"` // Deduplicated 原操作恢复,不重复修改控制版本或计时。 } type Store interface { Apply(context.Context, auth.Token, core.ID, string, Input) (Result, error) } type Service struct{ store Store } func New(store Store) *Service { return &Service{store: store} } func (s *Service) Apply(ctx context.Context, t auth.Token, id core.ID, key string, in Input) (Result, error) { if err := service.ValidateKey(key); err != nil { return Result{}, err } if id.Validate() != nil || in.ExpectedControlRevision == 0 { return Result{}, fault.Invalid("workflow id and positive control revision required") } if in.Operation != "PAUSE" && in.Operation != "RESUME" && in.Operation != "CANCEL" { return Result{}, fault.Invalid("workflow operation must be PAUSE, RESUME or CANCEL") } if !utf8.ValidString(in.Reason) || strings.TrimSpace(in.Reason) == "" || utf8.RuneCountInString(in.Reason) > 1024 || strings.ContainsRune(in.Reason, 0) { return Result{}, fault.Invalid("workflow control reason required, maximum 1024 characters") } return s.store.Apply(ctx, t, id, key, in) }