diff --git a/contracts/go/seats/meshwants/contract.go b/contracts/go/seats/meshwants/contract.go index c4faef83..7e958b08 100644 --- a/contracts/go/seats/meshwants/contract.go +++ b/contracts/go/seats/meshwants/contract.go @@ -67,8 +67,16 @@ const SubjectAssignmentRevision = "mesh.seat.mesh-wants.event.assignment-revisio // SubjectDifference is where difference is published. const SubjectDifference = "mesh.seat.mesh-wants.event.difference" -// SubjectWanted is where wanted is published. -const SubjectWanted = "mesh.seat.mesh-wants.event.wanted" +// StreamWanted is the stream wanted is kept in. +const StreamWanted = "SEAT_mesh-wants_wanted" + +// SubjectWanted is where wanted is published, on mesh.seat.mesh-wants.event.wanted... +func SubjectWanted(node, module string) string { + return "mesh.seat.mesh-wants.event.wanted." + node + "." + module +} + +// SubjectWantedAll hears every wanted. +const SubjectWantedAll = "mesh.seat.mesh-wants.event.wanted.*.*" // SubjectWaitHeld is where wait-held is published. const SubjectWaitHeld = "mesh.seat.mesh-wants.event.wait-held" diff --git a/contracts/go/seats/meshwants/contract_test.go b/contracts/go/seats/meshwants/contract_test.go index 29449e7f..b21c64c9 100644 --- a/contracts/go/seats/meshwants/contract_test.go +++ b/contracts/go/seats/meshwants/contract_test.go @@ -25,10 +25,10 @@ func TestFixtures(t *testing.T) { }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-wants\\.event\\.assignment-revision$")}, {name: "a difference worked out", subject: "mesh.seat.mesh-wants.event.difference", given: "{\"changes\":1,\"from\":40,\"nodes\":[\"n1\"],\"source\":3589,\"to\":41,\"v\":1}", wire: "{\"changes\":1,\"from\":40,\"nodes\":[\"n1\"],\"source\":3589,\"to\":41,\"v\":1}", decode: func(b []byte) (any, error) { var v DifferenceEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-wants\\.event\\.difference$")}, - {name: "an entry wanted from a trunk revision", subject: "mesh.seat.mesh-wants.event.wanted", given: "{\"at\":\"2026-11-09T19:00:00Z\",\"fp\":\"src2:b427bdde1f100e2f52490cfa9df0c5112dd3700226b4892349f0c14a15a4af56\",\"module\":\"xclip\",\"node\":\"n1\",\"revision\":40,\"source\":3589,\"v\":1}", wire: "{\"at\":\"2026-11-09T19:00:00Z\",\"fp\":\"src2:b427bdde1f100e2f52490cfa9df0c5112dd3700226b4892349f0c14a15a4af56\",\"module\":\"xclip\",\"node\":\"n1\",\"revision\":40,\"source\":3589,\"v\":1}", - decode: func(b []byte) (any, error) { var v WantedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-wants\\.event\\.wanted$")}, - {name: "a want removed, its node left or its module unplaced", subject: "mesh.seat.mesh-wants.event.wanted", given: "{\"at\":\"2026-11-09T19:05:00Z\",\"fp\":\"src2:b427bdde1f100e2f52490cfa9df0c5112dd3700226b4892349f0c14a15a4af56\",\"module\":\"xclip\",\"node\":\"n1\",\"removed\":true,\"revision\":41,\"v\":1}", wire: "{\"at\":\"2026-11-09T19:05:00Z\",\"fp\":\"src2:b427bdde1f100e2f52490cfa9df0c5112dd3700226b4892349f0c14a15a4af56\",\"module\":\"xclip\",\"node\":\"n1\",\"removed\":true,\"revision\":41,\"v\":1}", - decode: func(b []byte) (any, error) { var v WantedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-wants\\.event\\.wanted$")}, + {name: "an entry wanted from a trunk revision", subject: "mesh.seat.mesh-wants.event.wanted.n1.xclip", given: "{\"at\":\"2026-11-09T19:00:00Z\",\"fp\":\"src2:b427bdde1f100e2f52490cfa9df0c5112dd3700226b4892349f0c14a15a4af56\",\"module\":\"xclip\",\"node\":\"n1\",\"revision\":40,\"source\":3589,\"v\":1}", wire: "{\"at\":\"2026-11-09T19:00:00Z\",\"fp\":\"src2:b427bdde1f100e2f52490cfa9df0c5112dd3700226b4892349f0c14a15a4af56\",\"module\":\"xclip\",\"node\":\"n1\",\"revision\":40,\"source\":3589,\"v\":1}", + decode: func(b []byte) (any, error) { var v WantedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-wants\\.event\\.wanted\\.[^.*> ]+\\.[^.*> ]+$")}, + {name: "a want removed, its node left or its module unplaced", subject: "mesh.seat.mesh-wants.event.wanted.n1.xclip", given: "{\"at\":\"2026-11-09T19:05:00Z\",\"fp\":\"src2:b427bdde1f100e2f52490cfa9df0c5112dd3700226b4892349f0c14a15a4af56\",\"module\":\"xclip\",\"node\":\"n1\",\"removed\":true,\"revision\":41,\"v\":1}", wire: "{\"at\":\"2026-11-09T19:05:00Z\",\"fp\":\"src2:b427bdde1f100e2f52490cfa9df0c5112dd3700226b4892349f0c14a15a4af56\",\"module\":\"xclip\",\"node\":\"n1\",\"removed\":true,\"revision\":41,\"v\":1}", + decode: func(b []byte) (any, error) { var v WantedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-wants\\.event\\.wanted\\.[^.*> ]+\\.[^.*> ]+$")}, {name: "a composing wait held with its bound", subject: "mesh.seat.mesh-wants.event.wait-held", given: "{\"bound\":\"30m\",\"fp\":\"src2:b427bdde1f100e2f52490cfa9df0c5112dd3700226b4892349f0c14a15a4af56\",\"module\":\"xclip\",\"node\":\"n1\",\"part\":\"node-engine\",\"since\":\"2026-11-09T19:00:00Z\",\"step\":\"compose\",\"version\":\"src2:7dd0db8e98224f46121a5ae05c0b9c5a430eff531a5120aa40b1a59237853a3f\"}", wire: "{\"bound\":\"30m\",\"fp\":\"src2:b427bdde1f100e2f52490cfa9df0c5112dd3700226b4892349f0c14a15a4af56\",\"module\":\"xclip\",\"node\":\"n1\",\"part\":\"node-engine\",\"since\":\"2026-11-09T19:00:00Z\",\"step\":\"compose\",\"version\":\"src2:7dd0db8e98224f46121a5ae05c0b9c5a430eff531a5120aa40b1a59237853a3f\"}", decode: func(b []byte) (any, error) { var v WaitHeldEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-wants\\.event\\.wait-held$")}, {name: "a wait ended, released by hand", subject: "mesh.seat.mesh-wants.event.wait-ended", given: "{\"bound\":\"30m\",\"by\":\"lead@shanks: the node is away\",\"fp\":\"src2:b427bdde1f100e2f52490cfa9df0c5112dd3700226b4892349f0c14a15a4af56\",\"how\":\"released\",\"module\":\"xclip\",\"node\":\"n1\",\"part\":\"node-engine\",\"since\":\"2026-11-09T19:00:00Z\",\"step\":\"compose\",\"version\":\"src2:7dd0db8e98224f46121a5ae05c0b9c5a430eff531a5120aa40b1a59237853a3f\"}", wire: "{\"bound\":\"30m\",\"by\":\"lead@shanks: the node is away\",\"fp\":\"src2:b427bdde1f100e2f52490cfa9df0c5112dd3700226b4892349f0c14a15a4af56\",\"how\":\"released\",\"module\":\"xclip\",\"node\":\"n1\",\"part\":\"node-engine\",\"since\":\"2026-11-09T19:00:00Z\",\"step\":\"compose\",\"version\":\"src2:7dd0db8e98224f46121a5ae05c0b9c5a430eff531a5120aa40b1a59237853a3f\"}", diff --git a/contracts/seats/mesh-wants/fixtures/events.json b/contracts/seats/mesh-wants/fixtures/events.json index 908e63d6..d30e8279 100644 --- a/contracts/seats/mesh-wants/fixtures/events.json +++ b/contracts/seats/mesh-wants/fixtures/events.json @@ -36,7 +36,7 @@ { "name": "an entry wanted from a trunk revision", "of": "event:wanted", - "subject": "mesh.seat.mesh-wants.event.wanted", + "subject": "mesh.seat.mesh-wants.event.wanted.n1.xclip", "given": { "v": 1, "node": "n1", @@ -50,7 +50,7 @@ { "name": "a want removed, its node left or its module unplaced", "of": "event:wanted", - "subject": "mesh.seat.mesh-wants.event.wanted", + "subject": "mesh.seat.mesh-wants.event.wanted.n1.xclip", "given": { "v": 1, "node": "n1", diff --git a/contracts/seats/mesh-wants/seat.json b/contracts/seats/mesh-wants/seat.json index fb0d2654..ca64e17c 100644 --- a/contracts/seats/mesh-wants/seat.json +++ b/contracts/seats/mesh-wants/seat.json @@ -303,6 +303,10 @@ }, { "name": "wanted", + "subject": "wanted..", + "keep": { + "last-per-subject": true + }, "body": { "type": "object", "description": "an entry written as a want, from a trunk revision only", diff --git a/contracts/ts/seats/meshwants/index.d.ts b/contracts/ts/seats/meshwants/index.d.ts index 974bc4d0..134842cd 100644 --- a/contracts/ts/seats/meshwants/index.d.ts +++ b/contracts/ts/seats/meshwants/index.d.ts @@ -40,7 +40,11 @@ export declare const assignmentRevisionSubject: "mesh.seat.mesh-wants.event.assi export declare const differenceSubject: "mesh.seat.mesh-wants.event.difference"; -export declare const wantedSubject: "mesh.seat.mesh-wants.event.wanted"; +export declare const wantedStream: "SEAT_mesh-wants_wanted"; + +export declare function wantedSubject(node: string, module: string): string; + +export declare const wantedSubjectAll: "mesh.seat.mesh-wants.event.wanted.*.*"; export declare const waitHeldSubject: "mesh.seat.mesh-wants.event.wait-held"; diff --git a/contracts/ts/seats/meshwants/index.js b/contracts/ts/seats/meshwants/index.js index df1d0f62..15556f82 100644 --- a/contracts/ts/seats/meshwants/index.js +++ b/contracts/ts/seats/meshwants/index.js @@ -40,7 +40,13 @@ export const assignmentRevisionSubject = "mesh.seat.mesh-wants.event.assignment- export const differenceSubject = "mesh.seat.mesh-wants.event.difference"; -export const wantedSubject = "mesh.seat.mesh-wants.event.wanted"; +export const wantedStream = "SEAT_mesh-wants_wanted"; + +export function wantedSubject(node, module) { + return "mesh.seat.mesh-wants.event.wanted." + node + "." + module; +} + +export const wantedSubjectAll = "mesh.seat.mesh-wants.event.wanted.*.*"; export const waitHeldSubject = "mesh.seat.mesh-wants.event.wait-held";