@mastra/dynamodb 1.4.2 → 1.4.3
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/index.cjs +82 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +83 -3
- package/dist/index.js.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/run-fencing.d.ts +7 -0
- package/dist/storage/domains/run-fencing.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/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { DescribeTableCommand, DynamoDBClient } from "@aws-sdk/client-dynamodb";
|
|
2
2
|
import { DynamoDBDocumentClient } from "@aws-sdk/lib-dynamodb";
|
|
3
3
|
import { ErrorCategory, ErrorDomain, MastraError } from "@mastra/core/error";
|
|
4
|
-
import { BackgroundTasksStorage, MastraCompositeStore, MemoryStorage, RunFenceConflictError, SCORERS_SCHEMA, ScoresStorage, TABLE_BACKGROUND_TASKS, TABLE_MEMORY_RUN_FENCES, TABLE_MESSAGES, TABLE_RESOURCES, TABLE_SCORERS, TABLE_THREADS, TABLE_WORKFLOW_RUN_OWNERS, TABLE_WORKFLOW_SNAPSHOT, WorkflowsStorage, calculatePagination, createStorageErrorId, isRunFenceConflictError, matchesExpectedWorkflowStatus, matchesRunFence, normalizePerPage, resolveRunFence, storageMessageMatchesMetadataFilter, validateStorageMetadataFilter } from "@mastra/core/storage";
|
|
4
|
+
import { BackgroundTasksStorage, MastraCompositeStore, MemoryStorage, RunFenceConflictError, SCORERS_SCHEMA, ScoresStorage, TABLE_BACKGROUND_TASKS, TABLE_MEMORY_RUN_FENCES, TABLE_MESSAGES, TABLE_RESOURCES, TABLE_SCORERS, TABLE_THREADS, TABLE_WORKFLOW_RUN_OWNERS, TABLE_WORKFLOW_SNAPSHOT, WorkflowsStorage, calculatePagination, createStorageErrorId, executeRetentionPrune, isRunFenceConflictError, matchesExpectedWorkflowStatus, matchesRunFence, normalizePerPage, resolveRetentionTargets, resolveRunFence, retentionCutoffMs, storageMessageMatchesMetadataFilter, validateStorageMetadataFilter } from "@mastra/core/storage";
|
|
5
5
|
import { Entity, Service } from "electrodb";
|
|
6
6
|
import { MessageList } from "@mastra/core/agent";
|
|
7
7
|
import { saveScorePayloadSchema } from "@mastra/core/evals";
|
|
@@ -1686,9 +1686,52 @@ async function goWithRunFence(service, check, write) {
|
|
|
1686
1686
|
await backoff(attempt);
|
|
1687
1687
|
}
|
|
1688
1688
|
}
|
|
1689
|
+
/**
|
|
1690
|
+
* Deletes up to `limit` items of a run claim entity whose epoch-ms `attribute`
|
|
1691
|
+
* is older than `cutoff`. These entities have no index on the anchor, so this
|
|
1692
|
+
* scans for them. Each delete repeats the cutoff as its condition, so an item
|
|
1693
|
+
* claimed or raised again since the scan is kept.
|
|
1694
|
+
*/
|
|
1695
|
+
async function pruneRunClaims(service, entityName, attribute, cutoff, limit) {
|
|
1696
|
+
const entity = service.entities[entityName];
|
|
1697
|
+
const olderThanCutoff = (attr, op) => op.lt(attr[attribute], cutoff);
|
|
1698
|
+
let deleted = 0;
|
|
1699
|
+
let cursor = null;
|
|
1700
|
+
do {
|
|
1701
|
+
const page = await entity.scan.where(olderThanCutoff).go({
|
|
1702
|
+
cursor,
|
|
1703
|
+
limit: limit - deleted
|
|
1704
|
+
});
|
|
1705
|
+
for (const item of page.data) {
|
|
1706
|
+
try {
|
|
1707
|
+
await retryOnTransactionConflict(() => entity.delete({
|
|
1708
|
+
entity: entityName,
|
|
1709
|
+
run_id: item.run_id
|
|
1710
|
+
}).where(olderThanCutoff).go());
|
|
1711
|
+
deleted++;
|
|
1712
|
+
} catch (error) {
|
|
1713
|
+
if (!isConditionalCheckFailed(error)) throw error;
|
|
1714
|
+
}
|
|
1715
|
+
if (deleted >= limit) return deleted;
|
|
1716
|
+
}
|
|
1717
|
+
cursor = page.cursor;
|
|
1718
|
+
} while (cursor);
|
|
1719
|
+
return deleted;
|
|
1720
|
+
}
|
|
1689
1721
|
//#endregion
|
|
1690
1722
|
//#region src/storage/domains/memory/index.ts
|
|
1691
|
-
var MemoryStorageDynamoDB = class extends MemoryStorage {
|
|
1723
|
+
var MemoryStorageDynamoDB = class MemoryStorageDynamoDB extends MemoryStorage {
|
|
1724
|
+
/**
|
|
1725
|
+
* Tables `prune()` can clean up. Run fences anchor on `retiredAt` (epoch ms), which stays unset until the
|
|
1726
|
+
* execution holding the fence settles, so a running execution's fence is
|
|
1727
|
+
* never pruned.
|
|
1728
|
+
*/
|
|
1729
|
+
static retentionTables = { runFences: {
|
|
1730
|
+
table: TABLE_MEMORY_RUN_FENCES,
|
|
1731
|
+
column: "retiredAt",
|
|
1732
|
+
indexed: false,
|
|
1733
|
+
anchorType: "epoch-ms"
|
|
1734
|
+
} };
|
|
1692
1735
|
supportsPartialThreadUpdate = true;
|
|
1693
1736
|
service;
|
|
1694
1737
|
ttlConfig;
|
|
@@ -1701,6 +1744,19 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
|
|
|
1701
1744
|
supportsRunFencing() {
|
|
1702
1745
|
return true;
|
|
1703
1746
|
}
|
|
1747
|
+
async prune(policies, options) {
|
|
1748
|
+
return executeRetentionPrune({
|
|
1749
|
+
domain: "memory",
|
|
1750
|
+
targets: resolveRetentionTargets({
|
|
1751
|
+
policies,
|
|
1752
|
+
descriptor: MemoryStorageDynamoDB.retentionTables,
|
|
1753
|
+
order: ["runFences"]
|
|
1754
|
+
}),
|
|
1755
|
+
options,
|
|
1756
|
+
cutoffFor: (target, now) => retentionCutoffMs(target.policy, now),
|
|
1757
|
+
deleteBatch: (_target, cutoff, limit) => pruneRunClaims(this.service, "memory_run_fence", "retiredAt", Number(cutoff), limit)
|
|
1758
|
+
});
|
|
1759
|
+
}
|
|
1704
1760
|
async dangerouslyClearAll() {
|
|
1705
1761
|
await deleteTableData(this.service, TABLE_THREADS);
|
|
1706
1762
|
await deleteTableData(this.service, TABLE_MESSAGES);
|
|
@@ -2832,7 +2888,18 @@ function toRunOwnershipRecord(item) {
|
|
|
2832
2888
|
}
|
|
2833
2889
|
const MAX_RETRIES = 5;
|
|
2834
2890
|
const BASE_DELAY_MS = 50;
|
|
2835
|
-
var WorkflowStorageDynamoDB = class extends WorkflowsStorage {
|
|
2891
|
+
var WorkflowStorageDynamoDB = class WorkflowStorageDynamoDB extends WorkflowsStorage {
|
|
2892
|
+
/**
|
|
2893
|
+
* Tables `prune()` can clean up. Run ownership records anchor on `updatedAt` (epoch ms), which every
|
|
2894
|
+
* claim, renewal and release refreshes, so a live execution's record is never
|
|
2895
|
+
* older than its renew interval.
|
|
2896
|
+
*/
|
|
2897
|
+
static retentionTables = { runOwnership: {
|
|
2898
|
+
table: TABLE_WORKFLOW_RUN_OWNERS,
|
|
2899
|
+
column: "updatedAt",
|
|
2900
|
+
indexed: false,
|
|
2901
|
+
anchorType: "epoch-ms"
|
|
2902
|
+
} };
|
|
2836
2903
|
service;
|
|
2837
2904
|
ttlConfig;
|
|
2838
2905
|
constructor(config) {
|
|
@@ -2847,6 +2914,19 @@ var WorkflowStorageDynamoDB = class extends WorkflowsStorage {
|
|
|
2847
2914
|
supportsRunFencing() {
|
|
2848
2915
|
return true;
|
|
2849
2916
|
}
|
|
2917
|
+
async prune(policies, options) {
|
|
2918
|
+
return executeRetentionPrune({
|
|
2919
|
+
domain: "workflows",
|
|
2920
|
+
targets: resolveRetentionTargets({
|
|
2921
|
+
policies,
|
|
2922
|
+
descriptor: WorkflowStorageDynamoDB.retentionTables,
|
|
2923
|
+
order: ["runOwnership"]
|
|
2924
|
+
}),
|
|
2925
|
+
options,
|
|
2926
|
+
cutoffFor: (target, now) => retentionCutoffMs(target.policy, now),
|
|
2927
|
+
deleteBatch: (_target, cutoff, limit) => pruneRunClaims(this.service, "workflow_run_owner", "updatedAt", Number(cutoff), limit)
|
|
2928
|
+
});
|
|
2929
|
+
}
|
|
2850
2930
|
async dangerouslyClearAll() {
|
|
2851
2931
|
await deleteTableData(this.service, TABLE_WORKFLOW_SNAPSHOT);
|
|
2852
2932
|
await deleteTableData(this.service, TABLE_WORKFLOW_RUN_OWNERS);
|