67 lines
2.9 KiB
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")
|
|
}
|