feat: serialize keyed tasks across queues with durable fencing tokens
This commit is contained in:
@@ -99,6 +99,8 @@ func TestWorkerPublishedContract(t *testing.T) {
|
||||
hello := worker.ConnectInput{InstanceID: id, InstanceSecret: secret, QueueID: id, Capacity: 1, Capabilities: []worker.Capability{{Handler: "text.normalize", HandlerVersion: "v1", PayloadVersion: "v1"}}}
|
||||
helloWithCancellation := hello
|
||||
helloWithCancellation.CancellationNotifications = true
|
||||
helloWithKeys := hello
|
||||
helloWithKeys.ConcurrencyKeys = true
|
||||
cases := []struct {
|
||||
kind string
|
||||
body any
|
||||
@@ -112,6 +114,7 @@ func TestWorkerPublishedContract(t *testing.T) {
|
||||
{"task.finish", worker.FinishInput{Ref: ref, Outcome: "FAILED", Retryable: true, ErrorCode: "TEMPORARY_REJECTION", Result: json.RawMessage(`{}`)}},
|
||||
{"task.finish", worker.FinishInput{Ref: ref, Outcome: "CANCELLED", ErrorCode: "CANCEL_CONFIRMED", Result: json.RawMessage(`{}`)}},
|
||||
{"worker.hello", helloWithCancellation},
|
||||
{"worker.hello", helloWithKeys},
|
||||
}
|
||||
var valid [][]byte
|
||||
for _, tc := range cases {
|
||||
@@ -189,6 +192,9 @@ func TestWorkerPublishedContract(t *testing.T) {
|
||||
receipt := worker.Receipt{Operation: "start", TaskState: pulse.TaskRunning, AttemptState: pulse.AttemptRunning, TaskRevision: 3, LeaseUntil: lease.LeaseUntil, Disposition: "APPLIED"}
|
||||
task := service.TaskView{ID: id, NamespaceID: id, QueueID: id, State: pulse.TaskLeased, Revision: 2, Handler: "text.normalize", HandlerVersion: "v1", PayloadVersion: "v1", Payload: json.RawMessage(`{}`), AvailableAt: now, DeadlineAt: now.Add(time.Hour), RecoverySafety: pulse.RecoveryReconcileOnly, Retry: pulse.RetryPolicy{MaxAttempts: 1, AttemptTimeoutMS: 30000}, AttemptCount: 1, CreatedAt: now, UpdatedAt: now}
|
||||
assignment := worker.Assignment{Task: task, AttemptID: id, Epoch: 1, LeaseSecret: secret, LeaseUntil: lease.LeaseUntil, ServerTime: now}
|
||||
keyed := assignment
|
||||
keyed.Task.ConcurrencyKey = "object/共享资源"
|
||||
keyed.ConcurrencyToken = ^uint64(0) - 1
|
||||
for _, tc := range []struct {
|
||||
kind string
|
||||
body any
|
||||
@@ -196,6 +202,7 @@ func TestWorkerPublishedContract(t *testing.T) {
|
||||
{"worker.welcome", welcome}, {"ack", welcome}, {"ack", lease},
|
||||
{"ack", worker.CommandResult{Receipt: receipt, Lease: lease, Deduplicated: true}}, {"task.assign", assignment},
|
||||
{"task.cancel", worker.Cancellation{TaskID: id, AttemptID: id, Epoch: 1, RequestedAt: now}},
|
||||
{"task.assign", keyed},
|
||||
} {
|
||||
raw, _ := jsonwire.Marshal(tc.body)
|
||||
f := workerFrame{Version: "1", Type: tc.kind, MessageID: id, SessionID: id, ReplyTo: id, Body: raw}
|
||||
@@ -205,6 +212,19 @@ func TestWorkerPublishedContract(t *testing.T) {
|
||||
frame, _ := jsonwire.Marshal(f)
|
||||
testcontract.WorkerFrame(t, "server", frame)
|
||||
}
|
||||
keyedBody, _ := jsonwire.Marshal(keyed)
|
||||
keyedFrame, _ := jsonwire.Marshal(workerFrame{Version: "1", Type: "task.assign", MessageID: id, SessionID: id, Body: keyedBody})
|
||||
for _, raw := range []string{
|
||||
strings.Replace(string(keyedFrame), `"concurrency_token":"18446744073709551614",`, "", 1),
|
||||
strings.Replace(string(keyedFrame), `"concurrency_key":"object/共享资源",`, "", 1),
|
||||
strings.Replace(string(keyedFrame), `"concurrency_token":"18446744073709551614"`, `"concurrency_token":0`, 1),
|
||||
strings.Replace(string(keyedFrame), `"concurrency_token":"18446744073709551614"`, `"concurrency_token":"0"`, 1),
|
||||
} {
|
||||
value, err := jsonschema.UnmarshalJSON(strings.NewReader(raw))
|
||||
if err != nil || testcontract.WorkerSchema(t, "server").Validate(value) == nil {
|
||||
t.Fatal("invalid concurrency key/token contract accepted")
|
||||
}
|
||||
}
|
||||
for _, f := range []workerFrame{
|
||||
{Version: "1", Type: "error", MessageID: id, ReplyTo: id, Error: fault.Unauthorized},
|
||||
{Version: "1", Type: "error", MessageID: id, SessionID: id, Error: worker.StaleSession},
|
||||
|
||||
Reference in New Issue
Block a user