@mastra/spanner 1.9.4 → 1.9.5-alpha.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/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/reference-storage-retention.md +15 -12
- package/dist/index.cjs +103 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +103 -0
- package/dist/index.js.map +1 -1
- package/dist/storage/db/index.d.ts +10 -0
- package/dist/storage/db/index.d.ts.map +1 -1
- package/dist/storage/domains/memory/index.d.ts +8 -1
- package/dist/storage/domains/memory/index.d.ts.map +1 -1
- package/dist/storage/domains/workflows/index.d.ts +8 -1
- package/dist/storage/domains/workflows/index.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -272,6 +272,51 @@ var SpannerDB = class extends MastraBase {
|
|
|
272
272
|
}
|
|
273
273
|
}
|
|
274
274
|
/**
|
|
275
|
+
* Delete up to `limit` rows keyed by `runId` whose epoch-ms `column` is
|
|
276
|
+
* older than `cutoff`. Used to prune the run fencing tables.
|
|
277
|
+
*/
|
|
278
|
+
async pruneRunRows({ tableName, column, cutoff, limit }) {
|
|
279
|
+
const table = quoteIdent(tableName, "table name");
|
|
280
|
+
const col = quoteIdent(column, "column name");
|
|
281
|
+
const runId = quoteIdent("runId", "column name");
|
|
282
|
+
const [rows] = await this.database.run({
|
|
283
|
+
sql: `SELECT ${runId} FROM ${table} WHERE ${col} IS NOT NULL AND ${col} < @cutoff ORDER BY ${col} LIMIT @limit`,
|
|
284
|
+
params: {
|
|
285
|
+
cutoff,
|
|
286
|
+
limit
|
|
287
|
+
},
|
|
288
|
+
types: {
|
|
289
|
+
cutoff: "int64",
|
|
290
|
+
limit: "int64"
|
|
291
|
+
},
|
|
292
|
+
json: true
|
|
293
|
+
});
|
|
294
|
+
const runIds = rows.map((row) => row.runId);
|
|
295
|
+
if (runIds.length === 0) return 0;
|
|
296
|
+
let deleted = 0;
|
|
297
|
+
await this.runWithAbortRetry(async () => {
|
|
298
|
+
await this.database.runTransactionAsync(async (tx) => {
|
|
299
|
+
const [count] = await tx.runUpdate({
|
|
300
|
+
sql: `DELETE FROM ${table} WHERE ${runId} IN UNNEST(@runIds) AND ${col} < @cutoff`,
|
|
301
|
+
params: {
|
|
302
|
+
runIds,
|
|
303
|
+
cutoff
|
|
304
|
+
},
|
|
305
|
+
types: {
|
|
306
|
+
runIds: {
|
|
307
|
+
type: "array",
|
|
308
|
+
child: "string"
|
|
309
|
+
},
|
|
310
|
+
cutoff: "int64"
|
|
311
|
+
}
|
|
312
|
+
});
|
|
313
|
+
await tx.commit();
|
|
314
|
+
deleted = count;
|
|
315
|
+
});
|
|
316
|
+
});
|
|
317
|
+
return deleted;
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
275
320
|
* Determine the primary-key column list for a table. Some core tables (like
|
|
276
321
|
* `mastra_workflow_snapshot`) don't carry a single-column PK in the schema,
|
|
277
322
|
* so we hardcode known composite PKs here.
|
|
@@ -6760,6 +6805,17 @@ var MemorySpanner = class MemorySpanner extends MemoryStorage {
|
|
|
6760
6805
|
TABLE_MESSAGES,
|
|
6761
6806
|
TABLE_RESOURCES
|
|
6762
6807
|
];
|
|
6808
|
+
/**
|
|
6809
|
+
* Tables `prune()` can clean up. Run fences anchor on `retiredAt` (epoch ms), which stays NULL until the
|
|
6810
|
+
* execution holding the fence settles, so a running execution's fence is
|
|
6811
|
+
* never pruned.
|
|
6812
|
+
*/
|
|
6813
|
+
static retentionTables = { runFences: {
|
|
6814
|
+
table: TABLE_MEMORY_RUN_FENCES,
|
|
6815
|
+
column: "retiredAt",
|
|
6816
|
+
indexed: false,
|
|
6817
|
+
anchorType: "epoch-ms"
|
|
6818
|
+
} };
|
|
6763
6819
|
constructor(config) {
|
|
6764
6820
|
super();
|
|
6765
6821
|
const { database, indexes, skipDefaultIndexes, initMode } = resolveSpannerConfig(config);
|
|
@@ -6816,6 +6872,24 @@ var MemorySpanner = class MemorySpanner extends MemoryStorage {
|
|
|
6816
6872
|
await this.db.createIndexes(this.indexes);
|
|
6817
6873
|
}
|
|
6818
6874
|
/** Removes every row from threads/messages/resources and run fence tables. Intended for tests. */
|
|
6875
|
+
async prune(policies, options) {
|
|
6876
|
+
return executeRetentionPrune({
|
|
6877
|
+
domain: "memory",
|
|
6878
|
+
targets: resolveRetentionTargets({
|
|
6879
|
+
policies,
|
|
6880
|
+
descriptor: MemorySpanner.retentionTables,
|
|
6881
|
+
order: ["runFences"]
|
|
6882
|
+
}),
|
|
6883
|
+
options,
|
|
6884
|
+
cutoffFor: (target, now) => retentionCutoffMs(target.policy, now),
|
|
6885
|
+
deleteBatch: (target, cutoff, limit) => this.db.pruneRunRows({
|
|
6886
|
+
tableName: target.table,
|
|
6887
|
+
column: target.column,
|
|
6888
|
+
cutoff,
|
|
6889
|
+
limit
|
|
6890
|
+
})
|
|
6891
|
+
});
|
|
6892
|
+
}
|
|
6819
6893
|
async dangerouslyClearAll() {
|
|
6820
6894
|
await this.db.clearTable({ tableName: TABLE_MESSAGES });
|
|
6821
6895
|
await this.db.clearTable({ tableName: TABLE_THREADS });
|
|
@@ -12478,6 +12552,17 @@ var WorkflowsSpanner = class WorkflowsSpanner extends WorkflowsStorage {
|
|
|
12478
12552
|
skipDefaultIndexes;
|
|
12479
12553
|
indexes;
|
|
12480
12554
|
static MANAGED_TABLES = [TABLE_WORKFLOW_SNAPSHOT];
|
|
12555
|
+
/**
|
|
12556
|
+
* Tables `prune()` can clean up. Run ownership rows anchor on `updatedAt` (epoch ms), which every
|
|
12557
|
+
* claim, renewal and release refreshes, so a live execution's row is never
|
|
12558
|
+
* older than its renew interval.
|
|
12559
|
+
*/
|
|
12560
|
+
static retentionTables = { runOwnership: {
|
|
12561
|
+
table: TABLE_WORKFLOW_RUN_OWNERS,
|
|
12562
|
+
column: "updatedAt",
|
|
12563
|
+
indexed: false,
|
|
12564
|
+
anchorType: "epoch-ms"
|
|
12565
|
+
} };
|
|
12481
12566
|
constructor(config) {
|
|
12482
12567
|
super();
|
|
12483
12568
|
const { database, indexes, skipDefaultIndexes, initMode } = resolveSpannerConfig(config);
|
|
@@ -12610,6 +12695,24 @@ var WorkflowsSpanner = class WorkflowsSpanner extends WorkflowsStorage {
|
|
|
12610
12695
|
await this.db.createIndexes(this.indexes);
|
|
12611
12696
|
}
|
|
12612
12697
|
/** Removes every workflow snapshot and run ownership row. Intended for tests. */
|
|
12698
|
+
async prune(policies, options) {
|
|
12699
|
+
return executeRetentionPrune({
|
|
12700
|
+
domain: "workflows",
|
|
12701
|
+
targets: resolveRetentionTargets({
|
|
12702
|
+
policies,
|
|
12703
|
+
descriptor: WorkflowsSpanner.retentionTables,
|
|
12704
|
+
order: ["runOwnership"]
|
|
12705
|
+
}),
|
|
12706
|
+
options,
|
|
12707
|
+
cutoffFor: (target, now) => retentionCutoffMs(target.policy, now),
|
|
12708
|
+
deleteBatch: (target, cutoff, limit) => this.db.pruneRunRows({
|
|
12709
|
+
tableName: target.table,
|
|
12710
|
+
column: target.column,
|
|
12711
|
+
cutoff,
|
|
12712
|
+
limit
|
|
12713
|
+
})
|
|
12714
|
+
});
|
|
12715
|
+
}
|
|
12613
12716
|
async dangerouslyClearAll() {
|
|
12614
12717
|
await this.db.clearTable({ tableName: TABLE_WORKFLOW_SNAPSHOT });
|
|
12615
12718
|
await this.db.clearTable({ tableName: TABLE_WORKFLOW_RUN_OWNERS });
|