@mastra/spanner 1.9.4 → 1.9.5
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 +5 -5
package/dist/docs/SKILL.md
CHANGED
|
@@ -12,18 +12,21 @@ Retention covers **growth tables** only: tables that accumulate rows unbounded a
|
|
|
12
12
|
|
|
13
13
|
Storage adapters use the shared core retention contract for `prune()`, or a database-native mechanism when that better matches the backend.
|
|
14
14
|
|
|
15
|
-
| Adapter
|
|
16
|
-
|
|
|
17
|
-
| libSQL
|
|
18
|
-
| PostgreSQL
|
|
19
|
-
| MongoDB
|
|
20
|
-
| DuckDB
|
|
21
|
-
| MySQL
|
|
22
|
-
| Microsoft SQL Server
|
|
23
|
-
| Oracle Database
|
|
24
|
-
| Amazon Aurora DSQL
|
|
25
|
-
| Google Cloud Spanner
|
|
26
|
-
|
|
|
15
|
+
| Adapter | Mechanism | Retention support |
|
|
16
|
+
| --------------------------------- | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
17
|
+
| libSQL | `prune()` | All supported growth domains |
|
|
18
|
+
| PostgreSQL | `prune()` | All supported growth domains. vNext observability drops expired partitions or chunks |
|
|
19
|
+
| MongoDB | `prune()` or native TTL | All supported growth domains. Native TTL indexes are also available |
|
|
20
|
+
| DuckDB | `prune()` | Observability spans, metrics, logs, scores, and feedback |
|
|
21
|
+
| MySQL | `prune()` | Observability spans, durable agent run fencing (`runOwnership`, `runFences`) |
|
|
22
|
+
| Microsoft SQL Server | `prune()` | Observability spans, durable agent run fencing (`runOwnership`, `runFences`) |
|
|
23
|
+
| Oracle Database | `prune()` | Observability spans and logs, durable agent run fencing (`runOwnership`, `runFences`) |
|
|
24
|
+
| Amazon Aurora DSQL | `prune()` | Observability spans, durable agent run fencing (`runOwnership`, `runFences`) |
|
|
25
|
+
| Google Cloud Spanner | `prune()` | Observability spans, plus metrics when metrics storage is enabled. Durable agent run fencing (`runOwnership`, `runFences`) |
|
|
26
|
+
| DynamoDB | `prune()` | Durable agent run fencing (`runOwnership`, `runFences`) |
|
|
27
|
+
| Convex | `prune()` | Durable agent run fencing (`runOwnership`, `runFences`). Redeploy your Convex functions after upgrading |
|
|
28
|
+
| Cloudflare D1 and Durable Objects | `prune()` | Durable agent run fencing (`runOwnership`, `runFences`) |
|
|
29
|
+
| ClickHouse | Native TTL | Observability spans, metrics, logs, scores, and feedback. When all five signals have finite retention, deletion-request records expire after the longest signal retention plus 30 days |
|
|
27
30
|
|
|
28
31
|
## Storage-specific maintenance
|
|
29
32
|
|
package/dist/index.cjs
CHANGED
|
@@ -273,6 +273,51 @@ var SpannerDB = class extends _mastra_core_base.MastraBase {
|
|
|
273
273
|
}
|
|
274
274
|
}
|
|
275
275
|
/**
|
|
276
|
+
* Delete up to `limit` rows keyed by `runId` whose epoch-ms `column` is
|
|
277
|
+
* older than `cutoff`. Used to prune the run fencing tables.
|
|
278
|
+
*/
|
|
279
|
+
async pruneRunRows({ tableName, column, cutoff, limit }) {
|
|
280
|
+
const table = quoteIdent(tableName, "table name");
|
|
281
|
+
const col = quoteIdent(column, "column name");
|
|
282
|
+
const runId = quoteIdent("runId", "column name");
|
|
283
|
+
const [rows] = await this.database.run({
|
|
284
|
+
sql: `SELECT ${runId} FROM ${table} WHERE ${col} IS NOT NULL AND ${col} < @cutoff ORDER BY ${col} LIMIT @limit`,
|
|
285
|
+
params: {
|
|
286
|
+
cutoff,
|
|
287
|
+
limit
|
|
288
|
+
},
|
|
289
|
+
types: {
|
|
290
|
+
cutoff: "int64",
|
|
291
|
+
limit: "int64"
|
|
292
|
+
},
|
|
293
|
+
json: true
|
|
294
|
+
});
|
|
295
|
+
const runIds = rows.map((row) => row.runId);
|
|
296
|
+
if (runIds.length === 0) return 0;
|
|
297
|
+
let deleted = 0;
|
|
298
|
+
await this.runWithAbortRetry(async () => {
|
|
299
|
+
await this.database.runTransactionAsync(async (tx) => {
|
|
300
|
+
const [count] = await tx.runUpdate({
|
|
301
|
+
sql: `DELETE FROM ${table} WHERE ${runId} IN UNNEST(@runIds) AND ${col} < @cutoff`,
|
|
302
|
+
params: {
|
|
303
|
+
runIds,
|
|
304
|
+
cutoff
|
|
305
|
+
},
|
|
306
|
+
types: {
|
|
307
|
+
runIds: {
|
|
308
|
+
type: "array",
|
|
309
|
+
child: "string"
|
|
310
|
+
},
|
|
311
|
+
cutoff: "int64"
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
await tx.commit();
|
|
315
|
+
deleted = count;
|
|
316
|
+
});
|
|
317
|
+
});
|
|
318
|
+
return deleted;
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
276
321
|
* Determine the primary-key column list for a table. Some core tables (like
|
|
277
322
|
* `mastra_workflow_snapshot`) don't carry a single-column PK in the schema,
|
|
278
323
|
* so we hardcode known composite PKs here.
|
|
@@ -6761,6 +6806,17 @@ var MemorySpanner = class MemorySpanner extends _mastra_core_storage.MemoryStora
|
|
|
6761
6806
|
_mastra_core_storage.TABLE_MESSAGES,
|
|
6762
6807
|
_mastra_core_storage.TABLE_RESOURCES
|
|
6763
6808
|
];
|
|
6809
|
+
/**
|
|
6810
|
+
* Tables `prune()` can clean up. Run fences anchor on `retiredAt` (epoch ms), which stays NULL until the
|
|
6811
|
+
* execution holding the fence settles, so a running execution's fence is
|
|
6812
|
+
* never pruned.
|
|
6813
|
+
*/
|
|
6814
|
+
static retentionTables = { runFences: {
|
|
6815
|
+
table: _mastra_core_storage.TABLE_MEMORY_RUN_FENCES,
|
|
6816
|
+
column: "retiredAt",
|
|
6817
|
+
indexed: false,
|
|
6818
|
+
anchorType: "epoch-ms"
|
|
6819
|
+
} };
|
|
6764
6820
|
constructor(config) {
|
|
6765
6821
|
super();
|
|
6766
6822
|
const { database, indexes, skipDefaultIndexes, initMode } = resolveSpannerConfig(config);
|
|
@@ -6817,6 +6873,24 @@ var MemorySpanner = class MemorySpanner extends _mastra_core_storage.MemoryStora
|
|
|
6817
6873
|
await this.db.createIndexes(this.indexes);
|
|
6818
6874
|
}
|
|
6819
6875
|
/** Removes every row from threads/messages/resources and run fence tables. Intended for tests. */
|
|
6876
|
+
async prune(policies, options) {
|
|
6877
|
+
return (0, _mastra_core_storage.executeRetentionPrune)({
|
|
6878
|
+
domain: "memory",
|
|
6879
|
+
targets: (0, _mastra_core_storage.resolveRetentionTargets)({
|
|
6880
|
+
policies,
|
|
6881
|
+
descriptor: MemorySpanner.retentionTables,
|
|
6882
|
+
order: ["runFences"]
|
|
6883
|
+
}),
|
|
6884
|
+
options,
|
|
6885
|
+
cutoffFor: (target, now) => (0, _mastra_core_storage.retentionCutoffMs)(target.policy, now),
|
|
6886
|
+
deleteBatch: (target, cutoff, limit) => this.db.pruneRunRows({
|
|
6887
|
+
tableName: target.table,
|
|
6888
|
+
column: target.column,
|
|
6889
|
+
cutoff,
|
|
6890
|
+
limit
|
|
6891
|
+
})
|
|
6892
|
+
});
|
|
6893
|
+
}
|
|
6820
6894
|
async dangerouslyClearAll() {
|
|
6821
6895
|
await this.db.clearTable({ tableName: _mastra_core_storage.TABLE_MESSAGES });
|
|
6822
6896
|
await this.db.clearTable({ tableName: _mastra_core_storage.TABLE_THREADS });
|
|
@@ -12479,6 +12553,17 @@ var WorkflowsSpanner = class WorkflowsSpanner extends _mastra_core_storage.Workf
|
|
|
12479
12553
|
skipDefaultIndexes;
|
|
12480
12554
|
indexes;
|
|
12481
12555
|
static MANAGED_TABLES = [_mastra_core_storage.TABLE_WORKFLOW_SNAPSHOT];
|
|
12556
|
+
/**
|
|
12557
|
+
* Tables `prune()` can clean up. Run ownership rows anchor on `updatedAt` (epoch ms), which every
|
|
12558
|
+
* claim, renewal and release refreshes, so a live execution's row is never
|
|
12559
|
+
* older than its renew interval.
|
|
12560
|
+
*/
|
|
12561
|
+
static retentionTables = { runOwnership: {
|
|
12562
|
+
table: _mastra_core_storage.TABLE_WORKFLOW_RUN_OWNERS,
|
|
12563
|
+
column: "updatedAt",
|
|
12564
|
+
indexed: false,
|
|
12565
|
+
anchorType: "epoch-ms"
|
|
12566
|
+
} };
|
|
12482
12567
|
constructor(config) {
|
|
12483
12568
|
super();
|
|
12484
12569
|
const { database, indexes, skipDefaultIndexes, initMode } = resolveSpannerConfig(config);
|
|
@@ -12611,6 +12696,24 @@ var WorkflowsSpanner = class WorkflowsSpanner extends _mastra_core_storage.Workf
|
|
|
12611
12696
|
await this.db.createIndexes(this.indexes);
|
|
12612
12697
|
}
|
|
12613
12698
|
/** Removes every workflow snapshot and run ownership row. Intended for tests. */
|
|
12699
|
+
async prune(policies, options) {
|
|
12700
|
+
return (0, _mastra_core_storage.executeRetentionPrune)({
|
|
12701
|
+
domain: "workflows",
|
|
12702
|
+
targets: (0, _mastra_core_storage.resolveRetentionTargets)({
|
|
12703
|
+
policies,
|
|
12704
|
+
descriptor: WorkflowsSpanner.retentionTables,
|
|
12705
|
+
order: ["runOwnership"]
|
|
12706
|
+
}),
|
|
12707
|
+
options,
|
|
12708
|
+
cutoffFor: (target, now) => (0, _mastra_core_storage.retentionCutoffMs)(target.policy, now),
|
|
12709
|
+
deleteBatch: (target, cutoff, limit) => this.db.pruneRunRows({
|
|
12710
|
+
tableName: target.table,
|
|
12711
|
+
column: target.column,
|
|
12712
|
+
cutoff,
|
|
12713
|
+
limit
|
|
12714
|
+
})
|
|
12715
|
+
});
|
|
12716
|
+
}
|
|
12614
12717
|
async dangerouslyClearAll() {
|
|
12615
12718
|
await this.db.clearTable({ tableName: _mastra_core_storage.TABLE_WORKFLOW_SNAPSHOT });
|
|
12616
12719
|
await this.db.clearTable({ tableName: _mastra_core_storage.TABLE_WORKFLOW_RUN_OWNERS });
|