Files
orbit/sdk/go/task_delay_integration_test.go

67 lines
2.9 KiB
Go

package orbit
import (
"context"
"encoding/json"
"testing"
"time"
)
func TestIntegrationWorkerRuntimeDelayedSubmission(t *testing.T) {
api, queue, _ := integrationWorkerClient(t)
ctx, stop := context.WithTimeout(context.Background(), 20*time.Second)
defer stop()
name := "delay." + workerTestID(t)
key := workerTestID(t)
in := SubmitTaskRequest{QueueID: queue, Handler: name, HandlerVersion: "v1", PayloadVersion: "v1", Payload: json.RawMessage(`{"n":9007199254740993}`), DelayMS: 1500, TaskTimeoutMS: 15000, Retry: RetryPolicy{MaxAttempts: 1, AttemptTimeoutMS: 5000}}
delayed, err := api.SubmitTask(ctx, key, in)
if err != nil || !delayed.Task.AvailableAt.Equal(delayed.Task.CreatedAt.Add(1500*time.Millisecond)) {
t.Fatal("relative delay not persisted", err)
}
at := delayed.Task.CreatedAt.Add(3 * time.Second)
absoluteInput := in
absoluteInput.DelayMS, absoluteInput.AvailableAt = 0, &at
absolute, err := api.SubmitTask(ctx, workerTestID(t), absoluteInput)
if err != nil || !absolute.Task.AvailableAt.Equal(at) {
t.Fatal("absolute release time changed", err)
}
r, err := NewWorkerRegistration(queue, 1, []WorkerCapability{{Handler: name, HandlerVersion: "v1", PayloadVersion: "v1"}})
if err != nil {
t.Fatal(err)
}
w, err := api.DialWorker(ctx, r)
if err != nil {
t.Fatal(err)
}
defer w.Close()
if _, err := w.Capacity(ctx, workerTestID(t), WorkerCapacity{Sequence: 1, Capacity: 1}); err != nil {
t.Fatal(err)
}
for _, want := range []Task{delayed.Task, absolute.Task} {
a, err := w.NextAssignment(ctx)
if err != nil || a.Task.ID != want.ID || a.ServerTime.Before(want.AvailableAt) || a.Epoch != 1 {
t.Fatal("task dispatched before its persisted release time", err)
}
if _, err := w.Start(ctx, workerTestID(t), a.Attempt()); err != nil {
t.Fatal(err)
}
if _, err := w.Finish(ctx, workerTestID(t), WorkerFinish{Ref: a.Attempt(), Outcome: WorkerSucceeded, Result: a.Task.Payload}); err != nil {
t.Fatal(err)
}
history, err := api.GetTaskAttempt(ctx, want.ID, a.AttemptID)
if err != nil || history.CreatedAt.Before(want.AvailableAt) || history.AuthorizedAt == nil || history.AuthorizedAt.Before(want.AvailableAt) {
t.Fatal("persisted history allowed an early start", err)
}
}
// 原等待时长已经经过,原键重报仍返回首次回执,不能建立新的计时或任务。
dupe, err := api.SubmitTask(ctx, key, in)
if err != nil || !dupe.Deduplicated || dupe.Task.ID != delayed.Task.ID || !dupe.Task.AvailableAt.Equal(delayed.Task.AvailableAt) || !dupe.Task.DeadlineAt.Equal(delayed.Task.DeadlineAt) {
t.Fatal("late replay reset original delay", err)
}
current, err := api.GetTask(ctx, delayed.Task.ID)
if err != nil || current.State != TaskSucceeded || current.AttemptCount != 1 {
t.Fatal("late replay reopened a completed task", err)
}
t.Log("relative and absolute release times obey database history; replay after elapsed delay returns original receipt without reopening")
}