@relaycast/engine 3.1.1 → 4.1.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.
- package/dist/adapters/node/event-queue.d.ts +10 -0
- package/dist/adapters/node/event-queue.d.ts.map +1 -1
- package/dist/adapters/node/event-queue.js +17 -0
- package/dist/adapters/node/event-queue.js.map +1 -1
- package/dist/adapters/node/index.d.ts.map +1 -1
- package/dist/adapters/node/index.js +10 -0
- package/dist/adapters/node/index.js.map +1 -1
- package/dist/adapters/node/realtime.d.ts +24 -2
- package/dist/adapters/node/realtime.d.ts.map +1 -1
- package/dist/adapters/node/realtime.js +178 -1
- package/dist/adapters/node/realtime.js.map +1 -1
- package/dist/bin/serve.js +18 -1
- package/dist/bin/serve.js.map +1 -1
- package/dist/db/migrations/0016_fleet_nodes.sql +189 -0
- package/dist/db/migrations/0017_spawn_reservation_and_retry_state.sql +5 -0
- package/dist/db/migrations/0018_spawn_reserved_at.sql +2 -0
- package/dist/db/migrations/0019_fleet_mailbox.sql +71 -0
- package/dist/db/migrations/0020_workspace_retention.sql +3 -0
- package/dist/db/schema.d.ts +1771 -911
- package/dist/db/schema.d.ts.map +1 -1
- package/dist/db/schema.js +77 -7
- package/dist/db/schema.js.map +1 -1
- package/dist/engine/action.d.ts +84 -10
- package/dist/engine/action.d.ts.map +1 -1
- package/dist/engine/action.js +523 -85
- package/dist/engine/action.js.map +1 -1
- package/dist/engine/agent.js +2 -2
- package/dist/engine/agent.js.map +1 -1
- package/dist/engine/delivery.d.ts +41 -6
- package/dist/engine/delivery.d.ts.map +1 -1
- package/dist/engine/delivery.js +316 -25
- package/dist/engine/delivery.js.map +1 -1
- package/dist/engine/deliveryWire.d.ts +34 -0
- package/dist/engine/deliveryWire.d.ts.map +1 -0
- package/dist/engine/deliveryWire.js +70 -0
- package/dist/engine/deliveryWire.js.map +1 -0
- package/dist/engine/deliveryWrites.d.ts +47 -0
- package/dist/engine/deliveryWrites.d.ts.map +1 -1
- package/dist/engine/deliveryWrites.js +155 -5
- package/dist/engine/deliveryWrites.js.map +1 -1
- package/dist/engine/dm.d.ts +4 -4
- package/dist/engine/dm.d.ts.map +1 -1
- package/dist/engine/dm.js +17 -7
- package/dist/engine/dm.js.map +1 -1
- package/dist/engine/eventQueue.d.ts.map +1 -1
- package/dist/engine/eventQueue.js +5 -0
- package/dist/engine/eventQueue.js.map +1 -1
- package/dist/engine/eventSubscription.d.ts +6 -0
- package/dist/engine/eventSubscription.d.ts.map +1 -1
- package/dist/engine/eventSubscription.js +13 -0
- package/dist/engine/eventSubscription.js.map +1 -1
- package/dist/engine/groupDm.d.ts +4 -0
- package/dist/engine/groupDm.d.ts.map +1 -1
- package/dist/engine/groupDm.js +16 -4
- package/dist/engine/groupDm.js.map +1 -1
- package/dist/engine/invocationCompletion.d.ts +13 -0
- package/dist/engine/invocationCompletion.d.ts.map +1 -0
- package/dist/engine/invocationCompletion.js +65 -0
- package/dist/engine/invocationCompletion.js.map +1 -0
- package/dist/engine/mailboxConfig.d.ts +9 -0
- package/dist/engine/mailboxConfig.d.ts.map +1 -0
- package/dist/engine/mailboxConfig.js +16 -0
- package/dist/engine/mailboxConfig.js.map +1 -0
- package/dist/engine/message.d.ts +4 -0
- package/dist/engine/message.d.ts.map +1 -1
- package/dist/engine/message.js +16 -4
- package/dist/engine/message.js.map +1 -1
- package/dist/engine/node.d.ts +201 -0
- package/dist/engine/node.d.ts.map +1 -0
- package/dist/engine/node.js +557 -0
- package/dist/engine/node.js.map +1 -0
- package/dist/engine/placement.d.ts +26 -0
- package/dist/engine/placement.d.ts.map +1 -0
- package/dist/engine/placement.js +242 -0
- package/dist/engine/placement.js.map +1 -0
- package/dist/engine/receipt.d.ts.map +1 -1
- package/dist/engine/receipt.js +5 -6
- package/dist/engine/receipt.js.map +1 -1
- package/dist/engine/retention.d.ts +65 -0
- package/dist/engine/retention.d.ts.map +1 -0
- package/dist/engine/retention.js +173 -0
- package/dist/engine/retention.js.map +1 -0
- package/dist/engine/snowflake.d.ts +11 -0
- package/dist/engine/snowflake.d.ts.map +1 -1
- package/dist/engine/snowflake.js +14 -0
- package/dist/engine/snowflake.js.map +1 -1
- package/dist/engine/thread.d.ts +4 -0
- package/dist/engine/thread.d.ts.map +1 -1
- package/dist/engine/thread.js +16 -4
- package/dist/engine/thread.js.map +1 -1
- package/dist/engine/trigger.d.ts +79 -0
- package/dist/engine/trigger.d.ts.map +1 -0
- package/dist/engine/trigger.js +151 -0
- package/dist/engine/trigger.js.map +1 -0
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +61 -2
- package/dist/engine.js.map +1 -1
- package/dist/entrypoints/node.d.ts.map +1 -1
- package/dist/entrypoints/node.js +36 -2
- package/dist/entrypoints/node.js.map +1 -1
- package/dist/env.d.ts +6 -0
- package/dist/env.d.ts.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/fleetNodes.d.ts +9 -0
- package/dist/lib/fleetNodes.d.ts.map +1 -0
- package/dist/lib/fleetNodes.js +66 -0
- package/dist/lib/fleetNodes.js.map +1 -0
- package/dist/lib/origin.d.ts.map +1 -1
- package/dist/lib/origin.js +0 -5
- package/dist/lib/origin.js.map +1 -1
- package/dist/lib/serverTelemetry.d.ts.map +1 -1
- package/dist/lib/serverTelemetry.js +0 -1
- package/dist/lib/serverTelemetry.js.map +1 -1
- package/dist/middleware/fleetNodes.d.ts +10 -0
- package/dist/middleware/fleetNodes.d.ts.map +1 -0
- package/dist/middleware/fleetNodes.js +18 -0
- package/dist/middleware/fleetNodes.js.map +1 -0
- package/dist/ports/index.d.ts +24 -2
- package/dist/ports/index.d.ts.map +1 -1
- package/dist/ports/realtime.d.ts +34 -2
- package/dist/ports/realtime.d.ts.map +1 -1
- package/dist/ports/realtime.js +1 -1
- package/dist/routes/action.d.ts.map +1 -1
- package/dist/routes/action.js +21 -21
- package/dist/routes/action.js.map +1 -1
- package/dist/routes/delivery.d.ts.map +1 -1
- package/dist/routes/delivery.js +7 -2
- package/dist/routes/delivery.js.map +1 -1
- package/dist/routes/deliveryRouting.d.ts +10 -0
- package/dist/routes/deliveryRouting.d.ts.map +1 -0
- package/dist/routes/deliveryRouting.js +91 -0
- package/dist/routes/deliveryRouting.js.map +1 -0
- package/dist/routes/dm.d.ts.map +1 -1
- package/dist/routes/dm.js +14 -13
- package/dist/routes/dm.js.map +1 -1
- package/dist/routes/groupDm.d.ts.map +1 -1
- package/dist/routes/groupDm.js +14 -15
- package/dist/routes/groupDm.js.map +1 -1
- package/dist/routes/inbox.d.ts.map +1 -1
- package/dist/routes/inbox.js +7 -0
- package/dist/routes/inbox.js.map +1 -1
- package/dist/routes/message.d.ts.map +1 -1
- package/dist/routes/message.js +45 -23
- package/dist/routes/message.js.map +1 -1
- package/dist/routes/node.d.ts +4 -0
- package/dist/routes/node.d.ts.map +1 -0
- package/dist/routes/node.js +57 -0
- package/dist/routes/node.js.map +1 -0
- package/dist/routes/thread.d.ts.map +1 -1
- package/dist/routes/thread.js +15 -16
- package/dist/routes/thread.js.map +1 -1
- package/dist/routes/trigger.d.ts +4 -0
- package/dist/routes/trigger.d.ts.map +1 -0
- package/dist/routes/trigger.js +83 -0
- package/dist/routes/trigger.js.map +1 -0
- package/dist/routes/webhookOutbox.d.ts +13 -6
- package/dist/routes/webhookOutbox.d.ts.map +1 -1
- package/dist/routes/webhookOutbox.js +29 -6
- package/dist/routes/webhookOutbox.js.map +1 -1
- package/dist/routes/workspace.d.ts.map +1 -1
- package/dist/routes/workspace.js +90 -0
- package/dist/routes/workspace.js.map +1 -1
- 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;;;;
|
|
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"}
|
package/dist/engine/receipt.js
CHANGED
|
@@ -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
|
|
40
|
-
// clear
|
|
41
|
-
//
|
|
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: '
|
|
46
|
-
.where(and(eq(deliveries.messageId, messageId), eq(deliveries.agentId, agentId), inArray(deliveries.status, ['
|
|
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":"AAAA,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE5D,OAAO,EACL,YAAY,EACZ,QAAQ,EACR,MAAM,EACN,cAAc,EACd,QAAQ,EACR,UAAU,EACV,eAAe,EACf,cAAc,GACf,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAIvD,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,EAAM,EACN,WAAmB,EACnB,SAAiB,EACjB,OAAe;IAEf,iDAAiD;IACjD,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,EAAE;SACnB,MAAM,EAAE;SACR,IAAI,CAAC,QAAQ,CAAC;SACd,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IACjF,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IAEtB,2EAA2E;IAC3E,2EAA2E;IAC3E,4EAA4E;IAC5E,qDAAqD;IACrD,MAAM,CAAC,iBAAiB,CAAC,GAAG,MAAM,EAAE;SACjC,MAAM,CAAC,EAAE,OAAO,EAAE,cAAc,CAAC,OAAO,EAAE,CAAC;SAC3C,IAAI,CAAC,cAAc,CAAC;SACpB,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,cAAc,CAAC,SAAS,EAAE,GAAG,CAAC,SAAS,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IAChG,IAAI,UAAU,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAC5C,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,CAAC,YAAY,CAAC,GAAG,MAAM,EAAE;aAC5B,MAAM,CAAC,EAAE,OAAO,EAAE,cAAc,CAAC,OAAO,EAAE,CAAC;aAC3C,IAAI,CAAC,cAAc,CAAC;aACpB,SAAS,CAAC,eAAe,EAAE,EAAE,CAAC,cAAc,CAAC,cAAc,EAAE,eAAe,CAAC,EAAE,CAAC,CAAC;aACjF,KAAK,CAAC,GAAG,CACR,EAAE,CAAC,eAAe,CAAC,SAAS,EAAE,GAAG,CAAC,SAAS,CAAC,EAC5C,EAAE,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,EACnC,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,CAC9B,CAAC,CAAC;QACL,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IACrC,CAAC;IACD,IAAI,CAAC,UAAU;QAAE,OAAO,IAAI,CAAC;IAE7B,2EAA2E;IAC3E,uDAAuD;IACvD,MAAM,eAAe,CAAC,EAAE,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC;QACrC,mCAAmC;QACnC,OAAO;aACJ,MAAM,CAAC,YAAY,CAAC;aACpB,MAAM,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC;aAC9B,mBAAmB,EAAE;QAExB,
|
|
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":"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"}
|
|
@@ -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"}
|
package/dist/engine/snowflake.js
CHANGED
|
@@ -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":"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"}
|
|
1
|
+
{"version":3,"file":"snowflake.js","sourceRoot":"","sources":["../../src/engine/snowflake.ts"],"names":[],"mappings":"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"}
|