package outbox import ( "bytes" "context" "encoding/json" "errors" "testing" "time" orbit "git.yuntuo.hk/k2safe/orbit/sdk/go" ) func testID(t *testing.T) string { t.Helper() id, err := orbit.NewEventMessageID() if err != nil { t.Fatal(err) } return id } func testRequest(queue string) orbit.SubmitTaskRequest { return orbit.SubmitTaskRequest{QueueID: queue, Handler: "object.prepare", HandlerVersion: "v1", PayloadVersion: "v1", Payload: json.RawMessage(`{"sequence":9007199254740993,"ref":"objects/test"}`), TaskTimeoutMS: 60000} } func TestFrozenDocumentAndFailureClassification(t *testing.T) { s := &Store{namespace: testID(t), queue: testID(t)} in := testRequest(s.queue) in.TaskTimeoutMS = 0 in.DelayMS = 1500 raw, err := s.document(in) if err != nil { t.Fatal(err) } var frozen orbit.SubmitTaskRequest if json.Unmarshal(raw, &frozen) != nil || frozen.TaskTimeoutMS != 86400000 || frozen.DelayMS != 1500 || frozen.AvailableAt != nil || frozen.Retry.MaxAttempts != 1 || frozen.Retry.AttemptTimeoutMS != 30000 || !bytes.Contains(frozen.Payload, []byte("9007199254740993")) { t.Fatal("frozen defaults or precision changed") } in.QueueID = testID(t) if _, err = s.document(in); !errors.Is(err, ErrInvalid) { t.Fatal("cross queue request frozen") } in = testRequest(s.queue) in.BusinessKey = "operation-\xff" if _, err = s.document(in); !errors.Is(err, ErrInvalid) { t.Fatal("invalid UTF-8 was silently rewritten") } for _, test := range []struct { err error state, code string }{ {context.DeadlineExceeded, "PENDING", "UNCONFIRMED"}, {&orbit.APIError{StatusCode: 503, Code: "UNAVAILABLE"}, "PENDING", "UNCONFIRMED"}, {&orbit.APIError{StatusCode: 429, RetryAfter: 30 * time.Second}, "PENDING", "BACKPRESSURE"}, {&orbit.APIError{StatusCode: 403}, "REVIEW", "AUTHORIZATION"}, {&orbit.APIError{StatusCode: 409, Code: "IDEMPOTENCY_CONFLICT"}, "REVIEW", "IDEMPOTENCY_CONFLICT"}, {&orbit.HTTPError{StatusCode: 302}, "REVIEW", "HTTP_REJECTED"}, {&orbit.HTTPError{StatusCode: 502}, "PENDING", "UNCONFIRMED"}, } { state, code, delay := classify(test.err, 100) if state != test.state || code != test.code || delay < time.Second || delay > time.Hour { t.Fatal(state, code, delay) } } }