feat(db): m1 — message_queue claim lease + presence.role columns
Schema groundwork for v2 agentic-comms milestone 1.
mesh.message_queue gets three nullable columns (claimed_at, claim_id,
claim_expires_at) so drainForMember can move from "claim-and-deliver in
one UPDATE" to a two-phase claim/lease + recipient-ack model. This is
the at-least-once retry hook the broker has been missing.
mesh.presence gets a typed `role` column ('control-plane' | 'session'
| 'service') with default 'session' so legacy hellos keep working. The
CLI's hidden-daemon hack (peerType === 'claudemesh-daemon') will swap
to a role-based filter in a follow-up worktree.
Migration is hand-authored as 0029_*.sql to match the existing pattern
(drizzle-kit's _journal.json drifted long ago — the runtime migrator
in apps/broker/src/migrate.ts tracks files lexicographically via
mesh.__cmh_migrations, not the journal).
This commit is contained in:
@@ -326,6 +326,14 @@ export const presence = meshSchema.table("presence", {
|
||||
statusUpdatedAt: timestamp().defaultNow().notNull(),
|
||||
summary: text(),
|
||||
groups: jsonb().$type<{ name: string; role?: string }[]>().default([]),
|
||||
// v2 agentic-comms (M1): connection role for routing/visibility.
|
||||
// 'control-plane' — long-lived daemon WS (claudemesh daemon),
|
||||
// used for fan-out and presence orchestration.
|
||||
// Hidden from user-facing peer lists.
|
||||
// 'session' — per-Claude-Code session WS (default).
|
||||
// 'service' — autonomous bots/services attached to the mesh.
|
||||
// Always populated; default 'session' keeps legacy hellos working.
|
||||
role: text().notNull().default("session"),
|
||||
connectedAt: timestamp().defaultNow().notNull(),
|
||||
lastPingAt: timestamp().defaultNow().notNull(),
|
||||
disconnectedAt: timestamp(),
|
||||
@@ -367,6 +375,14 @@ export const messageQueue = meshSchema.table("message_queue", {
|
||||
// §4.4), hex-encoded. Nullable for legacy traffic. Brokers that want
|
||||
// to enforce idempotency on retries will read this column.
|
||||
requestFingerprint: text("request_fingerprint"),
|
||||
// v2 agentic-comms (M1): two-phase claim/deliver with lease.
|
||||
// `drainForMember` claims a row by setting (claimedAt, claimId,
|
||||
// claimExpiresAt) — NOT deliveredAt. The recipient's WS only marks
|
||||
// deliveredAt after replying with a `client_ack`. A periodic sweeper
|
||||
// reaps expired claims so dropped pushes are redelivered (at-least-once).
|
||||
claimedAt: timestamp(),
|
||||
claimId: text("claim_id"),
|
||||
claimExpiresAt: timestamp(),
|
||||
});
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user