package orbit import ( "context" "errors" ) // StartWorkflow 固定发布版本;响应不明时保留原键及完整请求核对,不自动创建新身份。 func (c *Client) StartWorkflow(ctx context.Context, key string, in StartWorkflowRequest) (WorkflowStartResult, error) { var out WorkflowStartResult if !validID(in.DefinitionID) || !workflowVersionName(in.Version) { return out, errors.New("invalid workflow definition or version") } err := c.call(ctx, "POST", "/v1/workflows", key, in, &out) if err == nil && (!validID(out.Instance.ID) || out.Instance.DefinitionID != in.DefinitionID || out.Instance.Version != in.Version || out.Instance.Revision == 0) { return WorkflowStartResult{}, errors.New("invalid workflow receipt; reconcile original identity") } return out, err } func (c *Client) GetWorkflow(ctx context.Context, id string) (WorkflowInstance, error) { var out WorkflowInstance if !validID(id) { return out, errors.New("invalid workflow id") } err := c.call(ctx, "GET", "/v1/workflows/"+id, "", nil, &out) if err == nil && out.ID != id { return WorkflowInstance{}, errors.New("workflow identity mismatch") } return out, err } func (c *Client) GetWorkflowSteps(ctx context.Context, id string) (WorkflowSteps, error) { var out WorkflowSteps if !validID(id) { return out, errors.New("invalid workflow id") } err := c.call(ctx, "GET", "/v1/workflows/"+id+"/steps", "", nil, &out) if err == nil && (out.InstanceID != id || out.Steps == nil || len(out.Steps) > 128) { return WorkflowSteps{}, errors.New("invalid workflow steps response") } return out, err } func (c *Client) GetWorkflowStep(ctx context.Context, id, key string) (WorkflowStepDetail, error) { var out WorkflowStepDetail if !validID(id) || !workflowVersionName(key) { return out, errors.New("invalid workflow or step identity") } err := c.call(ctx, "GET", "/v1/workflows/"+id+"/steps/"+key, "", nil, &out) if err == nil && (out.InstanceID != id || out.Step.Key != key) { return WorkflowStepDetail{}, errors.New("workflow step identity mismatch") } return out, err } // ControlWorkflow 使用control_revision;RESUME不会解除人工核查,也不重置截止。 func (c *Client) ControlWorkflow(ctx context.Context, id, key string, in WorkflowControlRequest) (WorkflowControlResult, error) { var out WorkflowControlResult if !validID(id) { return out, errors.New("invalid workflow id") } err := c.call(ctx, "POST", "/v1/workflows/"+id+"/control", key, in, &out) if err == nil && out.Instance.ID != id { return WorkflowControlResult{}, errors.New("invalid workflow control receipt; reconcile original identity") } return out, err } // SendWorkflowSignal 受理不代表消费;必须显式指定步骤及等待代次,原键重报不会跟随新激活。 func (c *Client) SendWorkflowSignal(ctx context.Context, id, key string, in SendWorkflowSignalRequest) (WorkflowSignalResult, error) { var out WorkflowSignalResult if !validID(id) { return out, errors.New("invalid workflow id") } err := c.call(ctx, "POST", "/v1/workflows/"+id+"/signals", key, in, &out) if err == nil && (!validID(out.Signal.ID) || out.Signal.WorkflowID != id || out.Signal.TargetStepKey != in.TargetStepKey || out.Signal.TargetActivationSequence != in.TargetActivationSequence) { return WorkflowSignalResult{}, errors.New("invalid signal receipt; reconcile original identity") } return out, err } func (c *Client) GetWorkflowSignal(ctx context.Context, id, signal string) (WorkflowSignalStatus, error) { var out WorkflowSignalStatus if !validID(id) || !validID(signal) { return out, errors.New("invalid workflow signal identity") } err := c.call(ctx, "GET", "/v1/workflows/"+id+"/signals/"+signal, "", nil, &out) if err == nil && (out.ID != signal || out.WorkflowID != id) { return WorkflowSignalStatus{}, errors.New("workflow signal identity mismatch") } return out, err } func (c *Client) workflowRecovery(ctx context.Context, id, key, operation string, in any) (WorkflowRecoveryResult, error) { var out WorkflowRecoveryResult if !validID(id) { return out, errors.New("invalid workflow id") } err := c.call(ctx, "POST", "/v1/workflows/"+id+"/recovery/"+operation, key, in, &out) if err == nil && (out.Instance.ID != id || !validID(out.AuditID)) { return WorkflowRecoveryResult{}, errors.New("invalid workflow recovery receipt; reconcile original identity") } return out, err } // ReviewWorkflowTask 仅核查执行事实;结果须经内部消费,再决定步骤结论或等待接续。 func (c *Client) ReviewWorkflowTask(ctx context.Context, id, key string, in ReviewWorkflowTaskRequest) (WorkflowRecoveryResult, error) { return c.workflowRecovery(ctx, id, key, "task-review", in) } func (c *Client) ResolveWorkflowStep(ctx context.Context, id, key string, in ResolveWorkflowStepRequest) (WorkflowRecoveryResult, error) { return c.workflowRecovery(ctx, id, key, "step-resolve", in) } // ContinueWorkflow 解除核查;保留原paused及停止意图。 func (c *Client) ContinueWorkflow(ctx context.Context, id, key string, in ContinueWorkflowRequest) (WorkflowRecoveryResult, error) { return c.workflowRecovery(ctx, id, key, "continue", in) } func (c *Client) RetryWorkflowStep(ctx context.Context, id, key string, in RetryWorkflowStepRequest) (WorkflowRecoveryResult, error) { return c.workflowRecovery(ctx, id, key, "step-retry", in) } func (c *Client) ContinueWorkflowPoll(ctx context.Context, id, key string, in ContinueWorkflowPollRequest) (WorkflowRecoveryResult, error) { return c.workflowRecovery(ctx, id, key, "poll-continue", in) } func (c *Client) RearmWorkflowWait(ctx context.Context, id, key string, in RearmWorkflowWaitRequest) (WorkflowRecoveryResult, error) { return c.workflowRecovery(ctx, id, key, "wait-rearm", in) } func (c *Client) ListWorkflowOperations(ctx context.Context, id string, in HistoryPageRequest) (WorkflowOperationPage, error) { var out WorkflowOperationPage if !validID(id) { return out, errors.New("invalid workflow id") } q, err := historyPageQuery(in) if err != nil { return out, err } err = c.call(ctx, "GET", "/v1/workflows/"+id+"/operations"+q, "", nil, &out) return out, err } func (c *Client) GetWorkflowOperation(ctx context.Context, id, operation string) (WorkflowOperation, error) { var out WorkflowOperation if !validID(id) || !validID(operation) { return out, errors.New("invalid workflow operation identity") } err := c.call(ctx, "GET", "/v1/workflows/"+id+"/operations/"+operation, "", nil, &out) return out, err }