81 lines
3.0 KiB
Go
81 lines
3.0 KiB
Go
package orbit
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestIntegrationWorkflowEventsSDK(t *testing.T) {
|
|
api, queue, _ := integrationWorkerClient(t)
|
|
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
|
defer cancel()
|
|
operation := workerTestID(t)
|
|
spec := workflowSDKSpec(queue, "events."+operation)
|
|
spec.Body = WorkflowBlock{Steps: []WorkflowStep{
|
|
{Key: "receipt", Kind: "SIGNAL", Signal: &WorkflowSignal{Name: "done", PayloadVersion: "v1", Correlation: WorkflowValue{Kind: "LITERAL", Literal: json.RawMessage(`"` + operation + `"`)}, PayloadType: spec.InputType, TimeoutMS: 60000}},
|
|
{Key: "delay", Kind: "TIMER", Timer: &WorkflowTimer{DelayMS: 60000}},
|
|
}, OutputType: WorkflowType{Kind: "NULL"}, Output: WorkflowRef("delay")}
|
|
v := startWorkflowSDK(t, ctx, api, spec)
|
|
sent, err := api.SendWorkflowSignal(ctx, v.ID, operation, SendWorkflowSignalRequest{Name: "done", PayloadVersion: "v1", TargetStepKey: "receipt", TargetActivationSequence: 1, CorrelationKey: operation, Payload: workflowExact, Reason: "verify timeline"})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
waitWorkflowStepSDK(t, ctx, api, v.ID, "receipt", func(d WorkflowStepDetail) bool { return d.Step.State == "SUCCEEDED" })
|
|
current, err := api.GetWorkflow(ctx, v.ID)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err = api.ControlWorkflow(ctx, v.ID, operation, WorkflowControlRequest{Operation: "CANCEL", ExpectedControlRevision: current.ControlRevision, Reason: "timeline cleanup"}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
waitWorkflowSDK(t, ctx, api, v.ID, "CANCELLED")
|
|
seen := map[string]bool{}
|
|
types := map[string]bool{}
|
|
cursor := ""
|
|
pages := 0
|
|
for {
|
|
page, err := api.ListWorkflowEvents(ctx, v.ID, HistoryPageRequest{Limit: 2, Cursor: cursor})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
pages++
|
|
raw, _ := json.Marshal(page)
|
|
if strings.Contains(string(raw), `"payload"`) || strings.Contains(string(raw), `9007199254740993`) {
|
|
t.Fatal("payload in summaries")
|
|
}
|
|
for _, e := range page.Items {
|
|
if seen[e.ID] || e.WorkflowID != v.ID || e.StepKey == "$root" {
|
|
t.Fatal("event identity", e)
|
|
}
|
|
seen[e.ID] = true
|
|
types[e.Type] = true
|
|
detail, err := api.GetWorkflowEvent(ctx, v.ID, e.ID)
|
|
if err != nil || detail.WorkflowEventSummary != e {
|
|
t.Fatal("detail", detail, err)
|
|
}
|
|
if e.AggregateKind == "workflow_signal" && (e.AggregateID != sent.Signal.ID || e.State != "CONSUMED" || e.StateScope != "SIGNAL") {
|
|
t.Fatal("signal transition", e)
|
|
}
|
|
}
|
|
if page.NextCursor == "" {
|
|
break
|
|
}
|
|
cursor = page.NextCursor
|
|
if pages > 20 {
|
|
t.Fatal("unbounded page repetition")
|
|
}
|
|
}
|
|
for _, kind := range []string{"workflow.started", "workflow.step.changed", "workflow.signal.accepted", "workflow.signal.changed", "workflow.controlled", "workflow.stopped"} {
|
|
if !types[kind] {
|
|
t.Fatal("event missing", kind, types)
|
|
}
|
|
}
|
|
if len(seen) < 7 || pages < 4 {
|
|
t.Fatal("incomplete timeline", len(seen), pages)
|
|
}
|
|
t.Logf("real HTTP event timeline: %d immutable events over %d pages; signal transition and cancelled workflow retained", len(seen), pages)
|
|
}
|