feat: serialize keyed tasks across queues with durable fencing tokens

This commit is contained in:
2026-09-17 18:25:00 +08:00
parent 993786476e
commit 958b4a8cea
43 changed files with 1319 additions and 82 deletions

View File

@@ -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},