@relaycast/engine 3.1.1 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (166) hide show
  1. package/dist/adapters/node/event-queue.d.ts +10 -0
  2. package/dist/adapters/node/event-queue.d.ts.map +1 -1
  3. package/dist/adapters/node/event-queue.js +17 -0
  4. package/dist/adapters/node/event-queue.js.map +1 -1
  5. package/dist/adapters/node/index.d.ts.map +1 -1
  6. package/dist/adapters/node/index.js +10 -0
  7. package/dist/adapters/node/index.js.map +1 -1
  8. package/dist/adapters/node/realtime.d.ts +24 -2
  9. package/dist/adapters/node/realtime.d.ts.map +1 -1
  10. package/dist/adapters/node/realtime.js +178 -1
  11. package/dist/adapters/node/realtime.js.map +1 -1
  12. package/dist/bin/serve.js +18 -1
  13. package/dist/bin/serve.js.map +1 -1
  14. package/dist/db/migrations/0016_fleet_nodes.sql +189 -0
  15. package/dist/db/migrations/0017_spawn_reservation_and_retry_state.sql +5 -0
  16. package/dist/db/migrations/0018_spawn_reserved_at.sql +2 -0
  17. package/dist/db/migrations/0019_fleet_mailbox.sql +71 -0
  18. package/dist/db/migrations/0020_workspace_retention.sql +3 -0
  19. package/dist/db/schema.d.ts +1771 -911
  20. package/dist/db/schema.d.ts.map +1 -1
  21. package/dist/db/schema.js +77 -7
  22. package/dist/db/schema.js.map +1 -1
  23. package/dist/engine/action.d.ts +84 -10
  24. package/dist/engine/action.d.ts.map +1 -1
  25. package/dist/engine/action.js +523 -85
  26. package/dist/engine/action.js.map +1 -1
  27. package/dist/engine/agent.js +2 -2
  28. package/dist/engine/agent.js.map +1 -1
  29. package/dist/engine/delivery.d.ts +41 -6
  30. package/dist/engine/delivery.d.ts.map +1 -1
  31. package/dist/engine/delivery.js +316 -25
  32. package/dist/engine/delivery.js.map +1 -1
  33. package/dist/engine/deliveryWire.d.ts +34 -0
  34. package/dist/engine/deliveryWire.d.ts.map +1 -0
  35. package/dist/engine/deliveryWire.js +70 -0
  36. package/dist/engine/deliveryWire.js.map +1 -0
  37. package/dist/engine/deliveryWrites.d.ts +47 -0
  38. package/dist/engine/deliveryWrites.d.ts.map +1 -1
  39. package/dist/engine/deliveryWrites.js +155 -5
  40. package/dist/engine/deliveryWrites.js.map +1 -1
  41. package/dist/engine/dm.d.ts +4 -4
  42. package/dist/engine/dm.d.ts.map +1 -1
  43. package/dist/engine/dm.js +17 -7
  44. package/dist/engine/dm.js.map +1 -1
  45. package/dist/engine/eventQueue.d.ts.map +1 -1
  46. package/dist/engine/eventQueue.js +5 -0
  47. package/dist/engine/eventQueue.js.map +1 -1
  48. package/dist/engine/eventSubscription.d.ts +6 -0
  49. package/dist/engine/eventSubscription.d.ts.map +1 -1
  50. package/dist/engine/eventSubscription.js +13 -0
  51. package/dist/engine/eventSubscription.js.map +1 -1
  52. package/dist/engine/groupDm.d.ts +4 -0
  53. package/dist/engine/groupDm.d.ts.map +1 -1
  54. package/dist/engine/groupDm.js +16 -4
  55. package/dist/engine/groupDm.js.map +1 -1
  56. package/dist/engine/invocationCompletion.d.ts +13 -0
  57. package/dist/engine/invocationCompletion.d.ts.map +1 -0
  58. package/dist/engine/invocationCompletion.js +65 -0
  59. package/dist/engine/invocationCompletion.js.map +1 -0
  60. package/dist/engine/mailboxConfig.d.ts +9 -0
  61. package/dist/engine/mailboxConfig.d.ts.map +1 -0
  62. package/dist/engine/mailboxConfig.js +16 -0
  63. package/dist/engine/mailboxConfig.js.map +1 -0
  64. package/dist/engine/message.d.ts +4 -0
  65. package/dist/engine/message.d.ts.map +1 -1
  66. package/dist/engine/message.js +16 -4
  67. package/dist/engine/message.js.map +1 -1
  68. package/dist/engine/node.d.ts +201 -0
  69. package/dist/engine/node.d.ts.map +1 -0
  70. package/dist/engine/node.js +533 -0
  71. package/dist/engine/node.js.map +1 -0
  72. package/dist/engine/placement.d.ts +26 -0
  73. package/dist/engine/placement.d.ts.map +1 -0
  74. package/dist/engine/placement.js +242 -0
  75. package/dist/engine/placement.js.map +1 -0
  76. package/dist/engine/receipt.d.ts.map +1 -1
  77. package/dist/engine/receipt.js +5 -6
  78. package/dist/engine/receipt.js.map +1 -1
  79. package/dist/engine/retention.d.ts +65 -0
  80. package/dist/engine/retention.d.ts.map +1 -0
  81. package/dist/engine/retention.js +173 -0
  82. package/dist/engine/retention.js.map +1 -0
  83. package/dist/engine/snowflake.d.ts +11 -0
  84. package/dist/engine/snowflake.d.ts.map +1 -1
  85. package/dist/engine/snowflake.js +14 -0
  86. package/dist/engine/snowflake.js.map +1 -1
  87. package/dist/engine/thread.d.ts +4 -0
  88. package/dist/engine/thread.d.ts.map +1 -1
  89. package/dist/engine/thread.js +16 -4
  90. package/dist/engine/thread.js.map +1 -1
  91. package/dist/engine/trigger.d.ts +79 -0
  92. package/dist/engine/trigger.d.ts.map +1 -0
  93. package/dist/engine/trigger.js +151 -0
  94. package/dist/engine/trigger.js.map +1 -0
  95. package/dist/engine.d.ts.map +1 -1
  96. package/dist/engine.js +61 -2
  97. package/dist/engine.js.map +1 -1
  98. package/dist/entrypoints/node.d.ts.map +1 -1
  99. package/dist/entrypoints/node.js +36 -2
  100. package/dist/entrypoints/node.js.map +1 -1
  101. package/dist/env.d.ts +6 -0
  102. package/dist/env.d.ts.map +1 -1
  103. package/dist/index.d.ts +4 -1
  104. package/dist/index.d.ts.map +1 -1
  105. package/dist/index.js +6 -1
  106. package/dist/index.js.map +1 -1
  107. package/dist/lib/fleetNodes.d.ts +9 -0
  108. package/dist/lib/fleetNodes.d.ts.map +1 -0
  109. package/dist/lib/fleetNodes.js +66 -0
  110. package/dist/lib/fleetNodes.js.map +1 -0
  111. package/dist/lib/origin.d.ts.map +1 -1
  112. package/dist/lib/origin.js +0 -5
  113. package/dist/lib/origin.js.map +1 -1
  114. package/dist/lib/serverTelemetry.d.ts.map +1 -1
  115. package/dist/lib/serverTelemetry.js +0 -1
  116. package/dist/lib/serverTelemetry.js.map +1 -1
  117. package/dist/middleware/fleetNodes.d.ts +10 -0
  118. package/dist/middleware/fleetNodes.d.ts.map +1 -0
  119. package/dist/middleware/fleetNodes.js +18 -0
  120. package/dist/middleware/fleetNodes.js.map +1 -0
  121. package/dist/ports/index.d.ts +24 -2
  122. package/dist/ports/index.d.ts.map +1 -1
  123. package/dist/ports/realtime.d.ts +34 -2
  124. package/dist/ports/realtime.d.ts.map +1 -1
  125. package/dist/ports/realtime.js +1 -1
  126. package/dist/routes/action.d.ts.map +1 -1
  127. package/dist/routes/action.js +21 -21
  128. package/dist/routes/action.js.map +1 -1
  129. package/dist/routes/delivery.d.ts.map +1 -1
  130. package/dist/routes/delivery.js +7 -2
  131. package/dist/routes/delivery.js.map +1 -1
  132. package/dist/routes/deliveryRouting.d.ts +10 -0
  133. package/dist/routes/deliveryRouting.d.ts.map +1 -0
  134. package/dist/routes/deliveryRouting.js +91 -0
  135. package/dist/routes/deliveryRouting.js.map +1 -0
  136. package/dist/routes/dm.d.ts.map +1 -1
  137. package/dist/routes/dm.js +14 -13
  138. package/dist/routes/dm.js.map +1 -1
  139. package/dist/routes/groupDm.d.ts.map +1 -1
  140. package/dist/routes/groupDm.js +14 -15
  141. package/dist/routes/groupDm.js.map +1 -1
  142. package/dist/routes/inbox.d.ts.map +1 -1
  143. package/dist/routes/inbox.js +7 -0
  144. package/dist/routes/inbox.js.map +1 -1
  145. package/dist/routes/message.d.ts.map +1 -1
  146. package/dist/routes/message.js +45 -23
  147. package/dist/routes/message.js.map +1 -1
  148. package/dist/routes/node.d.ts +4 -0
  149. package/dist/routes/node.d.ts.map +1 -0
  150. package/dist/routes/node.js +57 -0
  151. package/dist/routes/node.js.map +1 -0
  152. package/dist/routes/thread.d.ts.map +1 -1
  153. package/dist/routes/thread.js +15 -16
  154. package/dist/routes/thread.js.map +1 -1
  155. package/dist/routes/trigger.d.ts +4 -0
  156. package/dist/routes/trigger.d.ts.map +1 -0
  157. package/dist/routes/trigger.js +83 -0
  158. package/dist/routes/trigger.js.map +1 -0
  159. package/dist/routes/webhookOutbox.d.ts +13 -6
  160. package/dist/routes/webhookOutbox.d.ts.map +1 -1
  161. package/dist/routes/webhookOutbox.js +29 -6
  162. package/dist/routes/webhookOutbox.js.map +1 -1
  163. package/dist/routes/workspace.d.ts.map +1 -1
  164. package/dist/routes/workspace.js +90 -0
  165. package/dist/routes/workspace.js.map +1 -1
  166. package/package.json +3 -3
