Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
refactor(workqueue): share assignment receipt projections
Centralize payload-free identity projections in workqueue and retain CLI receipt aliases and captured lifecycle enrichment.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
  • Loading branch information
pelikhan and Copilot committed Oct 11, 2026
commit cf911909f77ea5ce166217ae69273d5c7f4201ec
32 changes: 7 additions & 25 deletions pkg/cli/logs_work_queue_current.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,9 @@ type WorkQueueCurrentSnapshot struct {
Assignment *WorkQueueAssignmentReceipt `json:"assignment,omitempty"`
}

type WorkQueueAssignmentReceipt struct {
DispatchID string `json:"dispatch_id"`
RequestID string `json:"request_id"`
CommitID string `json:"commit_id"`
State string `json:"state"`
Released bool `json:"released"`
Claims []WorkQueueClaimReceipt `json:"claims"`
}
type WorkQueueAssignmentReceipt = workqueue.AssignmentReceipt

type WorkQueueClaimReceipt struct {
Handle string `json:"claim_handle"`
ClaimID string `json:"claim_id"`
WorkID string `json:"work_id"`
State string `json:"state"`
Barrier string `json:"delivery_barrier"`
}
type WorkQueueClaimReceipt = workqueue.ClaimReceipt

type WorkQueueFinishReceipt struct {
IntentID string `json:"intent_id"`
Expand Down Expand Up @@ -230,18 +217,13 @@ func currentWorkQueueAssignmentReceipt(state workqueue.Projection, assignment wo
dispatch.Run.Principal != origin.Principal {
return nil, errors.New("current snapshot origin differs from durable assignment binding")
}
receipt := &WorkQueueAssignmentReceipt{
DispatchID: dispatch.DispatchID, RequestID: dispatch.RequestID, CommitID: dispatch.CommitID,
State: dispatch.State, Released: dispatch.Released,
}
for _, member := range dispatch.Claims {
receipt := dispatch.ToReceipt()
Comment thread
pelikhan marked this conversation as resolved.
Resolved
receipt.State, receipt.Released = dispatch.State, dispatch.Released
for i, member := range receipt.Claims {
Comment thread
pelikhan marked this conversation as resolved.
Resolved
claim, work := state.Claims[member.ClaimID], state.Works[member.WorkID]
receipt.Claims = append(receipt.Claims, WorkQueueClaimReceipt{
Handle: member.Handle, ClaimID: member.ClaimID, WorkID: member.WorkID,
State: claim.State, Barrier: work.Barrier,
})
receipt.Claims[i].State, receipt.Claims[i].Barrier = claim.State, work.Barrier
}
return receipt, nil
return &receipt, nil
}

func readCurrentWorkQueueFinishIntents(path string, snapshot *WorkQueueCurrentSnapshot) ([]WorkQueueFinishReceipt, error) {
Expand Down
26 changes: 26 additions & 0 deletions pkg/cli/logs_work_queue_current_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,32 @@ func TestWorkQueueCurrentReport(t *testing.T) {
assert.NotContains(t, string(serialized), "principal")
}

func TestWorkQueueAssignmentReceiptSchema(t *testing.T) {
t.Parallel()
fixture := currentWorkQueueFixture(t)
commits, err := workqueue.Parse([]byte(fixture["transactionLog"].(string)))
require.NoError(t, err)
state, err := workqueue.Replay(commits)
require.NoError(t, err)
assignment := fixture["worker"].(workqueue.Assignment)
dispatch := state.Dispatches[assignment.DispatchID]
dispatch.State, dispatch.Released = "completed", true
first, second := assignment.Claims[0], assignment.Claims[1]
state.Works[first.WorkID].Barrier = "verified"
receipt, err := currentWorkQueueAssignmentReceipt(state, assignment, fixture["origin"].(workqueue.Actor))
require.NoError(t, err)
data, err := json.Marshal(receipt)
require.NoError(t, err)
assert.JSONEq(t, fmt.Sprintf(`{
"dispatch_id":%q,"request_id":%q,"commit_id":%q,"state":"completed","released":true,
"claims":[
{"claim_handle":%q,"claim_id":%q,"work_id":%q,"state":"completed","delivery_barrier":"verified"},
{"claim_handle":%q,"claim_id":%q,"work_id":%q,"state":"cancelled","delivery_barrier":"none"}
]
}`, assignment.DispatchID, assignment.RequestID, assignment.CommitID,
first.Handle, first.ClaimID, first.WorkID, second.Handle, second.ClaimID, second.WorkID), string(data))
}

func TestWorkQueueCurrentSnapshotRejectsMalformed(t *testing.T) {
t.Parallel()
for _, scenario := range []string{"fork", "truncated", "duplicate-key", "wrong-worker", "foreign-origin", "rerun", "unknown-origin-field", "missing-policy"} {
Expand Down
47 changes: 47 additions & 0 deletions pkg/workqueue/receipts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package workqueue

// AssignmentReceipt describes assignment identity and captured lifecycle facts
// without carrying work payloads, result descriptors, or actor credentials.
type AssignmentReceipt struct {
DispatchID string `json:"dispatch_id"`
RequestID string `json:"request_id"`
CommitID string `json:"commit_id"`
State string `json:"state"`
Released bool `json:"released"`
Claims []ClaimReceipt `json:"claims"`
}

type ClaimReceipt struct {
Handle string `json:"claim_handle"`
ClaimID string `json:"claim_id"`
WorkID string `json:"work_id"`
State string `json:"state"`
Barrier string `json:"delivery_barrier"`
}

// ToReceipt projects immutable identity only. Callers must validate the
// assignment and populate lifecycle facts from their captured projection.
func (assignment Assignment) ToReceipt() AssignmentReceipt {
receipt := AssignmentReceipt{
DispatchID: assignment.DispatchID,
RequestID: assignment.RequestID,
CommitID: assignment.CommitID,
}
if assignment.Claims != nil {
receipt.Claims = make([]ClaimReceipt, 0, len(assignment.Claims))
for _, claim := range assignment.Claims {
receipt.Claims = append(receipt.Claims, claim.ToReceipt())
}
}
return receipt
}

// ToReceipt omits work payloads and result references; lifecycle fields are
// populated separately from the captured projection.
func (claim AssignmentClaim) ToReceipt() ClaimReceipt {
return ClaimReceipt{
Handle: claim.Handle,
ClaimID: claim.ClaimID,
WorkID: claim.WorkID,
}
}
76 changes: 76 additions & 0 deletions pkg/workqueue/receipts_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package workqueue

import (
"encoding/json"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestAssignmentToReceipt(t *testing.T) {
t.Parallel()
assignment := Assignment{
Version: 3, DispatchID: "dispatch", RequestID: "request", CommitID: "commit",
PolicyEpoch: "epoch", Pool: "pool", WorkerProfile: "profile",
Claims: []AssignmentClaim{
{Handle: "h2", ClaimID: "c2", WorkID: "w2", Work: json.RawMessage(`{"private":"payload"}`),
ResultRefs: []ResultReference{{WorkID: "parent", ResultCommitID: "result",
Descriptor: json.RawMessage(`{"private":"descriptor"}`)}}},
{Handle: "h1", ClaimID: "c1", WorkID: "w1"},
},
}
receipt := assignment.ToReceipt()
assert.Equal(t, AssignmentReceipt{
DispatchID: "dispatch", RequestID: "request", CommitID: "commit",
Claims: []ClaimReceipt{
{Handle: "h2", ClaimID: "c2", WorkID: "w2"},
{Handle: "h1", ClaimID: "c1", WorkID: "w1"},
},
}, receipt)
data, err := json.Marshal(receipt)
require.NoError(t, err)
assert.JSONEq(t, `{
"dispatch_id":"dispatch","request_id":"request","commit_id":"commit","state":"","released":false,
"claims":[
{"claim_handle":"h2","claim_id":"c2","work_id":"w2","state":"","delivery_barrier":""},
{"claim_handle":"h1","claim_id":"c1","work_id":"w1","state":"","delivery_barrier":""}
]
}`, string(data))
receipt.Claims[0].Handle = "changed"
assert.Equal(t, "h2", assignment.Claims[0].Handle, "receipts must not alias assignment claims")
}

func TestAssignmentToReceiptPreservesClaimsShape(t *testing.T) {
t.Parallel()
for _, test := range []struct {
name string
claims []AssignmentClaim
want string
}{
{name: "nil", want: "null"},
{name: "empty", claims: []AssignmentClaim{}, want: "[]"},
} {
t.Run(test.name, func(t *testing.T) {
receipt := (Assignment{Claims: test.claims}).ToReceipt()
data, err := json.Marshal(receipt)
require.NoError(t, err)
assert.JSONEq(t, `{"dispatch_id":"","request_id":"","commit_id":"","state":"","released":false,"claims":`+test.want+`}`, string(data))
})
}
}

func TestAssignmentClaimToReceipt(t *testing.T) {
t.Parallel()
claim := AssignmentClaim{
Handle: "handle", ClaimID: "claim", WorkID: "work",
Work: json.RawMessage(`{"private":"payload"}`),
ResultRefs: []ResultReference{{Descriptor: json.RawMessage(`{"private":"descriptor"}`)}},
}
receipt := claim.ToReceipt()
assert.Equal(t, ClaimReceipt{Handle: "handle", ClaimID: "claim", WorkID: "work"}, receipt)
data, err := json.Marshal(receipt)
require.NoError(t, err)
assert.JSONEq(t, `{"claim_handle":"handle","claim_id":"claim","work_id":"work","state":"","delivery_barrier":""}`, string(data))
assert.Equal(t, ClaimReceipt{}, (AssignmentClaim{}).ToReceipt())
}
Loading