/* * What a live feed takes its task lease under — pure naming, one place. * * ── Why the name is built here and not by the adapter ────────────────────── * `TaskLease` deliberately has no domain column: the thing made exclusive is a * loop, not a tenant's slice of one, and a task that does need to be per-tenant * puts the tenant in its name so the unique index keeps meaning what it says. * * An adapter cannot honour that. It receives `cfg` and `site`, and neither * carries a domain — so a name built from `siteId` would let two domains that * happen to share a plant code block each other's channel. It would look * exactly like "someone else holds it", which is the ordinary case on every * instance but one, so nothing would be logged and nothing would look wrong. * * ── Why the source and not the site ─────────────────────────────────────── * One reference is one connection to one system, and that connection is what a * second instance must not open twice. A source that discovers several sites * still reads them over that one connection. * * ── Why the parts are joined with `::` ──────────────────────────────────── * The same separator the push cursor key already uses (`instanceId::scope`), so * a person reading `task_leases` during an incident sees the same shape they * see in `liveCursor`. */ /** Marks the name as a live feed, so a lease table read tells you what kind of task it is. */ const PREFIX = 'twin-live' /** * The lease name for one twin's feed. * * ── Domain and instance are required; the source is not ─────────────────── * A feed is registered per instance, so domain plus instance already names it * uniquely. The source is appended when known because it is what a person * reading `task_leases` wants to see — which system this channel talks to. * * Missing a domain or an instance is refused rather than filled in. A blank * there would collapse two different feeds onto one name, and the failure * would be that one of them silently stops: it would look exactly like * "someone else holds it", which is the ordinary case on every instance but * one, so nothing would be logged. */ export function liveFeedLeaseName(domainId: string, instanceId: string, source?: string): string { for (const [what, value] of [ ['domainId', domainId], ['instanceId', instanceId] ] as const) { if (!value || !String(value).trim()) { throw new Error(`cannot name a live feed lease without ${what} — two feeds would share one name`) } } const named = source && String(source).trim() return named ? `${PREFIX}::${domainId}::${instanceId}::${named}` : `${PREFIX}::${domainId}::${instanceId}` }