@farukada/aws-langgraph-dynamodb-ts 0.1.0 → 0.2.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/README.md +131 -5
- package/dist/checkpointer/actions/delete-thread.d.ts.map +1 -1
- package/dist/checkpointer/actions/delete-thread.js +17 -9
- package/dist/checkpointer/actions/delete-thread.js.map +1 -1
- package/dist/checkpointer/actions/get-tuple.d.ts.map +1 -1
- package/dist/checkpointer/actions/get-tuple.js +70 -32
- package/dist/checkpointer/actions/get-tuple.js.map +1 -1
- package/dist/checkpointer/actions/put-writes.d.ts.map +1 -1
- package/dist/checkpointer/actions/put-writes.js +36 -19
- package/dist/checkpointer/actions/put-writes.js.map +1 -1
- package/dist/checkpointer/actions/put.d.ts.map +1 -1
- package/dist/checkpointer/actions/put.js +75 -18
- package/dist/checkpointer/actions/put.js.map +1 -1
- package/dist/checkpointer/actions/writer.d.ts +6 -4
- package/dist/checkpointer/actions/writer.d.ts.map +1 -1
- package/dist/checkpointer/actions/writer.js +12 -12
- package/dist/checkpointer/actions/writer.js.map +1 -1
- package/dist/checkpointer/index.d.ts +11 -4
- package/dist/checkpointer/index.d.ts.map +1 -1
- package/dist/checkpointer/index.js +97 -72
- package/dist/checkpointer/index.js.map +1 -1
- package/dist/checkpointer/types/index.d.ts +8 -0
- package/dist/checkpointer/types/index.d.ts.map +1 -1
- package/dist/checkpointer/utils/deserialization.d.ts.map +1 -1
- package/dist/checkpointer/utils/deserialization.js +28 -4
- package/dist/checkpointer/utils/deserialization.js.map +1 -1
- package/dist/checkpointer/utils/validation.d.ts +8 -8
- package/dist/checkpointer/utils/validation.d.ts.map +1 -1
- package/dist/checkpointer/utils/validation.js +45 -1
- package/dist/checkpointer/utils/validation.js.map +1 -1
- package/dist/factory.d.ts +14 -0
- package/dist/factory.d.ts.map +1 -1
- package/dist/factory.js +39 -20
- package/dist/factory.js.map +1 -1
- package/dist/history/actions/add-message.d.ts +5 -9
- package/dist/history/actions/add-message.d.ts.map +1 -1
- package/dist/history/actions/add-message.js +14 -42
- package/dist/history/actions/add-message.js.map +1 -1
- package/dist/history/actions/add-messages.d.ts +6 -10
- package/dist/history/actions/add-messages.d.ts.map +1 -1
- package/dist/history/actions/add-messages.js +33 -38
- package/dist/history/actions/add-messages.js.map +1 -1
- package/dist/history/actions/clear.d.ts.map +1 -1
- package/dist/history/actions/clear.js +3 -3
- package/dist/history/actions/clear.js.map +1 -1
- package/dist/history/actions/get-messages.d.ts.map +1 -1
- package/dist/history/actions/get-messages.js +2 -2
- package/dist/history/actions/get-messages.js.map +1 -1
- package/dist/history/actions/list-sessions.d.ts.map +1 -1
- package/dist/history/actions/list-sessions.js +6 -3
- package/dist/history/actions/list-sessions.js.map +1 -1
- package/dist/history/index.d.ts +41 -5
- package/dist/history/index.d.ts.map +1 -1
- package/dist/history/index.js +52 -18
- package/dist/history/index.js.map +1 -1
- package/dist/history/session-adapter.d.ts +39 -0
- package/dist/history/session-adapter.d.ts.map +1 -0
- package/dist/history/session-adapter.js +74 -0
- package/dist/history/session-adapter.js.map +1 -0
- package/dist/history/types/index.d.ts +32 -1
- package/dist/history/types/index.d.ts.map +1 -1
- package/dist/history/utils/index.d.ts +1 -0
- package/dist/history/utils/index.d.ts.map +1 -1
- package/dist/history/utils/index.js +1 -0
- package/dist/history/utils/index.js.map +1 -1
- package/dist/history/utils/optimistic-retry.d.ts +31 -0
- package/dist/history/utils/optimistic-retry.d.ts.map +1 -0
- package/dist/history/utils/optimistic-retry.js +74 -0
- package/dist/history/utils/optimistic-retry.js.map +1 -0
- package/dist/history/utils/title-generator.d.ts.map +1 -1
- package/dist/history/utils/title-generator.js +8 -3
- package/dist/history/utils/title-generator.js.map +1 -1
- package/dist/history/utils/update-expression-builder.d.ts +18 -21
- package/dist/history/utils/update-expression-builder.d.ts.map +1 -1
- package/dist/history/utils/update-expression-builder.js +31 -46
- package/dist/history/utils/update-expression-builder.js.map +1 -1
- package/dist/history/utils/validation.d.ts.map +1 -1
- package/dist/history/utils/validation.js +23 -3
- package/dist/history/utils/validation.js.map +1 -1
- package/dist/index.d.ts +6 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/shared/utils/batch-write.d.ts +44 -6
- package/dist/shared/utils/batch-write.d.ts.map +1 -1
- package/dist/shared/utils/batch-write.js +76 -28
- package/dist/shared/utils/batch-write.js.map +1 -1
- package/dist/shared/utils/client-factory.d.ts +25 -0
- package/dist/shared/utils/client-factory.d.ts.map +1 -0
- package/dist/shared/utils/client-factory.js +23 -0
- package/dist/shared/utils/client-factory.js.map +1 -0
- package/dist/shared/utils/compressor.d.ts +21 -3
- package/dist/shared/utils/compressor.d.ts.map +1 -1
- package/dist/shared/utils/compressor.js +75 -10
- package/dist/shared/utils/compressor.js.map +1 -1
- package/dist/shared/utils/constants.d.ts +1 -1
- package/dist/shared/utils/constants.d.ts.map +1 -1
- package/dist/shared/utils/constants.js +5 -1
- package/dist/shared/utils/constants.js.map +1 -1
- package/dist/shared/utils/index.d.ts +3 -0
- package/dist/shared/utils/index.d.ts.map +1 -1
- package/dist/shared/utils/index.js +3 -0
- package/dist/shared/utils/index.js.map +1 -1
- package/dist/shared/utils/logger.d.ts +27 -0
- package/dist/shared/utils/logger.d.ts.map +1 -1
- package/dist/shared/utils/logger.js +86 -0
- package/dist/shared/utils/logger.js.map +1 -1
- package/dist/shared/utils/retry.d.ts +7 -0
- package/dist/shared/utils/retry.d.ts.map +1 -1
- package/dist/shared/utils/retry.js +75 -17
- package/dist/shared/utils/retry.js.map +1 -1
- package/dist/shared/utils/s3-offloader.d.ts +10 -3
- package/dist/shared/utils/s3-offloader.d.ts.map +1 -1
- package/dist/shared/utils/s3-offloader.js +19 -9
- package/dist/shared/utils/s3-offloader.js.map +1 -1
- package/dist/shared/utils/s3-orphans.d.ts +16 -0
- package/dist/shared/utils/s3-orphans.d.ts.map +1 -0
- package/dist/shared/utils/s3-orphans.js +79 -0
- package/dist/shared/utils/s3-orphans.js.map +1 -0
- package/dist/shared/utils/sleep.d.ts +48 -0
- package/dist/shared/utils/sleep.d.ts.map +1 -0
- package/dist/shared/utils/sleep.js +82 -0
- package/dist/shared/utils/sleep.js.map +1 -0
- package/dist/shared/utils/ttl.d.ts +6 -2
- package/dist/shared/utils/ttl.d.ts.map +1 -1
- package/dist/shared/utils/ttl.js +17 -2
- package/dist/shared/utils/ttl.js.map +1 -1
- package/dist/store/actions/get-operation.d.ts.map +1 -1
- package/dist/store/actions/get-operation.js +2 -2
- package/dist/store/actions/get-operation.js.map +1 -1
- package/dist/store/actions/list-namespaces-operation.d.ts.map +1 -1
- package/dist/store/actions/list-namespaces-operation.js +44 -29
- package/dist/store/actions/list-namespaces-operation.js.map +1 -1
- package/dist/store/actions/put-operation.d.ts.map +1 -1
- package/dist/store/actions/put-operation.js +19 -5
- package/dist/store/actions/put-operation.js.map +1 -1
- package/dist/store/actions/search-operation.d.ts.map +1 -1
- package/dist/store/actions/search-operation.js +54 -21
- package/dist/store/actions/search-operation.js.map +1 -1
- package/dist/store/index.d.ts +1 -0
- package/dist/store/index.d.ts.map +1 -1
- package/dist/store/index.js +24 -20
- package/dist/store/index.js.map +1 -1
- package/dist/store/types/index.d.ts +33 -1
- package/dist/store/types/index.d.ts.map +1 -1
- package/dist/store/utils/filter.d.ts.map +1 -1
- package/dist/store/utils/filter.js +63 -1
- package/dist/store/utils/filter.js.map +1 -1
- package/dist/store/utils/validation.d.ts +6 -2
- package/dist/store/utils/validation.d.ts.map +1 -1
- package/dist/store/utils/validation.js +21 -5
- package/dist/store/utils/validation.js.map +1 -1
- package/package.json +36 -25
|
@@ -15,22 +15,60 @@ interface DeleteWriteRequest {
|
|
|
15
15
|
}
|
|
16
16
|
type WriteRequest = PutWriteRequest | DeleteWriteRequest;
|
|
17
17
|
/**
|
|
18
|
-
*
|
|
18
|
+
* Error thrown when `batchWriteWithRetry` / `batchWriteAllWithRetry` exhaust
|
|
19
|
+
* their UnprocessedItems retry budget. Carries enough information for the
|
|
20
|
+
* caller to reason about recovery: how many items persisted before the giveup,
|
|
21
|
+
* how many are still un-acked, and which items remained un-acked.
|
|
22
|
+
*
|
|
23
|
+
* *Partial-success semantics:* DynamoDB's BatchWriteItem is not atomic across
|
|
24
|
+
* items in a batch, and `batchWriteAllWithRetry` issues a sequence of 25-item
|
|
25
|
+
* batches. When this error is thrown, any item not listed in `unprocessed` has
|
|
26
|
+
* already been acked by DynamoDB. Callers that need all-or-nothing must drive
|
|
27
|
+
* reconciliation from `unprocessed` (retry, compensating delete, or surface to
|
|
28
|
+
* the user) — this helper cannot roll back the successful rows for you.
|
|
29
|
+
*/
|
|
30
|
+
export declare class BatchWriteIncompleteError extends Error {
|
|
31
|
+
readonly succeededCount: number;
|
|
32
|
+
readonly unprocessed: WriteRequest[];
|
|
33
|
+
constructor(succeededCount: number, unprocessed: WriteRequest[], retries: number);
|
|
34
|
+
}
|
|
35
|
+
export interface BatchWriteOptions {
|
|
36
|
+
/** Optional AbortSignal — short-circuits retry backoff and rejects with the abort reason. */
|
|
37
|
+
signal?: AbortSignal;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Execute a single batchWrite call with exponential backoff retry for UnprocessedItems.
|
|
41
|
+
*
|
|
42
|
+
* @remarks
|
|
43
|
+
* On exhaustion of the UnprocessedItems retry budget this throws a
|
|
44
|
+
* {@link BatchWriteIncompleteError} that carries the un-acked items — items
|
|
45
|
+
* NOT listed there were acked by DynamoDB and persist in the table. There is
|
|
46
|
+
* no rollback: callers that need an all-or-nothing write must use
|
|
47
|
+
* `TransactWriteItems` (capped at 100 items per request) instead of this
|
|
48
|
+
* helper.
|
|
19
49
|
*
|
|
20
50
|
* @param client - DynamoDB Document client
|
|
21
51
|
* @param tableName - Target DynamoDB table name
|
|
22
52
|
* @param requestItems - Array of write requests (PutRequest or DeleteRequest objects)
|
|
23
|
-
* @
|
|
53
|
+
* @param options.signal - Optional AbortSignal cancelling in-flight retries
|
|
54
|
+
* @throws {BatchWriteIncompleteError} if retries are exhausted with items still unprocessed
|
|
24
55
|
*/
|
|
25
|
-
export declare function batchWriteWithRetry(client: DynamoDBDocument, tableName: string, requestItems: WriteRequest[]): Promise<void>;
|
|
56
|
+
export declare function batchWriteWithRetry(client: DynamoDBDocument, tableName: string, requestItems: WriteRequest[], options?: BatchWriteOptions): Promise<void>;
|
|
26
57
|
/**
|
|
27
|
-
* Execute batch writes for an arbitrary number of items, chunking into batches of 25
|
|
58
|
+
* Execute batch writes for an arbitrary number of items, chunking into batches of 25.
|
|
59
|
+
*
|
|
60
|
+
* @remarks
|
|
61
|
+
* Each batch is retried independently. On failure of one batch, any preceding
|
|
62
|
+
* batches in the same call have already been acked by DynamoDB. This helper
|
|
63
|
+
* does not span a transaction across batches — see
|
|
64
|
+
* {@link batchWriteWithRetry} for the partial-success contract.
|
|
28
65
|
*
|
|
29
66
|
* @param client - DynamoDB Document client
|
|
30
67
|
* @param tableName - Target DynamoDB table name
|
|
31
68
|
* @param requestItems - Array of write requests (can exceed 25)
|
|
32
|
-
* @
|
|
69
|
+
* @param options.signal - Optional AbortSignal cancelling in-flight retries
|
|
70
|
+
* @throws {BatchWriteIncompleteError} if any batch fails after exhausting retries
|
|
33
71
|
*/
|
|
34
|
-
export declare function batchWriteAllWithRetry(client: DynamoDBDocument, tableName: string, requestItems: WriteRequest[]): Promise<void>;
|
|
72
|
+
export declare function batchWriteAllWithRetry(client: DynamoDBDocument, tableName: string, requestItems: WriteRequest[], options?: BatchWriteOptions): Promise<void>;
|
|
35
73
|
export {};
|
|
36
74
|
//# sourceMappingURL=batch-write.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"batch-write.d.ts","sourceRoot":"","sources":["../../../src/shared/utils/batch-write.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"batch-write.d.ts","sourceRoot":"","sources":["../../../src/shared/utils/batch-write.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAM9D,UAAU,eAAe;IACvB,UAAU,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CAC9B;AAED,UAAU,kBAAkB;IAC1B,aAAa,EAAE;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;CAChC;AAED,KAAK,YAAY,GAAG,eAAe,GAAG,kBAAkB,CAAC;AAEzD;;;;;;;;;;;;GAYG;AACH,qBAAa,yBAA0B,SAAQ,KAAK;IAClD,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,WAAW,EAAE,YAAY,EAAE,CAAC;gBAEzB,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,EAAE,OAAO,EAAE,MAAM;CAUjF;AAED,MAAM,WAAW,iBAAiB;IAChC,6FAA6F;IAC7F,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,gBAAgB,EACxB,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,YAAY,EAAE,EAC5B,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,IAAI,CAAC,CAuCf;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,gBAAgB,EACxB,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,YAAY,EAAE,EAC5B,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,IAAI,CAAC,CAOf"}
|
|
@@ -4,59 +4,107 @@
|
|
|
4
4
|
* Eliminates duplication of the retry pattern across checkpointer, store, and history modules
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.BatchWriteIncompleteError = void 0;
|
|
7
8
|
exports.batchWriteWithRetry = batchWriteWithRetry;
|
|
8
9
|
exports.batchWriteAllWithRetry = batchWriteAllWithRetry;
|
|
9
10
|
const constants_1 = require("./constants");
|
|
10
11
|
const retry_1 = require("./retry");
|
|
12
|
+
const sleep_1 = require("./sleep");
|
|
11
13
|
/**
|
|
12
|
-
*
|
|
14
|
+
* Error thrown when `batchWriteWithRetry` / `batchWriteAllWithRetry` exhaust
|
|
15
|
+
* their UnprocessedItems retry budget. Carries enough information for the
|
|
16
|
+
* caller to reason about recovery: how many items persisted before the giveup,
|
|
17
|
+
* how many are still un-acked, and which items remained un-acked.
|
|
18
|
+
*
|
|
19
|
+
* *Partial-success semantics:* DynamoDB's BatchWriteItem is not atomic across
|
|
20
|
+
* items in a batch, and `batchWriteAllWithRetry` issues a sequence of 25-item
|
|
21
|
+
* batches. When this error is thrown, any item not listed in `unprocessed` has
|
|
22
|
+
* already been acked by DynamoDB. Callers that need all-or-nothing must drive
|
|
23
|
+
* reconciliation from `unprocessed` (retry, compensating delete, or surface to
|
|
24
|
+
* the user) — this helper cannot roll back the successful rows for you.
|
|
25
|
+
*/
|
|
26
|
+
class BatchWriteIncompleteError extends Error {
|
|
27
|
+
succeededCount;
|
|
28
|
+
unprocessed;
|
|
29
|
+
constructor(succeededCount, unprocessed, retries) {
|
|
30
|
+
super(`batchWrite did not drain after ${retries} UnprocessedItems retries: ` +
|
|
31
|
+
`${succeededCount} item(s) persisted, ${unprocessed.length} still un-acked. ` +
|
|
32
|
+
`Inspect err.unprocessed to drive reconciliation.`);
|
|
33
|
+
this.name = 'BatchWriteIncompleteError';
|
|
34
|
+
this.succeededCount = succeededCount;
|
|
35
|
+
this.unprocessed = unprocessed;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
exports.BatchWriteIncompleteError = BatchWriteIncompleteError;
|
|
39
|
+
/**
|
|
40
|
+
* Execute a single batchWrite call with exponential backoff retry for UnprocessedItems.
|
|
41
|
+
*
|
|
42
|
+
* @remarks
|
|
43
|
+
* On exhaustion of the UnprocessedItems retry budget this throws a
|
|
44
|
+
* {@link BatchWriteIncompleteError} that carries the un-acked items — items
|
|
45
|
+
* NOT listed there were acked by DynamoDB and persist in the table. There is
|
|
46
|
+
* no rollback: callers that need an all-or-nothing write must use
|
|
47
|
+
* `TransactWriteItems` (capped at 100 items per request) instead of this
|
|
48
|
+
* helper.
|
|
13
49
|
*
|
|
14
50
|
* @param client - DynamoDB Document client
|
|
15
51
|
* @param tableName - Target DynamoDB table name
|
|
16
52
|
* @param requestItems - Array of write requests (PutRequest or DeleteRequest objects)
|
|
17
|
-
* @
|
|
53
|
+
* @param options.signal - Optional AbortSignal cancelling in-flight retries
|
|
54
|
+
* @throws {BatchWriteIncompleteError} if retries are exhausted with items still unprocessed
|
|
18
55
|
*/
|
|
19
|
-
async function batchWriteWithRetry(client, tableName, requestItems) {
|
|
56
|
+
async function batchWriteWithRetry(client, tableName, requestItems, options = {}) {
|
|
20
57
|
if (requestItems.length === 0)
|
|
21
58
|
return;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
`${unprocessed.length} items remain unprocessed.`);
|
|
36
|
-
}
|
|
37
|
-
await new Promise((resolve) => setTimeout(resolve, retryDelay));
|
|
38
|
-
retryDelay = Math.min(retryDelay * 2, 5000);
|
|
39
|
-
const retryResult = await client.batchWrite({
|
|
40
|
-
RequestItems: { [tableName]: unprocessed },
|
|
59
|
+
// Loop over UnprocessedItems OUTSIDE the transient-error retry wrapper.
|
|
60
|
+
// This way a ThrottlingException during an UnprocessedItems follow-up call
|
|
61
|
+
// doesn't cause the outer loop to re-submit items that already succeeded —
|
|
62
|
+
// which would be an idempotency problem for DeleteRequests against items
|
|
63
|
+
// that have since been recreated.
|
|
64
|
+
const initialCount = requestItems.length;
|
|
65
|
+
let pending = requestItems;
|
|
66
|
+
let retryDelay = sleep_1.INITIAL_BACKOFF_DELAY_MS;
|
|
67
|
+
let retryCount = 0;
|
|
68
|
+
while (pending.length > 0) {
|
|
69
|
+
const result = await (0, retry_1.withDynamoDBRetry)(async () => {
|
|
70
|
+
return await client.batchWrite({
|
|
71
|
+
RequestItems: { [tableName]: pending },
|
|
41
72
|
});
|
|
42
|
-
|
|
73
|
+
}, { signal: options.signal });
|
|
74
|
+
const unprocessed = result.UnprocessedItems?.[tableName] ?? [];
|
|
75
|
+
if (unprocessed.length === 0)
|
|
76
|
+
return;
|
|
77
|
+
retryCount++;
|
|
78
|
+
if (retryCount > constants_1.MAX_UNPROCESSED_RETRIES) {
|
|
79
|
+
throw new BatchWriteIncompleteError(initialCount - unprocessed.length, unprocessed, constants_1.MAX_UNPROCESSED_RETRIES);
|
|
43
80
|
}
|
|
44
|
-
|
|
81
|
+
// Full jitter so concurrent batch writers don't re-pressure the partition together.
|
|
82
|
+
await (0, sleep_1.sleep)((0, sleep_1.fullJitter)(retryDelay), options.signal);
|
|
83
|
+
retryDelay = (0, sleep_1.nextBackoffDelay)(retryDelay);
|
|
84
|
+
pending = unprocessed;
|
|
85
|
+
}
|
|
45
86
|
}
|
|
46
87
|
/**
|
|
47
|
-
* Execute batch writes for an arbitrary number of items, chunking into batches of 25
|
|
88
|
+
* Execute batch writes for an arbitrary number of items, chunking into batches of 25.
|
|
89
|
+
*
|
|
90
|
+
* @remarks
|
|
91
|
+
* Each batch is retried independently. On failure of one batch, any preceding
|
|
92
|
+
* batches in the same call have already been acked by DynamoDB. This helper
|
|
93
|
+
* does not span a transaction across batches — see
|
|
94
|
+
* {@link batchWriteWithRetry} for the partial-success contract.
|
|
48
95
|
*
|
|
49
96
|
* @param client - DynamoDB Document client
|
|
50
97
|
* @param tableName - Target DynamoDB table name
|
|
51
98
|
* @param requestItems - Array of write requests (can exceed 25)
|
|
52
|
-
* @
|
|
99
|
+
* @param options.signal - Optional AbortSignal cancelling in-flight retries
|
|
100
|
+
* @throws {BatchWriteIncompleteError} if any batch fails after exhausting retries
|
|
53
101
|
*/
|
|
54
|
-
async function batchWriteAllWithRetry(client, tableName, requestItems) {
|
|
102
|
+
async function batchWriteAllWithRetry(client, tableName, requestItems, options = {}) {
|
|
55
103
|
if (requestItems.length === 0)
|
|
56
104
|
return;
|
|
57
105
|
for (let i = 0; i < requestItems.length; i += constants_1.BATCH_WRITE_MAX) {
|
|
58
106
|
const batch = requestItems.slice(i, i + constants_1.BATCH_WRITE_MAX);
|
|
59
|
-
await batchWriteWithRetry(client, tableName, batch);
|
|
107
|
+
await batchWriteWithRetry(client, tableName, batch, options);
|
|
60
108
|
}
|
|
61
109
|
}
|
|
62
110
|
//# sourceMappingURL=batch-write.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"batch-write.js","sourceRoot":"","sources":["../../../src/shared/utils/batch-write.ts"],"names":[],"mappings":";AAAA;;;GAGG
|
|
1
|
+
{"version":3,"file":"batch-write.js","sourceRoot":"","sources":["../../../src/shared/utils/batch-write.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAqEH,kDA4CC;AAiBD,wDAYC;AA1ID,2CAAuE;AACvE,mCAA4C;AAC5C,mCAAwF;AAYxF;;;;;;;;;;;;GAYG;AACH,MAAa,yBAA0B,SAAQ,KAAK;IACzC,cAAc,CAAS;IACvB,WAAW,CAAiB;IAErC,YAAY,cAAsB,EAAE,WAA2B,EAAE,OAAe;QAC9E,KAAK,CACH,kCAAkC,OAAO,6BAA6B;YACpE,GAAG,cAAc,uBAAuB,WAAW,CAAC,MAAM,mBAAmB;YAC7E,kDAAkD,CACrD,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,2BAA2B,CAAC;QACxC,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;QACrC,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;IACjC,CAAC;CACF;AAdD,8DAcC;AAOD;;;;;;;;;;;;;;;;GAgBG;AACI,KAAK,UAAU,mBAAmB,CACvC,MAAwB,EACxB,SAAiB,EACjB,YAA4B,EAC5B,UAA6B,EAAE;IAE/B,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAEtC,wEAAwE;IACxE,2EAA2E;IAC3E,2EAA2E;IAC3E,yEAAyE;IACzE,kCAAkC;IAClC,MAAM,YAAY,GAAG,YAAY,CAAC,MAAM,CAAC;IACzC,IAAI,OAAO,GAAmB,YAAY,CAAC;IAC3C,IAAI,UAAU,GAAG,gCAAwB,CAAC;IAC1C,IAAI,UAAU,GAAG,CAAC,CAAC;IAEnB,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,MAAM,MAAM,GAAG,MAAM,IAAA,yBAAiB,EACpC,KAAK,IAAI,EAAE;YACT,OAAO,MAAM,MAAM,CAAC,UAAU,CAAC;gBAC7B,YAAY,EAAE,EAAE,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE;aACvC,CAAC,CAAC;QACL,CAAC,EACD,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAC3B,CAAC;QAEF,MAAM,WAAW,GAAI,MAAM,CAAC,gBAAgB,EAAE,CAAC,SAAS,CAAgC,IAAI,EAAE,CAAC;QAC/F,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAErC,UAAU,EAAE,CAAC;QACb,IAAI,UAAU,GAAG,mCAAuB,EAAE,CAAC;YACzC,MAAM,IAAI,yBAAyB,CACjC,YAAY,GAAG,WAAW,CAAC,MAAM,EACjC,WAAW,EACX,mCAAuB,CACxB,CAAC;QACJ,CAAC;QACD,oFAAoF;QACpF,MAAM,IAAA,aAAK,EAAC,IAAA,kBAAU,EAAC,UAAU,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QACpD,UAAU,GAAG,IAAA,wBAAgB,EAAC,UAAU,CAAC,CAAC;QAC1C,OAAO,GAAG,WAAW,CAAC;IACxB,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACI,KAAK,UAAU,sBAAsB,CAC1C,MAAwB,EACxB,SAAiB,EACjB,YAA4B,EAC5B,UAA6B,EAAE;IAE/B,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAEtC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,IAAI,2BAAe,EAAE,CAAC;QAC9D,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,2BAAe,CAAC,CAAC;QACzD,MAAM,mBAAmB,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IAC/D,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared DynamoDB client resolution for DynamoDBSaver / DynamoDBStore /
|
|
3
|
+
* DynamoDBChatMessageHistory.
|
|
4
|
+
*
|
|
5
|
+
* Each module supports two construction modes:
|
|
6
|
+
* 1. Pass `client` (pre-built DynamoDBDocument): we do not own it and skip cleanup.
|
|
7
|
+
* 2. Pass `clientConfig` (or nothing): we build our own client and own its lifecycle.
|
|
8
|
+
*
|
|
9
|
+
* This helper captures the if/else and the `ownsClient` flag in one place.
|
|
10
|
+
*/
|
|
11
|
+
import { DynamoDBClient, type DynamoDBClientConfig } from '@aws-sdk/client-dynamodb';
|
|
12
|
+
import { DynamoDBDocument } from '@aws-sdk/lib-dynamodb';
|
|
13
|
+
export interface ResolvedDynamoDBClient {
|
|
14
|
+
/** Underlying DynamoDB client — undefined when an external client was injected. */
|
|
15
|
+
ddbClient: DynamoDBClient | undefined;
|
|
16
|
+
/** DocumentClient wrapper used for all operations. */
|
|
17
|
+
client: DynamoDBDocument;
|
|
18
|
+
/** True when this library owns the underlying client and must destroy it. */
|
|
19
|
+
ownsClient: boolean;
|
|
20
|
+
}
|
|
21
|
+
export declare function resolveDynamoDBClient(options: {
|
|
22
|
+
client?: DynamoDBDocument;
|
|
23
|
+
clientConfig?: DynamoDBClientConfig;
|
|
24
|
+
}): ResolvedDynamoDBClient;
|
|
25
|
+
//# sourceMappingURL=client-factory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-factory.d.ts","sourceRoot":"","sources":["../../../src/shared/utils/client-factory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,cAAc,EAAE,KAAK,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AACrF,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzD,MAAM,WAAW,sBAAsB;IACrC,mFAAmF;IACnF,SAAS,EAAE,cAAc,GAAG,SAAS,CAAC;IACtC,sDAAsD;IACtD,MAAM,EAAE,gBAAgB,CAAC;IACzB,6EAA6E;IAC7E,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE;IAC7C,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,YAAY,CAAC,EAAE,oBAAoB,CAAC;CACrC,GAAG,sBAAsB,CAMzB"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Shared DynamoDB client resolution for DynamoDBSaver / DynamoDBStore /
|
|
4
|
+
* DynamoDBChatMessageHistory.
|
|
5
|
+
*
|
|
6
|
+
* Each module supports two construction modes:
|
|
7
|
+
* 1. Pass `client` (pre-built DynamoDBDocument): we do not own it and skip cleanup.
|
|
8
|
+
* 2. Pass `clientConfig` (or nothing): we build our own client and own its lifecycle.
|
|
9
|
+
*
|
|
10
|
+
* This helper captures the if/else and the `ownsClient` flag in one place.
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.resolveDynamoDBClient = resolveDynamoDBClient;
|
|
14
|
+
const client_dynamodb_1 = require("@aws-sdk/client-dynamodb");
|
|
15
|
+
const lib_dynamodb_1 = require("@aws-sdk/lib-dynamodb");
|
|
16
|
+
function resolveDynamoDBClient(options) {
|
|
17
|
+
if (options.client) {
|
|
18
|
+
return { ddbClient: undefined, client: options.client, ownsClient: false };
|
|
19
|
+
}
|
|
20
|
+
const ddbClient = new client_dynamodb_1.DynamoDBClient(options.clientConfig || {});
|
|
21
|
+
return { ddbClient, client: lib_dynamodb_1.DynamoDBDocument.from(ddbClient), ownsClient: true };
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=client-factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-factory.js","sourceRoot":"","sources":["../../../src/shared/utils/client-factory.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;;AAcH,sDASC;AArBD,8DAAqF;AACrF,wDAAyD;AAWzD,SAAgB,qBAAqB,CAAC,OAGrC;IACC,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;IAC7E,CAAC;IACD,MAAM,SAAS,GAAG,IAAI,gCAAc,CAAC,OAAO,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC;IACjE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,+BAAgB,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;AACnF,CAAC"}
|
|
@@ -12,6 +12,12 @@ export interface CompressionConfig {
|
|
|
12
12
|
minSizeBytes?: number;
|
|
13
13
|
/** Gzip compression level 1-9 (default: 6 = balanced speed/ratio) */
|
|
14
14
|
level?: number;
|
|
15
|
+
/**
|
|
16
|
+
* Hard cap on decompressed output size in bytes (default: 50 MiB).
|
|
17
|
+
* Protects against gzip-bomb payloads. Decompression throws if the output
|
|
18
|
+
* would exceed this cap.
|
|
19
|
+
*/
|
|
20
|
+
maxDecompressedBytes?: number;
|
|
15
21
|
}
|
|
16
22
|
/**
|
|
17
23
|
* Compressor for checkpoint data using gzip
|
|
@@ -24,6 +30,7 @@ export interface CompressionConfig {
|
|
|
24
30
|
export declare class Compressor {
|
|
25
31
|
private readonly minSizeBytes;
|
|
26
32
|
private readonly level;
|
|
33
|
+
private readonly maxDecompressedBytes;
|
|
27
34
|
constructor(config: CompressionConfig);
|
|
28
35
|
/**
|
|
29
36
|
* Compress data if above the minimum size threshold
|
|
@@ -33,15 +40,26 @@ export declare class Compressor {
|
|
|
33
40
|
*/
|
|
34
41
|
compress(data: Uint8Array): Promise<Uint8Array>;
|
|
35
42
|
/**
|
|
36
|
-
* Decompress data if
|
|
37
|
-
*
|
|
43
|
+
* Decompress data if it is library-compressed, otherwise passthrough.
|
|
44
|
+
*
|
|
45
|
+
* Detection order:
|
|
46
|
+
* 1. LGC marker: new-format payloads produced by compress() above.
|
|
47
|
+
* 2. Gzip magic: legacy payloads from before the marker was introduced;
|
|
48
|
+
* decompressed for backward compatibility.
|
|
49
|
+
*
|
|
50
|
+
* Raw user binary that happens to start with the gzip magic bytes is still at
|
|
51
|
+
* risk under (2), but new writes use the marker and will be unambiguous.
|
|
38
52
|
*
|
|
39
53
|
* @param data - Potentially compressed data
|
|
40
54
|
* @returns Decompressed data
|
|
41
55
|
*/
|
|
42
56
|
decompress(data: Uint8Array): Promise<Uint8Array>;
|
|
43
57
|
/**
|
|
44
|
-
* Check if data
|
|
58
|
+
* Check if data carries the library's compression marker.
|
|
59
|
+
*/
|
|
60
|
+
static hasCompressedMarker(data: Uint8Array): boolean;
|
|
61
|
+
/**
|
|
62
|
+
* Check if data starts with the gzip magic number (legacy-format detection).
|
|
45
63
|
*/
|
|
46
64
|
static isGzipped(data: Uint8Array): boolean;
|
|
47
65
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compressor.d.ts","sourceRoot":"","sources":["../../../src/shared/utils/compressor.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"compressor.d.ts","sourceRoot":"","sources":["../../../src/shared/utils/compressor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAiCH;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,sDAAsD;IACtD,OAAO,EAAE,OAAO,CAAC;IACjB,iFAAiF;IACjF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qEAAqE;IACrE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED;;;;;;;GAOG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAS;gBAElC,MAAM,EAAE,iBAAiB;IAMrC;;;;;OAKG;IACG,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IAqBrD;;;;;;;;;;;;;OAaG;IACG,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IA8BvD;;OAEG;IACH,MAAM,CAAC,mBAAmB,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO;IAQrD;;OAEG;IACH,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO;CAG5C"}
|
|
@@ -9,8 +9,28 @@ const node_util_1 = require("node:util");
|
|
|
9
9
|
const node_zlib_1 = require("node:zlib");
|
|
10
10
|
const gzipAsync = (0, node_util_1.promisify)(node_zlib_1.gzip);
|
|
11
11
|
const gunzipAsync = (0, node_util_1.promisify)(node_zlib_1.gunzip);
|
|
12
|
-
/** Gzip magic number bytes for auto-detection */
|
|
12
|
+
/** Gzip magic number bytes for auto-detection of legacy payloads */
|
|
13
13
|
const GZIP_MAGIC = new Uint8Array([0x1f, 0x8b]);
|
|
14
|
+
/**
|
|
15
|
+
* 3-byte marker stamped at the start of new compressed payloads. Unambiguously
|
|
16
|
+
* identifies "this is library-compressed" so we do not try to gunzip raw binary
|
|
17
|
+
* that happens to start with the gzip magic bytes. Legacy payloads (pre-marker)
|
|
18
|
+
* are still decompressed on a gzip-magic fallback — see `decompress()`.
|
|
19
|
+
*
|
|
20
|
+
* Bytes 0x4C 0x47 0x43 spell "LGC" (LangGraph-Compressed).
|
|
21
|
+
*/
|
|
22
|
+
const COMPRESSED_MARKER = new Uint8Array([0x4c, 0x47, 0x43]);
|
|
23
|
+
/**
|
|
24
|
+
* Default maximum decompressed output size: 50 MiB.
|
|
25
|
+
*
|
|
26
|
+
* Guards against "gzip bomb" payloads that are small on disk / in DynamoDB but
|
|
27
|
+
* expand to multi-gigabyte buffers that would OOM the process. Raise this via
|
|
28
|
+
* `CompressionConfig.maxDecompressedBytes` only if a legitimate workload needs
|
|
29
|
+
* larger checkpoints (remember: a DynamoDB item is hard-capped at 400 KB, so
|
|
30
|
+
* values above this threshold must originate from S3 offloading and should be
|
|
31
|
+
* treated with the same scrutiny).
|
|
32
|
+
*/
|
|
33
|
+
const DEFAULT_MAX_DECOMPRESSED_BYTES = 50 * 1024 * 1024;
|
|
14
34
|
/**
|
|
15
35
|
* Compressor for checkpoint data using gzip
|
|
16
36
|
*
|
|
@@ -22,9 +42,11 @@ const GZIP_MAGIC = new Uint8Array([0x1f, 0x8b]);
|
|
|
22
42
|
class Compressor {
|
|
23
43
|
minSizeBytes;
|
|
24
44
|
level;
|
|
45
|
+
maxDecompressedBytes;
|
|
25
46
|
constructor(config) {
|
|
26
47
|
this.minSizeBytes = config.minSizeBytes ?? 1024;
|
|
27
48
|
this.level = config.level ?? 6;
|
|
49
|
+
this.maxDecompressedBytes = config.maxDecompressedBytes ?? DEFAULT_MAX_DECOMPRESSED_BYTES;
|
|
28
50
|
}
|
|
29
51
|
/**
|
|
30
52
|
* Compress data if above the minimum size threshold
|
|
@@ -37,28 +59,71 @@ class Compressor {
|
|
|
37
59
|
return data;
|
|
38
60
|
}
|
|
39
61
|
const compressed = new Uint8Array(await gzipAsync(data, { level: this.level }));
|
|
40
|
-
// Only use compressed output if it saves
|
|
41
|
-
//
|
|
42
|
-
|
|
62
|
+
// Only use compressed output if it saves enough space to pay for the 3-byte
|
|
63
|
+
// marker overhead plus a reasonable margin (10%). Avoids data expansion for
|
|
64
|
+
// already-compressed or random binary payloads.
|
|
65
|
+
if (compressed.length + COMPRESSED_MARKER.length >= data.length * 0.9) {
|
|
43
66
|
return data;
|
|
44
67
|
}
|
|
45
|
-
|
|
68
|
+
// Prepend the LGC marker so decompress() can unambiguously identify our output.
|
|
69
|
+
const out = new Uint8Array(COMPRESSED_MARKER.length + compressed.length);
|
|
70
|
+
out.set(COMPRESSED_MARKER, 0);
|
|
71
|
+
out.set(compressed, COMPRESSED_MARKER.length);
|
|
72
|
+
return out;
|
|
46
73
|
}
|
|
47
74
|
/**
|
|
48
|
-
* Decompress data if
|
|
49
|
-
*
|
|
75
|
+
* Decompress data if it is library-compressed, otherwise passthrough.
|
|
76
|
+
*
|
|
77
|
+
* Detection order:
|
|
78
|
+
* 1. LGC marker: new-format payloads produced by compress() above.
|
|
79
|
+
* 2. Gzip magic: legacy payloads from before the marker was introduced;
|
|
80
|
+
* decompressed for backward compatibility.
|
|
81
|
+
*
|
|
82
|
+
* Raw user binary that happens to start with the gzip magic bytes is still at
|
|
83
|
+
* risk under (2), but new writes use the marker and will be unambiguous.
|
|
50
84
|
*
|
|
51
85
|
* @param data - Potentially compressed data
|
|
52
86
|
* @returns Decompressed data
|
|
53
87
|
*/
|
|
54
88
|
async decompress(data) {
|
|
55
|
-
|
|
89
|
+
// zlib rejects with an ERR_BUFFER_TOO_LARGE when the decompressed output
|
|
90
|
+
// would exceed maxOutputLength — caps memory use on hostile gzip-bomb input.
|
|
91
|
+
const opts = { maxOutputLength: this.maxDecompressedBytes };
|
|
92
|
+
try {
|
|
93
|
+
if (Compressor.hasCompressedMarker(data)) {
|
|
94
|
+
const payload = data.subarray(COMPRESSED_MARKER.length);
|
|
95
|
+
return new Uint8Array(await gunzipAsync(payload, opts));
|
|
96
|
+
}
|
|
97
|
+
if (Compressor.isGzipped(data)) {
|
|
98
|
+
// Legacy, pre-marker payload
|
|
99
|
+
return new Uint8Array(await gunzipAsync(data, opts));
|
|
100
|
+
}
|
|
56
101
|
return data;
|
|
57
102
|
}
|
|
58
|
-
|
|
103
|
+
catch (err) {
|
|
104
|
+
if (err &&
|
|
105
|
+
typeof err === 'object' &&
|
|
106
|
+
err.code === 'ERR_BUFFER_TOO_LARGE') {
|
|
107
|
+
throw new Error(`Refusing to decompress payload: decompressed output would exceed ${this.maxDecompressedBytes} bytes. ` +
|
|
108
|
+
`Raise Compressor's maxDecompressedBytes if this limit is too low.`, { cause: err });
|
|
109
|
+
}
|
|
110
|
+
throw err;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Check if data carries the library's compression marker.
|
|
115
|
+
*/
|
|
116
|
+
static hasCompressedMarker(data) {
|
|
117
|
+
if (data.length < COMPRESSED_MARKER.length)
|
|
118
|
+
return false;
|
|
119
|
+
for (let i = 0; i < COMPRESSED_MARKER.length; i++) {
|
|
120
|
+
if (data[i] !== COMPRESSED_MARKER[i])
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
return true;
|
|
59
124
|
}
|
|
60
125
|
/**
|
|
61
|
-
* Check if data starts with the gzip magic number
|
|
126
|
+
* Check if data starts with the gzip magic number (legacy-format detection).
|
|
62
127
|
*/
|
|
63
128
|
static isGzipped(data) {
|
|
64
129
|
return data.length >= 2 && data[0] === GZIP_MAGIC[0] && data[1] === GZIP_MAGIC[1];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compressor.js","sourceRoot":"","sources":["../../../src/shared/utils/compressor.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,yCAAsC;AACtC,yCAAyC;AAEzC,MAAM,SAAS,GAAG,IAAA,qBAAS,EAAC,gBAAI,CAAC,CAAC;AAClC,MAAM,WAAW,GAAG,IAAA,qBAAS,EAAC,kBAAM,CAAC,CAAC;AAEtC,
|
|
1
|
+
{"version":3,"file":"compressor.js","sourceRoot":"","sources":["../../../src/shared/utils/compressor.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Shared constants for validation across store and checkpointer
|
|
3
3
|
*/
|
|
4
4
|
export declare const MAX_TTL_DAYS: number;
|
|
5
|
-
export declare const MAX_LOOP_ITERATIONS =
|
|
5
|
+
export declare const MAX_LOOP_ITERATIONS = 1000;
|
|
6
6
|
export declare const MAX_TOTAL_ITEMS_IN_MEMORY = 10000;
|
|
7
7
|
export declare const BATCH_WRITE_MAX = 25;
|
|
8
8
|
export declare const MAX_UNPROCESSED_RETRIES = 10;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/shared/utils/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,eAAO,MAAM,YAAY,QAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/shared/utils/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,eAAO,MAAM,YAAY,QAAU,CAAC;AAKpC,eAAO,MAAM,mBAAmB,OAAO,CAAC;AACxC,eAAO,MAAM,yBAAyB,QAAQ,CAAC;AAC/C,eAAO,MAAM,eAAe,KAAK,CAAC;AAClC,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAE1C;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAgBjE"}
|
|
@@ -7,7 +7,11 @@ exports.MAX_UNPROCESSED_RETRIES = exports.BATCH_WRITE_MAX = exports.MAX_TOTAL_IT
|
|
|
7
7
|
exports.validateTTLDays = validateTTLDays;
|
|
8
8
|
// Common DynamoDB limits
|
|
9
9
|
exports.MAX_TTL_DAYS = 365 * 5; // 5 years
|
|
10
|
-
|
|
10
|
+
// A DynamoDB Query page is bounded by ~1MB. 1000 iterations × 1MB = ~1GB of data,
|
|
11
|
+
// which is well beyond MAX_TOTAL_ITEMS_IN_MEMORY anyway, so the lower memory cap
|
|
12
|
+
// stays the real guard. Previously 100 — too tight for long chat histories or
|
|
13
|
+
// filter-heavy searches where many pages yield few matching items.
|
|
14
|
+
exports.MAX_LOOP_ITERATIONS = 1000;
|
|
11
15
|
exports.MAX_TOTAL_ITEMS_IN_MEMORY = 10000; // Maximum items to collect in memory
|
|
12
16
|
exports.BATCH_WRITE_MAX = 25; // DynamoDB BatchWriteItem limit per request
|
|
13
17
|
exports.MAX_UNPROCESSED_RETRIES = 10; // Maximum retries for UnprocessedItems loops
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/shared/utils/constants.ts"],"names":[],"mappings":";AAAA;;GAEG;;;
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/shared/utils/constants.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAgBH,0CAgBC;AA9BD,yBAAyB;AACZ,QAAA,YAAY,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,UAAU;AAC/C,kFAAkF;AAClF,iFAAiF;AACjF,8EAA8E;AAC9E,mEAAmE;AACtD,QAAA,mBAAmB,GAAG,IAAI,CAAC;AAC3B,QAAA,yBAAyB,GAAG,KAAK,CAAC,CAAC,qCAAqC;AACxE,QAAA,eAAe,GAAG,EAAE,CAAC,CAAC,4CAA4C;AAClE,QAAA,uBAAuB,GAAG,EAAE,CAAC,CAAC,6CAA6C;AAExF;;GAEG;AACH,SAAgB,eAAe,CAAC,OAA2B;IACzD,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO;IACT,CAAC;IAED,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC;QAC9D,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;IACjD,CAAC;IAED,IAAI,OAAO,IAAI,CAAC,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;IAC/C,CAAC;IAED,IAAI,OAAO,GAAG,oBAAY,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,0BAA0B,oBAAY,EAAE,CAAC,CAAC;IAC5D,CAAC;AACH,CAAC"}
|
|
@@ -6,6 +6,9 @@ export * from './constants';
|
|
|
6
6
|
export * from './logger';
|
|
7
7
|
export * from './retry';
|
|
8
8
|
export * from './s3-offloader';
|
|
9
|
+
export * from './s3-orphans';
|
|
9
10
|
export * from './batch-write';
|
|
11
|
+
export * from './client-factory';
|
|
12
|
+
export * from './sleep';
|
|
10
13
|
export * from './ttl';
|
|
11
14
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/shared/utils/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,OAAO,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/shared/utils/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,SAAS,CAAC;AACxB,cAAc,OAAO,CAAC"}
|
|
@@ -22,6 +22,9 @@ __exportStar(require("./constants"), exports);
|
|
|
22
22
|
__exportStar(require("./logger"), exports);
|
|
23
23
|
__exportStar(require("./retry"), exports);
|
|
24
24
|
__exportStar(require("./s3-offloader"), exports);
|
|
25
|
+
__exportStar(require("./s3-orphans"), exports);
|
|
25
26
|
__exportStar(require("./batch-write"), exports);
|
|
27
|
+
__exportStar(require("./client-factory"), exports);
|
|
28
|
+
__exportStar(require("./sleep"), exports);
|
|
26
29
|
__exportStar(require("./ttl"), exports);
|
|
27
30
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/shared/utils/index.ts"],"names":[],"mappings":";AAAA;;GAEG;;;;;;;;;;;;;;;;AAEH,+CAA6B;AAC7B,8CAA4B;AAC5B,2CAAyB;AACzB,0CAAwB;AACxB,iDAA+B;AAC/B,gDAA8B;AAC9B,wCAAsB"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/shared/utils/index.ts"],"names":[],"mappings":";AAAA;;GAEG;;;;;;;;;;;;;;;;AAEH,+CAA6B;AAC7B,8CAA4B;AAC5B,2CAAyB;AACzB,0CAAwB;AACxB,iDAA+B;AAC/B,+CAA6B;AAC7B,gDAA8B;AAC9B,mDAAiC;AACjC,0CAAwB;AACxB,wCAAsB"}
|
|
@@ -45,4 +45,31 @@ export declare function getLogger(): Logger;
|
|
|
45
45
|
* Reset the logger to the default console-based implementation
|
|
46
46
|
*/
|
|
47
47
|
export declare function resetLogger(): void;
|
|
48
|
+
/**
|
|
49
|
+
* Recursively clone an object, replacing values at any secret-looking key with
|
|
50
|
+
* `[REDACTED]`. Cycles are broken with a WeakSet. Leaves primitives and non-
|
|
51
|
+
* enumerable values untouched. Does not mutate the input.
|
|
52
|
+
*
|
|
53
|
+
* @param value - Arbitrary value to redact
|
|
54
|
+
* @param patterns - Lower-cased substrings to match against each key
|
|
55
|
+
*/
|
|
56
|
+
export declare function redactSecrets(value: unknown, patterns?: readonly string[]): unknown;
|
|
57
|
+
/**
|
|
58
|
+
* Wrap an existing logger with automatic secret redaction applied to the
|
|
59
|
+
* variadic args (the message string itself is passed through unchanged — don't
|
|
60
|
+
* interpolate secrets into messages). Strings in args are left as-is; only
|
|
61
|
+
* object properties whose keys match a secret pattern are replaced.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```ts
|
|
65
|
+
* import { setGlobalLogger, redactLogger, getLogger } from '@farukada/aws-langgraph-dynamodb-ts';
|
|
66
|
+
* setGlobalLogger(redactLogger(getLogger()));
|
|
67
|
+
* ```
|
|
68
|
+
*
|
|
69
|
+
* @param inner - Logger to wrap
|
|
70
|
+
* @param options.extraKeys - Additional lower-cased substrings to treat as secret keys
|
|
71
|
+
*/
|
|
72
|
+
export declare function redactLogger(inner: Logger, options?: {
|
|
73
|
+
extraKeys?: readonly string[];
|
|
74
|
+
}): Logger;
|
|
48
75
|
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/shared/utils/logger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH;;GAEG;AACH,MAAM,WAAW,MAAM;IACrB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IACjD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;CAClD;AAuBD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAEpD;AAED;;;;GAIG;AACH,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,IAAI,CAElC"}
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/shared/utils/logger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH;;GAEG;AACH,MAAM,WAAW,MAAM;IACrB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IACjD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;CAClD;AAuBD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAEpD;AAED;;;;GAIG;AACH,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,IAAI,CAElC;AA8BD;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,OAAO,EACd,QAAQ,GAAE,SAAS,MAAM,EAAgC,GACxD,OAAO,CA0BT;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,MAAM,EACb,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAAO,GAC9C,MAAM,CAWR"}
|