@@ -0,0 +1,242 @@
1
+ import { and, eq, sql } from 'drizzle-orm';
2
+ import { agents, nodes } from '../db/schema.js';
3
+ import { codedError } from '../lib/httpError.js';
4
+ import { runAtomic } from '../ports/database.js';
5
+ export const NODE_LIVENESS_TTL_MS = 45_000;
6
+ export function isNodeLive(node, now = Date.now()) {
7
+ return (node.status === 'online' &&
8
+ !!node.lastHeartbeatAt &&
9
+ now - node.lastHeartbeatAt.getTime() <= NODE_LIVENESS_TTL_MS);
10
+ }
11
+ export function nodeHasCapability(node, capability) {
12
+ return Array.isArray(node.capabilities)
13
+ && node.capabilities.some((item) => {
14
+ if (typeof item === 'string')
15
+ return item === capability;
16
+ return item?.name === capability;
17
+ });
18
+ }
19
+ export function nodeHasCapacity(node) {
20
+ return node.maxAgents === 0 || node.activeAgents + (node.reservedAgents ?? 0) < node.maxAgents;
21
+ }
22
+ function normalizeTarget(target) {
23
+ return typeof target === 'string' && target.trim().length > 0 ? target.trim() : undefined;
24
+ }
25
+ function normalizeCapability(actionName, input) {
26
+ const raw = input.capability ?? input.cli;
27
+ if (typeof raw === 'string' && raw.trim().length > 0) {
28
+ const value = raw.trim();
29
+ return value.startsWith('spawn:') ? value : actionName === 'spawn' ? `spawn:${value}` : value;
30
+ }
31
+ return actionName;
32
+ }
33
+ export async function reserveNodeCapacity(db, workspaceId, nodeId) {
34
+ const [updated] = await db
35
+ .update(nodes)
36
+ .set({
37
+ reservedAgents: sql `coalesce(${nodes.reservedAgents}, 0) + 1`,
38
+ })
39
+ .where(and(eq(nodes.workspaceId, workspaceId), eq(nodes.id, nodeId), eq(nodes.status, 'online'), eq(nodes.handlersLive, true), sql `(${nodes.maxAgents} = 0 OR (${nodes.activeAgents} + coalesce(${nodes.reservedAgents}, 0)) < ${nodes.maxAgents})`))
40
+ .returning();
41
+ return updated ?? null;
42
+ }
43
+ export async function releaseNodeCapacity(db, workspaceId, nodeId, count = 1) {
44
+ if (count <= 0)
45
+ return;
46
+ await db
47
+ .update(nodes)
48
+ .set({
49
+ reservedAgents: sql `CASE WHEN coalesce(${nodes.reservedAgents}, 0) > ${count} THEN coalesce(${nodes.reservedAgents}, 0) - ${count} ELSE 0 END`,
50
+ })
51
+ .where(and(eq(nodes.workspaceId, workspaceId), eq(nodes.id, nodeId)));
52
+ }
53
+ export async function claimSpawnNode(db, workspaceId, request) {
54
+ const input = request.input ?? {};
55
+ const capability = normalizeCapability('spawn', input);
56
+ const target = normalizeTarget(input.target_node ?? input.node ?? input.target);
57
+ const excluded = new Set(request.excludeNodeIds ?? []);
58
+ return runAtomic(db, async (tx) => {
59
+ const chooseLiveCandidate = async (node) => {
60
+ if (!node)
61
+ return null;
62
+ if (!nodeHasCapability(node, capability) || excluded.has(node.id))
63
+ return null;
64
+ if (!isNodeLive(node) || !node.handlersLive)
65
+ return { node, capability, queued: true };
66
+ const reserved = await reserveNodeCapacity(tx, workspaceId, node.id);
67
+ if (!reserved) {
68
+ throw codedError(`Node "${node.name}" is at capacity`, 'handler_unavailable', 503);
69
+ }
70
+ return { node: reserved, capability, queued: false };
71
+ };
72
+ if (request.preferredNodeId) {
73
+ const [node] = await tx
74
+ .select()
75
+ .from(nodes)
76
+ .where(and(eq(nodes.workspaceId, workspaceId), eq(nodes.id, request.preferredNodeId)));
77
+ const claimed = await chooseLiveCandidate(node ?? undefined);
78
+ if (claimed)
79
+ return claimed;
80
+ if (node && excluded.has(node.id)) {
81
+ throw codedError(`Node "${node.name}" is unavailable for retry`, 'handler_unavailable', 503);
82
+ }
83
+ if (node && nodeHasCapability(node, capability)) {
84
+ return { node, capability, queued: !isNodeLive(node) || !node.handlersLive };
85
+ }
86
+ }
87
+ if (target === 'self') {
88
+ if (!request.callerId) {
89
+ throw codedError('target "self" requires an agent caller', 'placement_self_requires_agent', 400);
90
+ }
91
+ const [caller] = await tx
92
+ .select({
93
+ locationNodeId: agents.locationNodeId,
94
+ locationType: agents.locationType,
95
+ })
96
+ .from(agents)
97
+ .where(and(eq(agents.workspaceId, workspaceId), eq(agents.id, request.callerId)));
98
+ if (!caller || caller.locationType !== 'via_node' || !caller.locationNodeId) {
99
+ throw codedError('caller is not attached to a node', 'placement_self_unavailable', 409);
100
+ }
101
+ const [node] = await tx
102
+ .select()
103
+ .from(nodes)
104
+ .where(and(eq(nodes.workspaceId, workspaceId), eq(nodes.id, caller.locationNodeId)));
105
+ if (!node) {
106
+ throw codedError('caller node was not found', 'node_not_found', 404);
107
+ }
108
+ const claimed = await chooseLiveCandidate(node);
109
+ if (claimed)
110
+ return claimed;
111
+ if (excluded.has(node.id)) {
112
+ throw codedError(`Node "${node.name}" is unavailable for retry`, 'handler_unavailable', 503);
113
+ }
114
+ if (!nodeHasCapability(node, capability)) {
115
+ throw codedError(`Node "${node.name}" does not provide ${capability}`, 'capability_mismatch', 409);
116
+ }
117
+ return { node, capability, queued: !isNodeLive(node) || !node.handlersLive };
118
+ }
119
+ if (target) {
120
+ const [node] = await tx
121
+ .select()
122
+ .from(nodes)
123
+ .where(and(eq(nodes.workspaceId, workspaceId), eq(nodes.name, target)));
124
+ if (!node) {
125
+ throw codedError(`Node "${target}" not found`, 'node_not_found', 404);
126
+ }
127
+ const claimed = await chooseLiveCandidate(node);
128
+ if (claimed)
129
+ return claimed;
130
+ if (excluded.has(node.id)) {
131
+ throw codedError(`Node "${node.name}" is unavailable for retry`, 'handler_unavailable', 503);
132
+ }
133
+ if (!nodeHasCapability(node, capability)) {
134
+ throw codedError(`Node "${target}" does not provide ${capability}`, 'capability_mismatch', 409);
135
+ }
136
+ return { node, capability, queued: !isNodeLive(node) || !node.handlersLive };
137
+ }
138
+ const rows = await tx.select().from(nodes).where(eq(nodes.workspaceId, workspaceId));
139
+ const eligible = rows
140
+ .filter((node) => !excluded.has(node.id) &&
141
+ nodeHasCapability(node, capability) &&
142
+ isNodeLive(node) &&
143
+ node.handlersLive &&
144
+ nodeHasCapacity(node))
145
+ .sort((a, b) => (a.load - b.load) || (a.activeAgents - b.activeAgents) || a.name.localeCompare(b.name));
146
+ for (const node of eligible) {
147
+ const reserved = await reserveNodeCapacity(tx, workspaceId, node.id);
148
+ if (reserved)
149
+ return { node: reserved, capability, queued: false };
150
+ }
151
+ throw codedError(`No live node provides ${capability}`, 'handler_unavailable', 503);
152
+ });
153
+ }
154
+ export async function chooseNodeForAction(db, workspaceId, request) {
155
+ const input = request.input ?? {};
156
+ const capability = normalizeCapability(request.actionName, input);
157
+ const target = normalizeTarget(input.target_node ?? input.node ?? input.target);
158
+ const excluded = new Set(request.excludeNodeIds ?? []);
159
+ if (request.preferredNodeId) {
160
+ const [node] = await db
161
+ .select()
162
+ .from(nodes)
163
+ .where(and(eq(nodes.workspaceId, workspaceId), eq(nodes.id, request.preferredNodeId)));
164
+ if (node && nodeHasCapability(node, capability) && !excluded.has(node.id)) {
165
+ return {
166
+ node,
167
+ capability,
168
+ queued: !isNodeLive(node) || !node.handlersLive,
169
+ };
170
+ }
171
+ if (node && excluded.has(node.id)) {
172
+ throw codedError(`Node "${node.name}" is unavailable for retry`, 'handler_unavailable', 503);
173
+ }
174
+ }
175
+ if (target === 'self') {
176
+ if (!request.callerId) {
177
+ throw codedError('target "self" requires an agent caller', 'placement_self_requires_agent', 400);
178
+ }
179
+ const [caller] = await db
180
+ .select({
181
+ locationNodeId: agents.locationNodeId,
182
+ locationType: agents.locationType,
183
+ })
184
+ .from(agents)
185
+ .where(and(eq(agents.workspaceId, workspaceId), eq(agents.id, request.callerId)));
186
+ if (!caller || caller.locationType !== 'via_node' || !caller.locationNodeId) {
187
+ throw codedError('caller is not attached to a node', 'placement_self_unavailable', 409);
188
+ }
189
+ const [node] = await db
190
+ .select()
191
+ .from(nodes)
192
+ .where(and(eq(nodes.workspaceId, workspaceId), eq(nodes.id, caller.locationNodeId)));
193
+ if (!node) {
194
+ throw codedError('caller node was not found', 'node_not_found', 404);
195
+ }
196
+ if (excluded.has(node.id)) {
197
+ throw codedError(`Node "${node.name}" is unavailable for retry`, 'handler_unavailable', 503);
198
+ }
199
+ if (!nodeHasCapability(node, capability)) {
200
+ throw codedError(`Node "${node.name}" does not provide ${capability}`, 'capability_mismatch', 409);
201
+ }
202
+ return {
203
+ node,
204
+ capability,
205
+ queued: !isNodeLive(node) || !node.handlersLive,
206
+ };
207
+ }
208
+ if (target) {
209
+ const [node] = await db
210
+ .select()
211
+ .from(nodes)
212
+ .where(and(eq(nodes.workspaceId, workspaceId), eq(nodes.name, target)));
213
+ if (!node) {
214
+ throw codedError(`Node "${target}" not found`, 'node_not_found', 404);
215
+ }
216
+ if (excluded.has(node.id)) {
217
+ throw codedError(`Node "${node.name}" is unavailable for retry`, 'handler_unavailable', 503);
218
+ }
219
+ if (!nodeHasCapability(node, capability)) {
220
+ throw codedError(`Node "${target}" does not provide ${capability}`, 'capability_mismatch', 409);
221
+ }
222
+ return {
223
+ node,
224
+ capability,
225
+ queued: !isNodeLive(node) || !node.handlersLive,
226
+ };
227
+ }
228
+ const rows = await db.select().from(nodes).where(eq(nodes.workspaceId, workspaceId));
229
+ const eligible = rows
230
+ .filter((node) => !excluded.has(node.id) &&
231
+ nodeHasCapability(node, capability) &&
232
+ isNodeLive(node) &&
233
+ node.handlersLive &&
234
+ nodeHasCapacity(node))
235
+ .sort((a, b) => (a.load - b.load) || (a.activeAgents - b.activeAgents) || a.name.localeCompare(b.name));
236
+ const node = eligible[0];
237
+ if (!node) {
238
+ throw codedError(`No live node provides ${capability}`, 'handler_unavailable', 503);
239
+ }
240
+ return { node, capability, queued: false };
241
+ }
242
+ //# sourceMappingURL=placement.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"placement.js","sourceRoot":"","sources":["../../src/engine/placement.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"receipt.d.ts","sourceRoot":"","sources":["../../src/engine/receipt.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAa5C,KAAK,EAAE,GAAG,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC;AAEnC,wBAAsB,QAAQ,CAC5B,EAAE,EAAE,EAAE,EACN,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM;;;;UAoFhB;AAED,wBAAsB,UAAU,CAAC,EAAE,EAAE,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;;;;YAkB9E;AAED,wBAAsB,aAAa,CAAC,EAAE,EAAE,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM;;;;YA+BnF"}
1
+ {"version":3,"file":"receipt.d.ts","sourceRoot":"","sources":["../../src/engine/receipt.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAa5C,KAAK,EAAE,GAAG,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC;AAEnC,wBAAsB,QAAQ,CAC5B,EAAE,EAAE,EAAE,EACN,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM;;;;UAmFhB;AAED,wBAAsB,UAAU,CAAC,EAAE,EAAE,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;;;;YAkB9E;AAED,wBAAsB,aAAa,CAAC,EAAE,EAAE,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM;;;;YA+BnF"}
@@ -36,14 +36,13 @@ export async function markRead(db, workspaceId, messageId, agentId) {
36
36
  .insert(readReceipts)
37
37
  .values({ messageId, agentId })
38
38
  .onConflictDoNothing(),
39
- // Transition delivery status to delivered. Reading consumes the message, so
40
- // clear both still-queued states (accepted and deferred) otherwise a
41
- // deferred delivery would linger in the durable replay queue after the agent
42
- // has already seen the message. `delivered`/`failed` are left untouched.
39
+ // Transition delivery status to acked. Reading consumes the message, so
40
+ // clear any in-flight mailbox state; otherwise a delivery would linger in
41
+ // the durable replay queue after the agent has already seen the message.
43
42
  writeDb
44
43
  .update(deliveries)
45
- .set({ status: 'delivered', updatedAt: new Date() })
46
- .where(and(eq(deliveries.messageId, messageId), eq(deliveries.agentId, agentId), inArray(deliveries.status, ['accepted', 'deferred']))),
44
+ .set({ status: 'acked', ackedAt: new Date(), updatedAt: new Date() })
45
+ .where(and(eq(deliveries.messageId, messageId), eq(deliveries.agentId, agentId), inArray(deliveries.status, ['queued', 'delivered']))),
47
46
  // Update lastReadId for the channel membership (only move forward)
48
47
  writeDb
49
48
  .update(channelMembers)
@@ -1 +1 @@
1
- {"version":3,"file":"receipt.js","sourceRoot":"","sources":["../../src/engine/receipt.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"receipt.js","sourceRoot":"","sources":["../../src/engine/receipt.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,65 @@
1
+ import type { getDb } from '../db/index.js';
2
+ type Db = ReturnType<typeof getDb>;
3
+ /** Settled deliveries are operational tracking rows, pruned after 90 days by default. */
4
+ export declare const DEFAULT_DELIVERY_TTL_DAYS = 90;
5
+ /** Message logs are operational telemetry (duplicate bodies), pruned after 90 days by default. */
6
+ export declare const DEFAULT_MESSAGE_LOG_TTL_DAYS = 90;
7
+ /**
8
+ * Deployment-wide TTL fallbacks, applied to workspaces without their own
9
+ * `workspaces.retention` settings. `null` disables pruning for that table.
10
+ */
11
+ export interface RetentionDefaults {
12
+ /** Messages are user data: no default — pruning is opt-in per workspace. */
13
+ messageTtlDays?: number | null;
14
+ /** Default {@link DEFAULT_DELIVERY_TTL_DAYS}. */
15
+ deliveryTtlDays?: number | null;
16
+ /** Default {@link DEFAULT_MESSAGE_LOG_TTL_DAYS}. */
17
+ messageLogTtlDays?: number | null;
18
+ }
19
+ export interface PruneOptions {
20
+ /** Max rows deleted per table per batch (the SQL LIMIT). Default 200. */
21
+ batchLimit?: number;
22
+ /** Max batches per table per call, bounding total work per run. Default 5. */
23
+ maxBatches?: number;
24
+ /** Clock override for tests. */
25
+ now?: Date;
26
+ /** Deployment-wide TTL fallbacks; see {@link RetentionDefaults}. */
27
+ defaults?: RetentionDefaults;
28
+ }
29
+ /** Rows deleted per table by a {@link pruneExpired} run. */
30
+ export interface PruneResult {
31
+ messages: number;
32
+ deliveries: number;
33
+ messageLogs: number;
34
+ readReceipts: number;
35
+ }
36
+ /**
37
+ * Delete expired rows in bounded batches.
38
+ *
39
+ * Per-workspace TTLs come from `workspaces.retention` (see
40
+ * {@link WorkspaceRetentionSettings}); workspaces without settings inherit
41
+ * `opts.defaults`. Out of the box only operational tables are pruned
42
+ * (settled `deliveries` and `message_logs`, 90 days); `messages` retention is
43
+ * strictly opt-in — no workspace loses message history unless its settings
44
+ * (or an explicit deployment default) say so.
45
+ *
46
+ * What a run does, per table, oldest rows first:
47
+ * - `messages` older than the effective TTL, leaf-first: a message still
48
+ * referenced as a `thread_id` parent is skipped until its replies age out,
49
+ * so the self-referencing FK never breaks mid-batch. Cascades take the
50
+ * message's receipts, reactions, attachments, deliveries, and log row.
51
+ * - settled `deliveries` (`acked`/`failed`/`dead_lettered`) older than the
52
+ * effective TTL. In-flight rows (`queued`/`delivered`) are never touched.
53
+ * - `message_logs` older than the effective TTL.
54
+ * - `read_receipts` whose message no longer exists (defensive sweep for rows
55
+ * written while FK enforcement was off).
56
+ *
57
+ * Every DELETE is a single `id IN (SELECT ... LIMIT n)` statement, capped at
58
+ * `batchLimit` rows and `maxBatches` passes per table, so a run is always
59
+ * short-lived and D1-friendly. Callers run it on a cadence (the Node adapter's
60
+ * outbox cleanup tick, or a cloud scheduled handler) and backlogs drain over
61
+ * successive runs.
62
+ */
63
+ export declare function pruneExpired(db: Db, opts?: PruneOptions): Promise<PruneResult>;
64
+ export {};
65
+ //# sourceMappingURL=retention.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retention.d.ts","sourceRoot":"","sources":["../../src/engine/retention.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAW5C,KAAK,EAAE,GAAG,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC;AAInC,yFAAyF;AACzF,eAAO,MAAM,yBAAyB,KAAK,CAAC;AAC5C,kGAAkG;AAClG,eAAO,MAAM,4BAA4B,KAAK,CAAC;AAe/C;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,4EAA4E;IAC5E,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,iDAAiD;IACjD,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,oDAAoD;IACpD,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAED,MAAM,WAAW,YAAY;IAC3B,yEAAyE;IACzE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8EAA8E;IAC9E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gCAAgC;IAChC,GAAG,CAAC,EAAE,IAAI,CAAC;IACX,oEAAoE;IACpE,QAAQ,CAAC,EAAE,iBAAiB,CAAC;CAC9B;AAED,4DAA4D;AAC5D,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB;AAsBD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAsB,YAAY,CAAC,EAAE,EAAE,EAAE,EAAE,IAAI,GAAE,YAAiB,GAAG,OAAO,CAAC,WAAW,CAAC,CA0IxF"}
@@ -0,0 +1,173 @@
1
+ import { and, eq, inArray, isNotNull, isNull, lt, notInArray, sql } from 'drizzle-orm';
2
+ import { deliveries, messageLogs, messages, readReceipts, workspaces, } from '../db/schema.js';
3
+ import { snowflakeIdLowerBound } from './snowflake.js';
4
+ const DAY_MS = 24 * 60 * 60 * 1000;
5
+ /** Settled deliveries are operational tracking rows, pruned after 90 days by default. */
6
+ export const DEFAULT_DELIVERY_TTL_DAYS = 90;
7
+ /** Message logs are operational telemetry (duplicate bodies), pruned after 90 days by default. */
8
+ export const DEFAULT_MESSAGE_LOG_TTL_DAYS = 90;
9
+ const DEFAULT_BATCH_LIMIT = 200;
10
+ const DEFAULT_MAX_BATCHES = 5;
11
+ /**
12
+ * Delivery statuses that are terminal — the row is only kept as history.
13
+ * Mirrors the engine's settled set (delivery.ts): `acked` (recipient
14
+ * acknowledged), `dead_lettered` (TTL expiry), and `failed`. NOTE: `delivered`
15
+ * is NOT terminal under the durable-mailbox model — it means "sent to the
16
+ * current location, awaiting cumulative ack" (in-flight), so it must never be
17
+ * pruned here; only `acked` is terminal success.
18
+ */
19
+ const SETTLED_DELIVERY_STATUSES = ['acked', 'failed', 'dead_lettered'];
20
+ /**
21
+ * `column < snowflakeIdLowerBound(cutoff)` compared numerically.
22
+ *
23
+ * Snowflake IDs are stored as decimal TEXT without leading zeros, and their
24
+ * digit count grows over time — plain lexicographic `<` would mis-order a
25
+ * short (older) ID against a longer bound. For non-negative decimals without
26
+ * leading zeros, "shorter string" implies "smaller number", so length-then-lex
27
+ * comparison is numerically exact.
28
+ */
29
+ function olderThanSnowflake(column, cutoffMs) {
30
+ const bound = snowflakeIdLowerBound(cutoffMs);
31
+ return sql `(length(${column}) < ${bound.length} OR (length(${column}) = ${bound.length} AND ${column} < ${bound}))`;
32
+ }
33
+ /**
34
+ * Delete expired rows in bounded batches.
35
+ *
36
+ * Per-workspace TTLs come from `workspaces.retention` (see
37
+ * {@link WorkspaceRetentionSettings}); workspaces without settings inherit
38
+ * `opts.defaults`. Out of the box only operational tables are pruned
39
+ * (settled `deliveries` and `message_logs`, 90 days); `messages` retention is
40
+ * strictly opt-in — no workspace loses message history unless its settings
41
+ * (or an explicit deployment default) say so.
42
+ *
43
+ * What a run does, per table, oldest rows first:
44
+ * - `messages` older than the effective TTL, leaf-first: a message still
45
+ * referenced as a `thread_id` parent is skipped until its replies age out,
46
+ * so the self-referencing FK never breaks mid-batch. Cascades take the
47
+ * message's receipts, reactions, attachments, deliveries, and log row.
48
+ * - settled `deliveries` (`acked`/`failed`/`dead_lettered`) older than the
49
+ * effective TTL. In-flight rows (`queued`/`delivered`) are never touched.
50
+ * - `message_logs` older than the effective TTL.
51
+ * - `read_receipts` whose message no longer exists (defensive sweep for rows
52
+ * written while FK enforcement was off).
53
+ *
54
+ * Every DELETE is a single `id IN (SELECT ... LIMIT n)` statement, capped at
55
+ * `batchLimit` rows and `maxBatches` passes per table, so a run is always
56
+ * short-lived and D1-friendly. Callers run it on a cadence (the Node adapter's
57
+ * outbox cleanup tick, or a cloud scheduled handler) and backlogs drain over
58
+ * successive runs.
59
+ */
60
+ export async function pruneExpired(db, opts = {}) {
61
+ const now = opts.now ?? new Date();
62
+ const batchLimit = Math.max(1, opts.batchLimit ?? DEFAULT_BATCH_LIMIT);
63
+ const maxBatches = Math.max(1, opts.maxBatches ?? DEFAULT_MAX_BATCHES);
64
+ const defaults = {
65
+ messageTtlDays: opts.defaults?.messageTtlDays ?? null,
66
+ deliveryTtlDays: opts.defaults?.deliveryTtlDays !== undefined
67
+ ? opts.defaults.deliveryTtlDays
68
+ : DEFAULT_DELIVERY_TTL_DAYS,
69
+ messageLogTtlDays: opts.defaults?.messageLogTtlDays !== undefined
70
+ ? opts.defaults.messageLogTtlDays
71
+ : DEFAULT_MESSAGE_LOG_TTL_DAYS,
72
+ };
73
+ // Workspaces with explicit settings get their own pass; everyone else is
74
+ // covered by one unscoped pass per table using the deployment default.
75
+ const overrides = await db
76
+ .select({ id: workspaces.id, retention: workspaces.retention })
77
+ .from(workspaces)
78
+ .where(isNotNull(workspaces.retention));
79
+ const overrideIds = overrides.map((o) => o.id);
80
+ function passes(defaultTtlDays, pick, workspaceIdColumn) {
81
+ const out = [];
82
+ if (defaultTtlDays != null && defaultTtlDays > 0) {
83
+ out.push({
84
+ cutoff: new Date(now.getTime() - defaultTtlDays * DAY_MS),
85
+ scope: overrideIds.length > 0 ? notInArray(workspaceIdColumn, overrideIds) : undefined,
86
+ });
87
+ }
88
+ for (const override of overrides) {
89
+ const setting = pick(override.retention ?? {});
90
+ // undefined inherits the default; explicit null disables pruning.
91
+ const ttlDays = setting === undefined ? defaultTtlDays : setting;
92
+ if (ttlDays != null && ttlDays > 0) {
93
+ out.push({
94
+ cutoff: new Date(now.getTime() - ttlDays * DAY_MS),
95
+ scope: eq(workspaceIdColumn, override.id),
96
+ });
97
+ }
98
+ }
99
+ return out;
100
+ }
101
+ async function drain(deleteBatch) {
102
+ let total = 0;
103
+ for (let i = 0; i < maxBatches; i++) {
104
+ const deleted = await deleteBatch();
105
+ total += deleted;
106
+ if (deleted < batchLimit)
107
+ break;
108
+ }
109
+ return total;
110
+ }
111
+ const result = { messages: 0, deliveries: 0, messageLogs: 0, readReceipts: 0 };
112
+ // Messages — leaf-first so the self-referencing thread FK never breaks.
113
+ for (const pass of passes(defaults.messageTtlDays, (s) => s.message_ttl_days, messages.workspaceId)) {
114
+ result.messages += await drain(async () => {
115
+ const batch = db
116
+ .select({ id: messages.id })
117
+ .from(messages)
118
+ .where(and(olderThanSnowflake(messages.id, pass.cutoff.getTime()), sql `NOT EXISTS (SELECT 1 FROM messages replies WHERE replies.thread_id = ${messages.id})`, pass.scope))
119
+ .limit(batchLimit);
120
+ const deleted = await db
121
+ .delete(messages)
122
+ .where(inArray(messages.id, batch))
123
+ .returning({ id: messages.id });
124
+ return deleted.length;
125
+ });
126
+ }
127
+ // Settled deliveries.
128
+ for (const pass of passes(defaults.deliveryTtlDays, (s) => s.delivery_ttl_days, deliveries.workspaceId)) {
129
+ result.deliveries += await drain(async () => {
130
+ const batch = db
131
+ .select({ id: deliveries.id })
132
+ .from(deliveries)
133
+ .where(and(inArray(deliveries.status, SETTLED_DELIVERY_STATUSES), lt(deliveries.createdAt, pass.cutoff), pass.scope))
134
+ .limit(batchLimit);
135
+ const deleted = await db
136
+ .delete(deliveries)
137
+ .where(inArray(deliveries.id, batch))
138
+ .returning({ id: deliveries.id });
139
+ return deleted.length;
140
+ });
141
+ }
142
+ // Message logs.
143
+ for (const pass of passes(defaults.messageLogTtlDays, (s) => s.message_log_ttl_days, messageLogs.workspaceId)) {
144
+ result.messageLogs += await drain(async () => {
145
+ const batch = db
146
+ .select({ id: messageLogs.id })
147
+ .from(messageLogs)
148
+ .where(and(olderThanSnowflake(messageLogs.id, pass.cutoff.getTime()), pass.scope))
149
+ .limit(batchLimit);
150
+ const deleted = await db
151
+ .delete(messageLogs)
152
+ .where(inArray(messageLogs.id, batch))
153
+ .returning({ id: messageLogs.id });
154
+ return deleted.length;
155
+ });
156
+ }
157
+ // Orphaned read receipts (referential garbage, always swept).
158
+ result.readReceipts += await drain(async () => {
159
+ const orphaned = db
160
+ .select({ messageId: readReceipts.messageId })
161
+ .from(readReceipts)
162
+ .leftJoin(messages, eq(messages.id, readReceipts.messageId))
163
+ .where(isNull(messages.id))
164
+ .limit(batchLimit);
165
+ const deleted = await db
166
+ .delete(readReceipts)
167
+ .where(inArray(readReceipts.messageId, orphaned))
168
+ .returning({ messageId: readReceipts.messageId });
169
+ return deleted.length;
170
+ });
171
+ return result;
172
+ }
173
+ //# sourceMappingURL=retention.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retention.js","sourceRoot":"","sources":["../../src/engine/retention.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,GAAG,EAAY,MAAM,aAAa,CAAC;AAGjG,OAAO,EACL,UAAU,EACV,WAAW,EACX,QAAQ,EACR,YAAY,EACZ,UAAU,GAEX,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAIvD,MAAM,MAAM,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAEnC,yFAAyF;AACzF,MAAM,CAAC,MAAM,yBAAyB,GAAG,EAAE,CAAC;AAC5C,kGAAkG;AAClG,MAAM,CAAC,MAAM,4BAA4B,GAAG,EAAE,CAAC;AAE/C,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAChC,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAE9B;;;;;;;GAOG;AACH,MAAM,yBAAyB,GAAG,CAAC,OAAO,EAAE,QAAQ,EAAE,eAAe,CAAC,CAAC;AAkCvE;;;;;;;;GAQG;AACH,SAAS,kBAAkB,CAAC,MAAoB,EAAE,QAAgB;IAChE,MAAM,KAAK,GAAG,qBAAqB,CAAC,QAAQ,CAAC,CAAC;IAC9C,OAAO,GAAG,CAAA,WAAW,MAAM,OAAO,KAAK,CAAC,MAAM,eAAe,MAAM,OAAO,KAAK,CAAC,MAAM,QAAQ,MAAM,MAAM,KAAK,IAAI,CAAC;AACtH,CAAC;AAQD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,EAAM,EAAE,OAAqB,EAAE;IAChE,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC;IACnC,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,UAAU,IAAI,mBAAmB,CAAC,CAAC;IACvE,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,UAAU,IAAI,mBAAmB,CAAC,CAAC;IACvE,MAAM,QAAQ,GAAgC;QAC5C,cAAc,EAAE,IAAI,CAAC,QAAQ,EAAE,cAAc,IAAI,IAAI;QACrD,eAAe,EACb,IAAI,CAAC,QAAQ,EAAE,eAAe,KAAK,SAAS;YAC1C,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,eAAe;YAC/B,CAAC,CAAC,yBAAyB;QAC/B,iBAAiB,EACf,IAAI,CAAC,QAAQ,EAAE,iBAAiB,KAAK,SAAS;YAC5C,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,iBAAiB;YACjC,CAAC,CAAC,4BAA4B;KACnC,CAAC;IAEF,yEAAyE;IACzE,uEAAuE;IACvE,MAAM,SAAS,GAAG,MAAM,EAAE;SACvB,MAAM,CAAC,EAAE,EAAE,EAAE,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,UAAU,CAAC,SAAS,EAAE,CAAC;SAC9D,IAAI,CAAC,UAAU,CAAC;SAChB,KAAK,CAAC,SAAS,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC;IAC1C,MAAM,WAAW,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAE/C,SAAS,MAAM,CACb,cAA6B,EAC7B,IAAyE,EACzE,iBAA+B;QAE/B,MAAM,GAAG,GAAgB,EAAE,CAAC;QAC5B,IAAI,cAAc,IAAI,IAAI,IAAI,cAAc,GAAG,CAAC,EAAE,CAAC;YACjD,GAAG,CAAC,IAAI,CAAC;gBACP,MAAM,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,cAAc,GAAG,MAAM,CAAC;gBACzD,KAAK,EAAE,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,iBAAiB,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,SAAS;aACvF,CAAC,CAAC;QACL,CAAC;QACD,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YACjC,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;YAC/C,kEAAkE;YAClE,MAAM,OAAO,GAAG,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,OAAO,CAAC;YACjE,IAAI,OAAO,IAAI,IAAI,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;gBACnC,GAAG,CAAC,IAAI,CAAC;oBACP,MAAM,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,OAAO,GAAG,MAAM,CAAC;oBAClD,KAAK,EAAE,EAAE,CAAC,iBAAiB,EAAE,QAAQ,CAAC,EAAE,CAAC;iBAC1C,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAED,KAAK,UAAU,KAAK,CAAC,WAAkC;QACrD,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,EAAE,CAAC,EAAE,EAAE,CAAC;YACpC,MAAM,OAAO,GAAG,MAAM,WAAW,EAAE,CAAC;YACpC,KAAK,IAAI,OAAO,CAAC;YACjB,IAAI,OAAO,GAAG,UAAU;gBAAE,MAAM;QAClC,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,MAAM,GAAgB,EAAE,QAAQ,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC;IAE5F,wEAAwE;IACxE,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,QAAQ,CAAC,cAAc,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,gBAAgB,EAAE,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;QACpG,MAAM,CAAC,QAAQ,IAAI,MAAM,KAAK,CAAC,KAAK,IAAI,EAAE;YACxC,MAAM,KAAK,GAAG,EAAE;iBACb,MAAM,CAAC,EAAE,EAAE,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC;iBAC3B,IAAI,CAAC,QAAQ,CAAC;iBACd,KAAK,CACJ,GAAG,CACD,kBAAkB,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,EACtD,GAAG,CAAA,wEAAwE,QAAQ,CAAC,EAAE,GAAG,EACzF,IAAI,CAAC,KAAK,CACX,CACF;iBACA,KAAK,CAAC,UAAU,CAAC,CAAC;YACrB,MAAM,OAAO,GAAG,MAAM,EAAE;iBACrB,MAAM,CAAC,QAAQ,CAAC;iBAChB,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;iBAClC,SAAS,CAAC,EAAE,EAAE,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC;YAClC,OAAO,OAAO,CAAC,MAAM,CAAC;QACxB,CAAC,CAAC,CAAC;IACL,CAAC;IAED,sBAAsB;IACtB,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,QAAQ,CAAC,eAAe,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,iBAAiB,EAAE,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QACxG,MAAM,CAAC,UAAU,IAAI,MAAM,KAAK,CAAC,KAAK,IAAI,EAAE;YAC1C,MAAM,KAAK,GAAG,EAAE;iBACb,MAAM,CAAC,EAAE,EAAE,EAAE,UAAU,CAAC,EAAE,EAAE,CAAC;iBAC7B,IAAI,CAAC,UAAU,CAAC;iBAChB,KAAK,CACJ,GAAG,CACD,OAAO,CAAC,UAAU,CAAC,MAAM,EAAE,yBAAyB,CAAC,EACrD,EAAE,CAAC,UAAU,CAAC,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,EACrC,IAAI,CAAC,KAAK,CACX,CACF;iBACA,KAAK,CAAC,UAAU,CAAC,CAAC;YACrB,MAAM,OAAO,GAAG,MAAM,EAAE;iBACrB,MAAM,CAAC,UAAU,CAAC;iBAClB,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;iBACpC,SAAS,CAAC,EAAE,EAAE,EAAE,UAAU,CAAC,EAAE,EAAE,CAAC,CAAC;YACpC,OAAO,OAAO,CAAC,MAAM,CAAC;QACxB,CAAC,CAAC,CAAC;IACL,CAAC;IAED,gBAAgB;IAChB,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,QAAQ,CAAC,iBAAiB,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,oBAAoB,EAAE,WAAW,CAAC,WAAW,CAAC,EAAE,CAAC;QAC9G,MAAM,CAAC,WAAW,IAAI,MAAM,KAAK,CAAC,KAAK,IAAI,EAAE;YAC3C,MAAM,KAAK,GAAG,EAAE;iBACb,MAAM,CAAC,EAAE,EAAE,EAAE,WAAW,CAAC,EAAE,EAAE,CAAC;iBAC9B,IAAI,CAAC,WAAW,CAAC;iBACjB,KAAK,CAAC,GAAG,CAAC,kBAAkB,CAAC,WAAW,CAAC,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;iBACjF,KAAK,CAAC,UAAU,CAAC,CAAC;YACrB,MAAM,OAAO,GAAG,MAAM,EAAE;iBACrB,MAAM,CAAC,WAAW,CAAC;iBACnB,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;iBACrC,SAAS,CAAC,EAAE,EAAE,EAAE,WAAW,CAAC,EAAE,EAAE,CAAC,CAAC;YACrC,OAAO,OAAO,CAAC,MAAM,CAAC;QACxB,CAAC,CAAC,CAAC;IACL,CAAC;IAED,8DAA8D;IAC9D,MAAM,CAAC,YAAY,IAAI,MAAM,KAAK,CAAC,KAAK,IAAI,EAAE;QAC5C,MAAM,QAAQ,GAAG,EAAE;aAChB,MAAM,CAAC,EAAE,SAAS,EAAE,YAAY,CAAC,SAAS,EAAE,CAAC;aAC7C,IAAI,CAAC,YAAY,CAAC;aAClB,QAAQ,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,YAAY,CAAC,SAAS,CAAC,CAAC;aAC3D,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;aAC1B,KAAK,CAAC,UAAU,CAAC,CAAC;QACrB,MAAM,OAAO,GAAG,MAAM,EAAE;aACrB,MAAM,CAAC,YAAY,CAAC;aACpB,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;aAChD,SAAS,CAAC,EAAE,SAAS,EAAE,YAAY,CAAC,SAAS,EAAE,CAAC,CAAC;QACpD,OAAO,OAAO,CAAC,MAAM,CAAC;IACxB,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -9,6 +9,17 @@ export declare class SnowflakeGenerator {
9
9
  static extractWorkerId(id: string): number;
10
10
  static extractSequence(id: string): number;
11
11
  }
12
+ /**
13
+ * The smallest snowflake ID a row created at `timestampMs` could have.
14
+ *
15
+ * Snowflakes are time-ordered, so this is usable as an exclusive upper bound
16
+ * when selecting rows older than a cutoff: every ID generated before
17
+ * `timestampMs` is numerically smaller than the returned value. Note IDs are
18
+ * stored as decimal TEXT of varying length, so compare numerically (shorter
19
+ * string == smaller ID), not lexicographically — see `olderThanSnowflake` in
20
+ * `retention.ts`.
21
+ */
22
+ export declare function snowflakeIdLowerBound(timestampMs: number): string;
12
23
  export declare function getSnowflakeGenerator(): SnowflakeGenerator;
13
24
  export declare function generateId(): string;
14
25
  //# sourceMappingURL=snowflake.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"snowflake.d.ts","sourceRoot":"","sources":["../../src/engine/snowflake.ts"],"names":[],"mappings":"AA0BA,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,CAAS;IAC1B,OAAO,CAAC,aAAa,CAAM;IAC3B,OAAO,CAAC,QAAQ,CAAK;gBAET,QAAQ,CAAC,EAAE,MAAM;IAI7B,WAAW,IAAI,MAAM;IAOrB,QAAQ,IAAI,MAAM;IA6BlB,MAAM,CAAC,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM;IAM3C,MAAM,CAAC,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM;IAM1C,MAAM,CAAC,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM;CAK3C;AAID,wBAAgB,qBAAqB,IAAI,kBAAkB,CAK1D;AAED,wBAAgB,UAAU,IAAI,MAAM,CAEnC"}
1
+ {"version":3,"file":"snowflake.d.ts","sourceRoot":"","sources":["../../src/engine/snowflake.ts"],"names":[],"mappings":"AA0BA,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,CAAS;IAC1B,OAAO,CAAC,aAAa,CAAM;IAC3B,OAAO,CAAC,QAAQ,CAAK;gBAET,QAAQ,CAAC,EAAE,MAAM;IAI7B,WAAW,IAAI,MAAM;IAOrB,QAAQ,IAAI,MAAM;IA6BlB,MAAM,CAAC,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM;IAM3C,MAAM,CAAC,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM;IAM1C,MAAM,CAAC,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM;CAK3C;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAGjE;AAID,wBAAgB,qBAAqB,IAAI,kBAAkB,CAK1D;AAED,wBAAgB,UAAU,IAAI,MAAM,CAEnC"}
@@ -75,6 +75,20 @@ export class SnowflakeGenerator {
75
75
  return Number(seq);
76
76
  }
77
77
  }
78
+ /**
79
+ * The smallest snowflake ID a row created at `timestampMs` could have.
80
+ *
81
+ * Snowflakes are time-ordered, so this is usable as an exclusive upper bound
82
+ * when selecting rows older than a cutoff: every ID generated before
83
+ * `timestampMs` is numerically smaller than the returned value. Note IDs are
84
+ * stored as decimal TEXT of varying length, so compare numerically (shorter
85
+ * string == smaller ID), not lexicographically — see `olderThanSnowflake` in
86
+ * `retention.ts`.
87
+ */
88
+ export function snowflakeIdLowerBound(timestampMs) {
89
+ const ts = BigInt(Math.max(0, timestampMs - EPOCH_MS));
90
+ return (ts << TIMESTAMP_SHIFT).toString();
91
+ }
78
92
  let defaultGenerator = null;
79
93
  export function getSnowflakeGenerator() {
80
94
  if (!defaultGenerator) {
@@ -1 +1 @@
1
- {"version":3,"file":"snowflake.js","sourceRoot":"","sources":["../../src/engine/snowflake.ts"],"names":[],"mappings":"AAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,uBAAuB;AAE9D,MAAM,cAAc,GAAG,GAAG,CAAC;AAC3B,MAAM,aAAa,GAAG,GAAG,CAAC;AAC1B,MAAM,aAAa,GAAG,CAAC,EAAE,IAAI,aAAa,CAAC,GAAG,EAAE,CAAC,CAAC,UAAU;AAC5D,MAAM,cAAc,GAAG,CAAC,EAAE,IAAI,cAAc,CAAC,GAAG,EAAE,CAAC,CAAC,UAAU;AAC9D,MAAM,eAAe,GAAG,aAAa,CAAC;AACtC,MAAM,eAAe,GAAG,aAAa,GAAG,cAAc,CAAC;AAEvD,wDAAwD;AACxD,IAAI,UAA8B,CAAC;AACnC,SAAS,YAAY;IACnB,IAAI,CAAC,UAAU;QAAE,UAAU,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;IAClD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,SAAS,WAAW,CAAC,KAAa;IAChC,gCAAgC;IAChC,IAAI,IAAI,GAAG,UAAU,CAAC;IACtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,IAAI,IAAI,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QAC5B,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,IAAI,GAAG,KAAK,CAAC;AACtB,CAAC;AAED,MAAM,OAAO,kBAAkB;IACrB,QAAQ,CAAU;IAClB,aAAa,GAAG,CAAC,CAAC,CAAC;IACnB,QAAQ,GAAG,CAAC,CAAC;IAErB,YAAY,QAAiB;QAC3B,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED,WAAW;QACT,IAAI,OAAO,IAAI,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YACtC,OAAO,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;QAC/B,CAAC;QACD,OAAO,WAAW,CAAC,YAAY,EAAE,CAAC,CAAC;IACrC,CAAC;IAED,QAAQ;QACN,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QAC/B,IAAI,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACrB,IAAI,GAAG,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;YAC7B,yEAAyE;YACzE,GAAG,GAAG,IAAI,CAAC,aAAa,CAAC;QAC3B,CAAC;QAED,IAAI,GAAG,KAAK,IAAI,CAAC,aAAa,EAAE,CAAC;YAC/B,IAAI,CAAC,QAAQ,GAAG,CAAC,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,aAAa,CAAC,CAAC;YAC5D,IAAI,IAAI,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;gBACxB,oDAAoD;gBACpD,OAAO,GAAG,IAAI,IAAI,CAAC,aAAa;oBAAE,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACrD,CAAC;QACH,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;QACpB,CAAC;QAED,IAAI,CAAC,aAAa,GAAG,GAAG,CAAC;QAEzB,MAAM,EAAE,GAAG,MAAM,CAAC,GAAG,GAAG,QAAQ,CAAC,CAAC;QAClC,MAAM,EAAE,GACN,CAAC,EAAE,IAAI,eAAe,CAAC;YACvB,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,cAAc,CAAC,IAAI,eAAe,CAAC;YACnD,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,aAAa,CAAC,CAAC;QAE1C,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC;IACvB,CAAC;IAED,MAAM,CAAC,gBAAgB,CAAC,EAAU;QAChC,MAAM,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC;QACrB,MAAM,EAAE,GAAG,CAAC,IAAI,eAAe,CAAC;QAChC,OAAO,MAAM,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC;IAC/B,CAAC;IAED,MAAM,CAAC,eAAe,CAAC,EAAU;QAC/B,MAAM,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC;QACrB,MAAM,GAAG,GAAG,CAAC,CAAC,IAAI,eAAe,CAAC,GAAG,cAAc,CAAC;QACpD,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;IACrB,CAAC;IAED,MAAM,CAAC,eAAe,CAAC,EAAU;QAC/B,MAAM,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC;QACrB,MAAM,GAAG,GAAG,CAAC,GAAG,aAAa,CAAC;QAC9B,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;IACrB,CAAC;CACF;AAED,IAAI,gBAAgB,GAA8B,IAAI,CAAC;AAEvD,MAAM,UAAU,qBAAqB;IACnC,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACtB,gBAAgB,GAAG,IAAI,kBAAkB,EAAE,CAAC;IAC9C,CAAC;IACD,OAAO,gBAAgB,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,OAAO,qBAAqB,EAAE,CAAC,QAAQ,EAAE,CAAC;AAC5C,CAAC"}
1
+ {"version":3,"file":"snowflake.js","sourceRoot":"","sources":["../../src/engine/snowflake.ts"],"names":[],"mappings":"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"}