@dbos-inc/dbos-enterprise 0.0.1 → 5.3.2-preview
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/README.md +4 -2
- package/dist/src/conductor/conductor.d.ts +39 -0
- package/dist/src/conductor/conductor.d.ts.map +1 -0
- package/dist/src/conductor/conductor.js +948 -0
- package/dist/src/conductor/conductor.js.map +1 -0
- package/dist/src/conductor/protocol.d.ts +594 -0
- package/dist/src/conductor/protocol.d.ts.map +1 -0
- package/dist/src/conductor/protocol.js +447 -0
- package/dist/src/conductor/protocol.js.map +1 -0
- package/dist/src/export.d.ts +12 -0
- package/dist/src/export.d.ts.map +1 -0
- package/dist/src/export.js +190 -0
- package/dist/src/export.js.map +1 -0
- package/dist/src/fork.d.ts +11 -0
- package/dist/src/fork.d.ts.map +1 -0
- package/dist/src/fork.js +63 -0
- package/dist/src/fork.js.map +1 -0
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +3 -3
- package/dist/src/index.js.map +1 -1
- package/dist/src/observability.d.ts +82 -0
- package/dist/src/observability.d.ts.map +1 -0
- package/dist/src/observability.js +378 -0
- package/dist/src/observability.js.map +1 -0
- package/dist/src/retention.d.ts +49 -0
- package/dist/src/retention.d.ts.map +1 -0
- package/dist/src/retention.js +448 -0
- package/dist/src/retention.js.map +1 -0
- package/package.json +11 -3
- package/dist/src/scratch.d.ts +0 -9
- package/dist/src/scratch.d.ts.map +0 -1
- package/dist/src/scratch.js +0 -15
- package/dist/src/scratch.js.map +0 -1
|
@@ -0,0 +1,448 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Retention and bulk timeout across the whole system database.
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.globalTimeout = exports.garbageCollect = exports.listTimedOutWorkflowIds = exports.collectStatuses = exports.collectPayloads = exports.acquireRetentionLock = exports.DEFAULT_GC_BATCH_SIZE = exports.retentionLockKey = exports.retryOnSerializationError = void 0;
|
|
5
|
+
const dbos_executor_1 = require("@dbos-inc/dbos-sdk/internal/dbos-executor");
|
|
6
|
+
const error_1 = require("@dbos-inc/dbos-sdk/internal/error");
|
|
7
|
+
const system_database_1 = require("@dbos-inc/dbos-sdk/internal/system_database");
|
|
8
|
+
const utils_1 = require("@dbos-inc/dbos-sdk/internal/utils");
|
|
9
|
+
const workflow_1 = require("@dbos-inc/dbos-sdk/internal/workflow");
|
|
10
|
+
/**
|
|
11
|
+
* Bulk maintenance retries these a bounded number of times. 40001 is kept out of core's retryable sets,
|
|
12
|
+
* which feed `dbRetry` and so retry forever; every other path runs READ COMMITTED and never sees it.
|
|
13
|
+
*/
|
|
14
|
+
const SERIALIZATION_SQLSTATE_CODES = new Set([
|
|
15
|
+
'40001', // serialization_failure (MVCC conflict)
|
|
16
|
+
'40P01', // deadlock_detected
|
|
17
|
+
]);
|
|
18
|
+
function isSerializationError(err) {
|
|
19
|
+
for (const e of (0, system_database_1.unwrapErrors)(err)) {
|
|
20
|
+
if ((0, system_database_1.isPgDatabaseError)(e) && SERIALIZATION_SQLSTATE_CODES.has(e.code)) {
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
/** Borrow a connection for a retention round, so the system database's destroy() can cut it. */
|
|
27
|
+
async function borrowRetentionClient(sysdb) {
|
|
28
|
+
if (sysdb.destroyed) {
|
|
29
|
+
throw new Error('System database shutting down');
|
|
30
|
+
}
|
|
31
|
+
const client = await sysdb.connect();
|
|
32
|
+
sysdb.retentionClients.add(client);
|
|
33
|
+
return client;
|
|
34
|
+
}
|
|
35
|
+
/** Return a retention connection, unless destroy() already cut it: a second release would throw. */
|
|
36
|
+
function releaseRetentionClient(sysdb, client) {
|
|
37
|
+
if (sysdb.retentionClients.delete(client)) {
|
|
38
|
+
// No error argument: a genuinely dead connection is still evicted by the pool's own check.
|
|
39
|
+
client.release();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Re-run a batch that lost a deadlock or serialization race. The database already rolled it
|
|
44
|
+
* back, so replaying it is safe.
|
|
45
|
+
*/
|
|
46
|
+
async function retryOnSerializationError(operation) {
|
|
47
|
+
const maxAttempts = 10;
|
|
48
|
+
const maxBackoff = 2.0;
|
|
49
|
+
let backoff = 0.05;
|
|
50
|
+
for (let attempt = 1;; attempt++) {
|
|
51
|
+
try {
|
|
52
|
+
return await operation();
|
|
53
|
+
}
|
|
54
|
+
catch (e) {
|
|
55
|
+
if (!isSerializationError(e)) {
|
|
56
|
+
throw e;
|
|
57
|
+
}
|
|
58
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
59
|
+
if (attempt === maxAttempts) {
|
|
60
|
+
dbos_executor_1.DBOSExecutor.globalInstance?.logger.warn(`Garbage collection failed after ${maxAttempts} attempts: ${message}`);
|
|
61
|
+
throw e;
|
|
62
|
+
}
|
|
63
|
+
// Jittered backoff, so peers that collided do not collide again
|
|
64
|
+
const actualBackoff = backoff * (0.5 + Math.random());
|
|
65
|
+
dbos_executor_1.DBOSExecutor.globalInstance?.logger.warn(`Contention or deadlock detected in workflow garbage collection: ${message}. ` +
|
|
66
|
+
`Retrying in ${actualBackoff.toFixed(2)}s (attempt ${attempt})`);
|
|
67
|
+
await (0, utils_1.sleepms)(actualBackoff * 1000);
|
|
68
|
+
backoff = Math.min(backoff * 2, maxBackoff);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
exports.retryOnSerializationError = retryOnSerializationError;
|
|
73
|
+
/**
|
|
74
|
+
* The pg_try_advisory_lock argument for one schema's retention round: the leading 8 bytes of
|
|
75
|
+
* SHA-256 over a fixed string, read as a signed big-endian 64-bit integer. Separate locks for
|
|
76
|
+
* separate schemas. Every DBOS SDK derives the key this way, so rounds in different languages
|
|
77
|
+
* against one system database contend for the same lock; changing it here changes it everywhere.
|
|
78
|
+
*/
|
|
79
|
+
function retentionLockKey(schemaName) {
|
|
80
|
+
return (0, system_database_1.advisoryLockKey)(`dbos.retention.${schemaName}`);
|
|
81
|
+
}
|
|
82
|
+
exports.retentionLockKey = retentionLockKey;
|
|
83
|
+
// Rows deleted per transaction by garbage collection.
|
|
84
|
+
exports.DEFAULT_GC_BATCH_SIZE = 50_000;
|
|
85
|
+
// Detecting CockroachDB costs a query, so it is resolved once per system database.
|
|
86
|
+
const cockroachBySysDb = new WeakMap();
|
|
87
|
+
/** Whether the system database is CockroachDB. */
|
|
88
|
+
async function isCockroach(sysdb) {
|
|
89
|
+
let cockroach = cockroachBySysDb.get(sysdb);
|
|
90
|
+
if (cockroach === undefined) {
|
|
91
|
+
const client = await sysdb.connect();
|
|
92
|
+
try {
|
|
93
|
+
cockroach = await (0, system_database_1.isCockroachDB)(client);
|
|
94
|
+
}
|
|
95
|
+
finally {
|
|
96
|
+
client.release();
|
|
97
|
+
}
|
|
98
|
+
cockroachBySysDb.set(sysdb, cockroach);
|
|
99
|
+
}
|
|
100
|
+
return cockroach;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Take a database-wide lock for one retention round, returning how to release it, or
|
|
104
|
+
* undefined when another round already holds it. The lock is session-scoped, so a round
|
|
105
|
+
* that crashes releases it. CockroachDB has no advisory locks and always takes it, so it
|
|
106
|
+
* collects unprotected rather than not at all.
|
|
107
|
+
*/
|
|
108
|
+
async function acquireRetentionLock(sysdb) {
|
|
109
|
+
if (await isCockroach(sysdb)) {
|
|
110
|
+
return { release: () => Promise.resolve() };
|
|
111
|
+
}
|
|
112
|
+
const key = retentionLockKey(sysdb.schemaName).toString();
|
|
113
|
+
// The round holds this connection until it ends: releasing it would drop the lock.
|
|
114
|
+
const client = await borrowRetentionClient(sysdb);
|
|
115
|
+
let acquired = false;
|
|
116
|
+
try {
|
|
117
|
+
const { rows } = await client.query('SELECT pg_try_advisory_lock($1) AS locked', [key]);
|
|
118
|
+
acquired = rows[0]?.locked === true;
|
|
119
|
+
}
|
|
120
|
+
catch (e) {
|
|
121
|
+
releaseRetentionClient(sysdb, client);
|
|
122
|
+
throw e;
|
|
123
|
+
}
|
|
124
|
+
if (!acquired) {
|
|
125
|
+
releaseRetentionClient(sysdb, client);
|
|
126
|
+
return undefined;
|
|
127
|
+
}
|
|
128
|
+
return {
|
|
129
|
+
release: async () => {
|
|
130
|
+
// Already cut by destroy(): the session is gone and took the lock with it.
|
|
131
|
+
if (!sysdb.retentionClients.has(client)) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
try {
|
|
135
|
+
// Explicit, since releasing the client only returns the session to the pool.
|
|
136
|
+
const { rows } = await client.query('SELECT pg_advisory_unlock($1) AS released', [key]);
|
|
137
|
+
if (rows[0]?.released !== true) {
|
|
138
|
+
// False means this session no longer holds it, which a transaction-pooling proxy
|
|
139
|
+
// causes by switching backends.
|
|
140
|
+
sysdb.logger.warn('Could not release the retention lock: this session no longer holds it. Retention will ' +
|
|
141
|
+
'not proceed until the lock is released, which happens when the holding backend closes. ' +
|
|
142
|
+
'A transaction-pooling proxy in front of Postgres causes this; run DBOS through a ' +
|
|
143
|
+
'session-pooled or direct connection.');
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
finally {
|
|
147
|
+
releaseRetentionClient(sysdb, client);
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
exports.acquireRetentionLock = acquireRetentionLock;
|
|
153
|
+
/** VACUUM the tables a sweep dirtied. No-op where there is no autovacuum to outrun. */
|
|
154
|
+
async function vacuumTables(sysdb, tables) {
|
|
155
|
+
if (await isCockroach(sysdb)) {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
const client = await borrowRetentionClient(sysdb);
|
|
159
|
+
let notices = [];
|
|
160
|
+
const onNotice = (notice) => notices.push(notice.message ?? '');
|
|
161
|
+
client.on('notice', onNotice);
|
|
162
|
+
try {
|
|
163
|
+
for (const table of tables) {
|
|
164
|
+
// Per table, so one refusal does not skip the rest.
|
|
165
|
+
notices = [];
|
|
166
|
+
try {
|
|
167
|
+
await client.query(`VACUUM (INDEX_CLEANUP ON, TRUNCATE OFF, ANALYZE) "${sysdb.schemaName}"."${table}"`);
|
|
168
|
+
}
|
|
169
|
+
catch (e) {
|
|
170
|
+
if (!sysdb.retentionClients.has(client)) {
|
|
171
|
+
throw e;
|
|
172
|
+
}
|
|
173
|
+
sysdb.logger.warn(`Payload retention could not vacuum ${table}: ${e.message}`);
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
// A refused or stalled VACUUM does not raise, it says so in a notice; a successful
|
|
177
|
+
// one is silent, so anything here is worth surfacing.
|
|
178
|
+
for (const notice of notices) {
|
|
179
|
+
sysdb.logger.warn(`Payload retention vacuuming ${table}: ${notice}`);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
finally {
|
|
184
|
+
client.removeListener('notice', onNotice);
|
|
185
|
+
releaseRetentionClient(sysdb, client);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
/** Delete one payload table's orphans below the cutoff, one batch per transaction. */
|
|
189
|
+
async function collectPayloadTable(sysdb, table, cutoff, batchSize) {
|
|
190
|
+
// A payload below the cutoff belongs to a workflow created before it, so the status side
|
|
191
|
+
// is the few such rows still present, not the whole table.
|
|
192
|
+
const orphaned = `NOT EXISTS (
|
|
193
|
+
SELECT 1 FROM "${sysdb.schemaName}".workflow_status ws
|
|
194
|
+
WHERE ws.workflow_uuid = t.workflow_uuid AND ws.created_at < $1
|
|
195
|
+
)`;
|
|
196
|
+
// Seed from the oldest row in range.
|
|
197
|
+
const oldest = await retryOnSerializationError(async () => {
|
|
198
|
+
const { rows } = await sysdb.pool.query(`SELECT retention_timestamp
|
|
199
|
+
FROM "${sysdb.schemaName}".${table}
|
|
200
|
+
WHERE retention_timestamp < $1
|
|
201
|
+
ORDER BY retention_timestamp
|
|
202
|
+
LIMIT 1`, [cutoff]);
|
|
203
|
+
// retention_timestamp is a bigint, so node-postgres hands it back as a string.
|
|
204
|
+
return rows.length > 0 ? Number(rows[0].retention_timestamp) : undefined;
|
|
205
|
+
});
|
|
206
|
+
if (oldest === undefined) {
|
|
207
|
+
return 0;
|
|
208
|
+
}
|
|
209
|
+
let total = 0;
|
|
210
|
+
let watermark = oldest - 1;
|
|
211
|
+
for (;;) {
|
|
212
|
+
const batch = await retryOnSerializationError(async () => {
|
|
213
|
+
// Borrowed rather than pool.query'd: that releases with the error, which discards the
|
|
214
|
+
// connection on a deadlock, so the retry wrapping this would churn the pool per batch.
|
|
215
|
+
const client = await borrowRetentionClient(sysdb);
|
|
216
|
+
try {
|
|
217
|
+
// Batches are cut by candidate count, so rows spared by the anti-join only thin one
|
|
218
|
+
// out; they are re-checked next round.
|
|
219
|
+
const { rows } = await client.query(`SELECT retention_timestamp
|
|
220
|
+
FROM "${sysdb.schemaName}".${table}
|
|
221
|
+
WHERE retention_timestamp < $1 AND retention_timestamp > $2
|
|
222
|
+
ORDER BY retention_timestamp
|
|
223
|
+
LIMIT 1 OFFSET ${batchSize - 1}`, [cutoff, watermark]);
|
|
224
|
+
const step = rows.length > 0 ? Number(rows[0].retention_timestamp) : undefined;
|
|
225
|
+
const params = [cutoff, watermark];
|
|
226
|
+
// Timestamp ties may push the batch slightly over batchSize, but never split across two.
|
|
227
|
+
const upperBound = step === undefined ? '' : `AND t.retention_timestamp <= $${params.push(step)} `;
|
|
228
|
+
const result = await client.query(`DELETE FROM "${sysdb.schemaName}".${table} t
|
|
229
|
+
WHERE t.retention_timestamp < $1 AND t.retention_timestamp > $2 ${upperBound}AND ${orphaned}`, params);
|
|
230
|
+
return { step, deleted: result.rowCount ?? 0 };
|
|
231
|
+
}
|
|
232
|
+
finally {
|
|
233
|
+
releaseRetentionClient(sysdb, client);
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
total += batch.deleted;
|
|
237
|
+
if (batch.step === undefined) {
|
|
238
|
+
return total;
|
|
239
|
+
}
|
|
240
|
+
watermark = batch.step;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Delete payload and step rows below the cutoff whose workflow is gone, returning the count
|
|
245
|
+
* removed from each table. Runs after the status sweep, whose orphans all fall in range:
|
|
246
|
+
* every payload is stamped no later than the completion that made the row collectable.
|
|
247
|
+
*/
|
|
248
|
+
async function collectPayloads(sysdb, cutoff, batchSize = exports.DEFAULT_GC_BATCH_SIZE) {
|
|
249
|
+
// A NaN survives a bare `< 1` test and would only fail once it reached SQL.
|
|
250
|
+
if (!Number.isInteger(batchSize) || batchSize < 1) {
|
|
251
|
+
throw new error_1.DBOSError(`batchSize must be a positive integer, got ${batchSize}`);
|
|
252
|
+
}
|
|
253
|
+
const tables = ['workflow_input', 'workflow_output', 'operation_outputs'];
|
|
254
|
+
// To optimize performance, vacuum payload tables both before and after collecting them.
|
|
255
|
+
await vacuumTables(sysdb, ['workflow_status', ...tables]);
|
|
256
|
+
// One connection per concurrent sweep, on top of the one the retention lock holds for the
|
|
257
|
+
// whole round. A pool too small for all three runs them sequentially rather than leaving
|
|
258
|
+
// sweeps waiting on a connection that only the round itself would free.
|
|
259
|
+
const poolMax = sysdb.pool.options.max ?? system_database_1.DEFAULT_POOL_SIZE;
|
|
260
|
+
const concurrency = Math.max(1, Math.min(tables.length, poolMax - 1));
|
|
261
|
+
const deleted = new Array(tables.length).fill(0);
|
|
262
|
+
const failures = [];
|
|
263
|
+
let next = 0;
|
|
264
|
+
const sweep = async () => {
|
|
265
|
+
for (;;) {
|
|
266
|
+
const i = next++;
|
|
267
|
+
if (i >= tables.length)
|
|
268
|
+
return;
|
|
269
|
+
try {
|
|
270
|
+
deleted[i] = await collectPayloadTable(sysdb, tables[i], cutoff, batchSize);
|
|
271
|
+
}
|
|
272
|
+
catch (e) {
|
|
273
|
+
failures.push(e);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
};
|
|
277
|
+
await Promise.all(Array.from({ length: concurrency }, () => sweep()));
|
|
278
|
+
// Only the first can be thrown, so the rest would otherwise be lost.
|
|
279
|
+
for (const extra of failures.slice(1)) {
|
|
280
|
+
sysdb.logger.warn(`Payload retention sweep also failed: ${extra instanceof Error ? extra.message : String(extra)}`);
|
|
281
|
+
}
|
|
282
|
+
if (failures.length > 0) {
|
|
283
|
+
throw failures[0];
|
|
284
|
+
}
|
|
285
|
+
await vacuumTables(sysdb, tables);
|
|
286
|
+
sysdb.logger.debug(`Payload retention deleted ${deleted[0]} inputs, ${deleted[1]} outputs, and ${deleted[2]} steps`);
|
|
287
|
+
return deleted;
|
|
288
|
+
}
|
|
289
|
+
exports.collectPayloads = collectPayloads;
|
|
290
|
+
/**
|
|
291
|
+
* Rows garbage collection may delete. completed_at is set on every terminal transition and
|
|
292
|
+
* cleared on resume, so one predicate covers eligibility: in-flight rows hold NULL and never
|
|
293
|
+
* compare true. Unscoped by application: retention is system-wide.
|
|
294
|
+
*/
|
|
295
|
+
function gcFilter(sysdb, cutoffEpochTimestampMs, params) {
|
|
296
|
+
params.push(cutoffEpochTimestampMs);
|
|
297
|
+
return `completed_at < $${params.length}`;
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Delete one batch, returning the watermark to resume from, or undefined once the last one ran.
|
|
301
|
+
* The delete is its own transaction; it re-checks the filter, so it needs no snapshot shared
|
|
302
|
+
* with the select that bounds it.
|
|
303
|
+
*/
|
|
304
|
+
async function collectStatusBatch(sysdb, cutoffEpochTimestampMs, batchSize, watermark) {
|
|
305
|
+
// Borrowed rather than pool.query'd: that releases with the error, which discards the
|
|
306
|
+
// connection on a deadlock, so the retry wrapping this would churn the pool per batch.
|
|
307
|
+
const client = await borrowRetentionClient(sysdb);
|
|
308
|
+
try {
|
|
309
|
+
// The batchSize-th oldest eligible row above the watermark bounds this range
|
|
310
|
+
const stepParams = [];
|
|
311
|
+
const stepScope = gcFilter(sysdb, cutoffEpochTimestampMs, stepParams);
|
|
312
|
+
stepParams.push(watermark);
|
|
313
|
+
const stepResult = await client.query(`SELECT completed_at
|
|
314
|
+
FROM "${sysdb.schemaName}".workflow_status
|
|
315
|
+
WHERE ${stepScope} AND completed_at > $${stepParams.length}
|
|
316
|
+
ORDER BY completed_at
|
|
317
|
+
LIMIT 1 OFFSET ${batchSize - 1}`, stepParams);
|
|
318
|
+
// completed_at is a bigint, so node-postgres hands it back as a string.
|
|
319
|
+
const step = stepResult.rows.length > 0 ? Number(stepResult.rows[0].completed_at) : undefined;
|
|
320
|
+
const deleteParams = [];
|
|
321
|
+
let deleteScope = gcFilter(sysdb, cutoffEpochTimestampMs, deleteParams);
|
|
322
|
+
if (step !== undefined) {
|
|
323
|
+
// Inclusive upper bound: completed_at ties may push a batch over batchSize, but never split across two.
|
|
324
|
+
deleteParams.push(watermark, step);
|
|
325
|
+
deleteScope = `${deleteScope} AND completed_at > $${deleteParams.length - 1} AND completed_at <= $${deleteParams.length}`;
|
|
326
|
+
}
|
|
327
|
+
// The final batch drops the watermark: unbounded, since an import can land a
|
|
328
|
+
// completed_at below it mid-pass.
|
|
329
|
+
await client.query(`DELETE FROM "${sysdb.schemaName}".workflow_status WHERE ${deleteScope}`, deleteParams);
|
|
330
|
+
return step;
|
|
331
|
+
}
|
|
332
|
+
finally {
|
|
333
|
+
releaseRetentionClient(sysdb, client);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Delete old terminal workflows throughout the system database, returning the cutoff
|
|
338
|
+
* actually used, or undefined when there is nothing to collect.
|
|
339
|
+
*
|
|
340
|
+
* Conductor sends cleared retention thresholds as JSON null, so every param is nullish.
|
|
341
|
+
*/
|
|
342
|
+
async function collectStatuses(sysdb, cutoffEpochTimestampMs, rowsThreshold, options = {}) {
|
|
343
|
+
const batchSize = options.batchSize ?? exports.DEFAULT_GC_BATCH_SIZE;
|
|
344
|
+
// A NaN survives a bare `< 1` test and would only fail once it reached SQL, leaving GC half-applied.
|
|
345
|
+
if (!Number.isInteger(batchSize) || batchSize < 1) {
|
|
346
|
+
throw new error_1.DBOSError(`batchSize must be a positive integer, got ${batchSize}`);
|
|
347
|
+
}
|
|
348
|
+
if (rowsThreshold !== undefined && rowsThreshold !== null) {
|
|
349
|
+
// The completed_at of the rowsThreshold newest completed row
|
|
350
|
+
const result = await retryOnSerializationError(() => sysdb.pool.query(`SELECT completed_at
|
|
351
|
+
FROM "${sysdb.schemaName}".workflow_status
|
|
352
|
+
WHERE completed_at IS NOT NULL
|
|
353
|
+
ORDER BY completed_at DESC
|
|
354
|
+
LIMIT 1 OFFSET $1`, [rowsThreshold - 1]));
|
|
355
|
+
if (result.rows.length > 0) {
|
|
356
|
+
const rowsBasedCutoff = Number(result.rows[0].completed_at);
|
|
357
|
+
// Use the more restrictive cutoff (higher timestamp = more recent = more deletion)
|
|
358
|
+
if (cutoffEpochTimestampMs === undefined ||
|
|
359
|
+
cutoffEpochTimestampMs === null ||
|
|
360
|
+
rowsBasedCutoff > cutoffEpochTimestampMs) {
|
|
361
|
+
cutoffEpochTimestampMs = rowsBasedCutoff;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
if (cutoffEpochTimestampMs === undefined || cutoffEpochTimestampMs === null) {
|
|
366
|
+
return undefined;
|
|
367
|
+
}
|
|
368
|
+
// Narrowed to a constant so the closures below keep it.
|
|
369
|
+
const cutoff = cutoffEpochTimestampMs;
|
|
370
|
+
// Advance a completed_at watermark, one committed transaction per batch, so a long
|
|
371
|
+
// history neither deletes in one transaction nor rescans what it already deleted.
|
|
372
|
+
const oldest = await retryOnSerializationError(async () => {
|
|
373
|
+
const params = [];
|
|
374
|
+
const scope = gcFilter(sysdb, cutoff, params);
|
|
375
|
+
const { rows } = await sysdb.pool.query(`SELECT completed_at
|
|
376
|
+
FROM "${sysdb.schemaName}".workflow_status
|
|
377
|
+
WHERE ${scope}
|
|
378
|
+
ORDER BY completed_at
|
|
379
|
+
LIMIT 1`, params);
|
|
380
|
+
return rows.length > 0 ? Number(rows[0].completed_at) : undefined;
|
|
381
|
+
});
|
|
382
|
+
let watermark = oldest === undefined ? 0 : oldest - 1;
|
|
383
|
+
for (;;) {
|
|
384
|
+
const next = await retryOnSerializationError(() => collectStatusBatch(sysdb, cutoff, batchSize, watermark));
|
|
385
|
+
// Fewer than a full batch remained, so that delete took the rest.
|
|
386
|
+
if (next === undefined)
|
|
387
|
+
return cutoff;
|
|
388
|
+
watermark = next;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
exports.collectStatuses = collectStatuses;
|
|
392
|
+
/**
|
|
393
|
+
* IDs of this application's in-flight workflows created at or before the cutoff.
|
|
394
|
+
* Claiming-scoped, so an upgrade still times out its own unclaimed workflows.
|
|
395
|
+
*/
|
|
396
|
+
async function listTimedOutWorkflowIds(sysdb, cutoffEpochTimestampMs) {
|
|
397
|
+
return (0, system_database_1.withDbRetry)(async () => {
|
|
398
|
+
const params = [
|
|
399
|
+
cutoffEpochTimestampMs,
|
|
400
|
+
workflow_1.StatusString.PENDING,
|
|
401
|
+
workflow_1.StatusString.ENQUEUED,
|
|
402
|
+
workflow_1.StatusString.DELAYED,
|
|
403
|
+
];
|
|
404
|
+
const scope = sysdb.appNameFilter('application_name', sysdb.appName, params);
|
|
405
|
+
const { rows } = await sysdb.pool.query(`SELECT workflow_uuid
|
|
406
|
+
FROM "${sysdb.schemaName}".workflow_status
|
|
407
|
+
WHERE created_at <= $1
|
|
408
|
+
AND status IN ($2, $3, $4)
|
|
409
|
+
AND ${scope}`, params);
|
|
410
|
+
return rows.map((row) => row.workflow_uuid);
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
exports.listTimedOutWorkflowIds = listTimedOutWorkflowIds;
|
|
414
|
+
/** Enforce retention across the entire system database. */
|
|
415
|
+
async function garbageCollect(sysdb, cutoffEpochTimestampMs, rowsThreshold, options = {}) {
|
|
416
|
+
if ((cutoffEpochTimestampMs === undefined || cutoffEpochTimestampMs === null) &&
|
|
417
|
+
(rowsThreshold === undefined || rowsThreshold === null)) {
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
420
|
+
const lock = await acquireRetentionLock(sysdb);
|
|
421
|
+
if (!lock) {
|
|
422
|
+
sysdb.logger.warn('Skipping retention: another round is already running against this system database.');
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
try {
|
|
426
|
+
// Both sweeps take the same batch size, and both default it the same way when unset.
|
|
427
|
+
const batchSize = options.batchSize ?? undefined;
|
|
428
|
+
const cutoff = await collectStatuses(sysdb, cutoffEpochTimestampMs, rowsThreshold, { batchSize });
|
|
429
|
+
if (cutoff === undefined) {
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
// Strictly after the status sweep: the payload sweep only takes orphans, so this round's
|
|
433
|
+
// are only visible to it once that sweep has committed.
|
|
434
|
+
await collectPayloads(sysdb, cutoff, batchSize);
|
|
435
|
+
}
|
|
436
|
+
finally {
|
|
437
|
+
await lock.release();
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
exports.garbageCollect = garbageCollect;
|
|
441
|
+
async function globalTimeout(sysdb, cutoffEpochTimestampMs) {
|
|
442
|
+
// IDs only, so a bulk timeout does not deserialize every row's inputs and outputs.
|
|
443
|
+
for (const workflowID of await listTimedOutWorkflowIds(sysdb, cutoffEpochTimestampMs)) {
|
|
444
|
+
await sysdb.cancelWorkflows([workflowID]);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
exports.globalTimeout = globalTimeout;
|
|
448
|
+
//# sourceMappingURL=retention.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retention.js","sourceRoot":"","sources":["../../src/retention.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dbos-inc/dbos-enterprise",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.3.2-preview",
|
|
4
4
|
"description": "Enterprise extension for DBOS Transact",
|
|
5
5
|
"license": "DBOS Conductor Software License (https://www.dbos.dev/conductor-license)",
|
|
6
6
|
"repository": {
|
|
@@ -27,11 +27,15 @@
|
|
|
27
27
|
"build": "tsc --build",
|
|
28
28
|
"prepack": "rm -rf dist && npm run build",
|
|
29
29
|
"lint": "eslint .",
|
|
30
|
-
"test": "jest --detectOpenHandles
|
|
30
|
+
"test": "jest --detectOpenHandles",
|
|
31
31
|
"check:package": "npm run build && publint && attw --pack .",
|
|
32
32
|
"release": "node publish/make_release.mjs",
|
|
33
33
|
"prepare": "husky"
|
|
34
34
|
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"serialize-error": "^8.1.0",
|
|
37
|
+
"ws": "^8.18.1"
|
|
38
|
+
},
|
|
35
39
|
"peerDependencies": {
|
|
36
40
|
"@dbos-inc/dbos-sdk": "*"
|
|
37
41
|
},
|
|
@@ -41,16 +45,20 @@
|
|
|
41
45
|
"@eslint/js": "^9.22.0",
|
|
42
46
|
"@types/jest": "^30.0.0",
|
|
43
47
|
"@types/node": "^20.19.1",
|
|
48
|
+
"@types/pg": "^8.11.2",
|
|
49
|
+
"@types/ws": "^8.18.0",
|
|
44
50
|
"eslint": "^9.22.0",
|
|
45
51
|
"globals": "^16.0.0",
|
|
46
52
|
"husky": "^9.1.7",
|
|
47
53
|
"jest": "^29.7.0",
|
|
48
54
|
"lint-staged": "^15.4.3",
|
|
55
|
+
"pg": "^8.11.3",
|
|
49
56
|
"prettier": "^3.4.2",
|
|
50
57
|
"publint": "^0.3.21",
|
|
51
58
|
"ts-jest": "^29.2.4",
|
|
52
59
|
"typescript": "^5.4.5",
|
|
53
|
-
"typescript-eslint": "^8.26.1"
|
|
60
|
+
"typescript-eslint": "^8.26.1",
|
|
61
|
+
"zod": "^4.3.6"
|
|
54
62
|
},
|
|
55
63
|
"lint-staged": {
|
|
56
64
|
"*.{js,cjs,mjs,ts,json,md,yml}": "prettier --write"
|
package/dist/src/scratch.d.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
export interface ExecutorInfo {
|
|
2
|
-
appName: string | undefined;
|
|
3
|
-
appVersion: string;
|
|
4
|
-
executorID: string;
|
|
5
|
-
dbosVersion: string;
|
|
6
|
-
}
|
|
7
|
-
/** Report the identity core assigns this process at launch. */
|
|
8
|
-
export declare function describeExecutor(): ExecutorInfo;
|
|
9
|
-
//# sourceMappingURL=scratch.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"scratch.d.ts","sourceRoot":"","sources":["../../src/scratch.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,+DAA+D;AAC/D,wBAAgB,gBAAgB,IAAI,YAAY,CAO/C"}
|
package/dist/src/scratch.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
// Scratch code proving the package can reach core internals. Delete when real code lands.
|
|
3
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.describeExecutor = describeExecutor;
|
|
5
|
-
const utils_1 = require("@dbos-inc/dbos-sdk/internal/utils");
|
|
6
|
-
/** Report the identity core assigns this process at launch. */
|
|
7
|
-
function describeExecutor() {
|
|
8
|
-
return {
|
|
9
|
-
appName: utils_1.globalParams.appName,
|
|
10
|
-
appVersion: utils_1.globalParams.appVersion,
|
|
11
|
-
executorID: utils_1.globalParams.executorID,
|
|
12
|
-
dbosVersion: utils_1.globalParams.dbosVersion,
|
|
13
|
-
};
|
|
14
|
-
}
|
|
15
|
-
//# sourceMappingURL=scratch.js.map
|
package/dist/src/scratch.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"scratch.js","sourceRoot":"","sources":["../../src/scratch.ts"],"names":[],"mappings":";AAAA,0FAA0F;;AAY1F,4CAOC;AAjBD,6DAAiE;AASjE,+DAA+D;AAC/D,SAAgB,gBAAgB;IAC9B,OAAO;QACL,OAAO,EAAE,oBAAY,CAAC,OAAO;QAC7B,UAAU,EAAE,oBAAY,CAAC,UAAU;QACnC,UAAU,EAAE,oBAAY,CAAC,UAAU;QACnC,WAAW,EAAE,oBAAY,CAAC,WAAW;KACtC,CAAC;AACJ,CAAC"}
|