@farukada/aws-langgraph-dynamodb-ts 0.6.0 → 0.8.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 +63 -9
- package/dist/checkpointer/actions/delete-thread.d.ts +3 -4
- package/dist/checkpointer/actions/delete-thread.d.ts.map +1 -1
- package/dist/checkpointer/actions/delete-thread.js +21 -41
- package/dist/checkpointer/actions/delete-thread.js.map +1 -1
- package/dist/checkpointer/actions/list.d.ts.map +1 -1
- package/dist/checkpointer/actions/list.js +31 -4
- package/dist/checkpointer/actions/list.js.map +1 -1
- package/dist/checkpointer/actions/put-writes.d.ts.map +1 -1
- package/dist/checkpointer/actions/put-writes.js +14 -24
- 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 +2 -0
- package/dist/checkpointer/actions/put.js.map +1 -1
- package/dist/checkpointer/internal/item-reader.d.ts +31 -0
- package/dist/checkpointer/internal/item-reader.d.ts.map +1 -1
- package/dist/checkpointer/internal/item-reader.js +49 -1
- package/dist/checkpointer/internal/item-reader.js.map +1 -1
- package/dist/checkpointer/internal/item-writer.d.ts +0 -8
- package/dist/checkpointer/internal/item-writer.d.ts.map +1 -1
- package/dist/checkpointer/internal/item-writer.js +15 -21
- package/dist/checkpointer/internal/item-writer.js.map +1 -1
- package/dist/checkpointer/internal/keys.d.ts +19 -3
- package/dist/checkpointer/internal/keys.d.ts.map +1 -1
- package/dist/checkpointer/internal/keys.js +41 -6
- package/dist/checkpointer/internal/keys.js.map +1 -1
- package/dist/checkpointer/internal/special-write-cleanup.d.ts.map +1 -1
- package/dist/checkpointer/internal/special-write-cleanup.js +6 -12
- package/dist/checkpointer/internal/special-write-cleanup.js.map +1 -1
- package/dist/checkpointer/internal/validation.d.ts +8 -4
- package/dist/checkpointer/internal/validation.d.ts.map +1 -1
- package/dist/checkpointer/internal/validation.js +12 -10
- package/dist/checkpointer/internal/validation.js.map +1 -1
- package/dist/checkpointer/internal/write-guard.d.ts +21 -0
- package/dist/checkpointer/internal/write-guard.d.ts.map +1 -0
- package/dist/checkpointer/internal/write-guard.js +48 -0
- package/dist/checkpointer/internal/write-guard.js.map +1 -0
- package/dist/checkpointer/internal/write-index.d.ts +29 -0
- package/dist/checkpointer/internal/write-index.d.ts.map +1 -0
- package/dist/checkpointer/internal/write-index.js +38 -0
- package/dist/checkpointer/internal/write-index.js.map +1 -0
- package/dist/checkpointer/types.d.ts +2 -0
- package/dist/checkpointer/types.d.ts.map +1 -1
- package/dist/history/actions/add-messages.d.ts.map +1 -1
- package/dist/history/actions/add-messages.js +24 -4
- package/dist/history/actions/add-messages.js.map +1 -1
- package/dist/history/actions/clear.d.ts +4 -6
- package/dist/history/actions/clear.d.ts.map +1 -1
- package/dist/history/actions/clear.js +18 -33
- package/dist/history/actions/clear.js.map +1 -1
- package/dist/history/actions/get-messages.d.ts +2 -1
- package/dist/history/actions/get-messages.d.ts.map +1 -1
- package/dist/history/actions/get-messages.js +28 -2
- package/dist/history/actions/get-messages.js.map +1 -1
- package/dist/history/actions/list-sessions.d.ts +2 -1
- package/dist/history/actions/list-sessions.d.ts.map +1 -1
- package/dist/history/actions/list-sessions.js +21 -2
- package/dist/history/actions/list-sessions.js.map +1 -1
- package/dist/history/actions/reconcile-count.d.ts.map +1 -1
- package/dist/history/actions/reconcile-count.js +2 -2
- package/dist/history/actions/reconcile-count.js.map +1 -1
- package/dist/history/internal/append-saga.d.ts.map +1 -1
- package/dist/history/internal/append-saga.js +2 -78
- package/dist/history/internal/append-saga.js.map +1 -1
- package/dist/history/internal/compensation.d.ts +21 -0
- package/dist/history/internal/compensation.d.ts.map +1 -0
- package/dist/history/internal/compensation.js +84 -0
- package/dist/history/internal/compensation.js.map +1 -0
- package/dist/history/internal/keys.d.ts +10 -2
- package/dist/history/internal/keys.d.ts.map +1 -1
- package/dist/history/internal/keys.js +32 -5
- package/dist/history/internal/keys.js.map +1 -1
- package/dist/history/internal/message-chunker.d.ts.map +1 -1
- package/dist/history/internal/message-chunker.js +13 -5
- package/dist/history/internal/message-chunker.js.map +1 -1
- package/dist/history/internal/session-count.d.ts +21 -0
- package/dist/history/internal/session-count.d.ts.map +1 -1
- package/dist/history/internal/session-count.js +51 -0
- package/dist/history/internal/session-count.js.map +1 -1
- package/dist/history/internal/session-title.d.ts +20 -0
- package/dist/history/internal/session-title.d.ts.map +1 -0
- package/dist/history/internal/session-title.js +44 -0
- package/dist/history/internal/session-title.js.map +1 -0
- package/dist/history/internal/setup.d.ts +2 -1
- package/dist/history/internal/setup.d.ts.map +1 -1
- package/dist/history/internal/setup.js +1 -0
- package/dist/history/internal/setup.js.map +1 -1
- package/dist/history/internal/title-generator.d.ts +8 -2
- package/dist/history/internal/title-generator.d.ts.map +1 -1
- package/dist/history/internal/title-generator.js +12 -3
- package/dist/history/internal/title-generator.js.map +1 -1
- package/dist/history/internal/validation.d.ts +9 -0
- package/dist/history/internal/validation.d.ts.map +1 -0
- package/dist/history/internal/validation.js +16 -0
- package/dist/history/internal/validation.js.map +1 -0
- package/dist/history/types.d.ts +12 -0
- package/dist/history/types.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/shared/codec/s3/offloader.d.ts +7 -1
- package/dist/shared/codec/s3/offloader.d.ts.map +1 -1
- package/dist/shared/codec/s3/offloader.js +14 -1
- package/dist/shared/codec/s3/offloader.js.map +1 -1
- package/dist/shared/dynamodb/batch-write.d.ts.map +1 -1
- package/dist/shared/dynamodb/batch-write.js +8 -6
- package/dist/shared/dynamodb/batch-write.js.map +1 -1
- package/dist/shared/dynamodb/drain-unprocessed.d.ts +5 -1
- package/dist/shared/dynamodb/drain-unprocessed.d.ts.map +1 -1
- package/dist/shared/dynamodb/drain-unprocessed.js +20 -11
- package/dist/shared/dynamodb/drain-unprocessed.js.map +1 -1
- package/dist/shared/dynamodb/partition-delete.d.ts +33 -0
- package/dist/shared/dynamodb/partition-delete.d.ts.map +1 -0
- package/dist/shared/dynamodb/partition-delete.js +70 -0
- package/dist/shared/dynamodb/partition-delete.js.map +1 -0
- package/dist/shared/dynamodb/retry-classifier.d.ts.map +1 -1
- package/dist/shared/dynamodb/retry-classifier.js +9 -1
- package/dist/shared/dynamodb/retry-classifier.js.map +1 -1
- package/dist/shared/errors/errors.d.ts +5 -2
- package/dist/shared/errors/errors.d.ts.map +1 -1
- package/dist/shared/errors/errors.js +6 -3
- package/dist/shared/errors/errors.js.map +1 -1
- package/dist/shared/logging/redaction-walk.d.ts +23 -0
- package/dist/shared/logging/redaction-walk.d.ts.map +1 -0
- package/dist/shared/logging/redaction-walk.js +92 -0
- package/dist/shared/logging/redaction-walk.js.map +1 -0
- package/dist/shared/logging/redaction.d.ts +22 -10
- package/dist/shared/logging/redaction.d.ts.map +1 -1
- package/dist/shared/logging/redaction.js +24 -36
- package/dist/shared/logging/redaction.js.map +1 -1
- package/dist/shared/logging/secret-patterns.d.ts +41 -0
- package/dist/shared/logging/secret-patterns.d.ts.map +1 -0
- package/dist/shared/logging/secret-patterns.js +74 -0
- package/dist/shared/logging/secret-patterns.js.map +1 -0
- package/dist/shared/validation/primitives.d.ts +9 -1
- package/dist/shared/validation/primitives.d.ts.map +1 -1
- package/dist/shared/validation/primitives.js +13 -0
- package/dist/shared/validation/primitives.js.map +1 -1
- package/dist/store/actions/get.d.ts.map +1 -1
- package/dist/store/actions/get.js +15 -1
- package/dist/store/actions/get.js.map +1 -1
- package/dist/store/actions/list-namespaces.d.ts.map +1 -1
- package/dist/store/actions/list-namespaces.js +1 -0
- package/dist/store/actions/list-namespaces.js.map +1 -1
- package/dist/store/actions/put.d.ts.map +1 -1
- package/dist/store/actions/put.js +20 -2
- package/dist/store/actions/put.js.map +1 -1
- package/dist/store/actions/search.d.ts.map +1 -1
- package/dist/store/actions/search.js +4 -35
- package/dist/store/actions/search.js.map +1 -1
- package/dist/store/internal/backend-search.d.ts +5 -0
- package/dist/store/internal/backend-search.d.ts.map +1 -0
- package/dist/store/internal/backend-search.js +67 -0
- package/dist/store/internal/backend-search.js.map +1 -0
- package/dist/store/internal/filter.d.ts.map +1 -1
- package/dist/store/internal/filter.js +26 -5
- package/dist/store/internal/filter.js.map +1 -1
- package/dist/store/internal/index-reconcile.d.ts.map +1 -1
- package/dist/store/internal/index-reconcile.js +33 -3
- package/dist/store/internal/index-reconcile.js.map +1 -1
- package/dist/store/internal/keys.d.ts +1 -1
- package/dist/store/internal/keys.d.ts.map +1 -1
- package/dist/store/internal/keys.js +8 -2
- package/dist/store/internal/keys.js.map +1 -1
- package/dist/store/internal/persist.d.ts.map +1 -1
- package/dist/store/internal/persist.js +1 -5
- package/dist/store/internal/persist.js.map +1 -1
- package/dist/store/internal/search-filter.d.ts +4 -0
- package/dist/store/internal/search-filter.d.ts.map +1 -0
- package/dist/store/internal/search-filter.js +11 -0
- package/dist/store/internal/search-filter.js.map +1 -0
- package/dist/store/internal/setup.d.ts +11 -1
- package/dist/store/internal/setup.d.ts.map +1 -1
- package/dist/store/internal/setup.js +17 -1
- package/dist/store/internal/setup.js.map +1 -1
- package/dist/store/internal/validation.d.ts +8 -2
- package/dist/store/internal/validation.d.ts.map +1 -1
- package/dist/store/internal/validation.js +15 -6
- package/dist/store/internal/validation.js.map +1 -1
- package/dist/store/internal/write-verify.d.ts +12 -0
- package/dist/store/internal/write-verify.d.ts.map +1 -1
- package/dist/store/internal/write-verify.js +27 -0
- package/dist/store/internal/write-verify.js.map +1 -1
- package/dist/store/vector-backend.d.ts +17 -0
- package/dist/store/vector-backend.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -11,11 +11,19 @@ const codec_1 = require("../../shared/codec/codec");
|
|
|
11
11
|
* overshoot the transaction byte limit.
|
|
12
12
|
*/
|
|
13
13
|
const ITEM_OVERHEAD_BYTES = 256;
|
|
14
|
+
/**
|
|
15
|
+
* Byte length of a string as DynamoDB stores it. `String.length` counts UTF-16
|
|
16
|
+
* code units, which understates every non-ASCII character — the wrong
|
|
17
|
+
* direction for an estimate documented to sit at or above the real size.
|
|
18
|
+
*/
|
|
19
|
+
function utf8Bytes(value) {
|
|
20
|
+
return Buffer.byteLength(value, 'utf8');
|
|
21
|
+
}
|
|
14
22
|
function descriptorBytes(descriptor) {
|
|
15
23
|
const body = descriptor.location === codec_1.PayloadLocation.INLINE
|
|
16
24
|
? descriptor.bytes.length
|
|
17
|
-
: descriptor.s3Key
|
|
18
|
-
return body + descriptor.serdeType
|
|
25
|
+
: utf8Bytes(descriptor.s3Key);
|
|
26
|
+
return body + utf8Bytes(descriptor.serdeType);
|
|
19
27
|
}
|
|
20
28
|
/**
|
|
21
29
|
* Conservatively estimate a message item's stored size, so chunks can stay under
|
|
@@ -23,9 +31,9 @@ function descriptorBytes(descriptor) {
|
|
|
23
31
|
* on the safe side of the real marshalled size.
|
|
24
32
|
*/
|
|
25
33
|
function estimateItemBytes(item) {
|
|
26
|
-
return (item.PK
|
|
27
|
-
item.SK
|
|
28
|
-
item.sessionId
|
|
34
|
+
return (utf8Bytes(item.PK) +
|
|
35
|
+
utf8Bytes(item.SK) +
|
|
36
|
+
utf8Bytes(item.sessionId) +
|
|
29
37
|
descriptorBytes(item.message) +
|
|
30
38
|
ITEM_OVERHEAD_BYTES);
|
|
31
39
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message-chunker.js","sourceRoot":"","sources":["../../../src/history/internal/message-chunker.ts"],"names":[],"mappings":";;;;AAAA,oDAAmF;AAGnF;;;;;;GAMG;AACH,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAEhC,SAAS,eAAe,CAAC,UAA6B;IACpD,MAAM,IAAI,GACR,UAAU,CAAC,QAAQ,KAAK,uBAAe,CAAC,MAAM;QAC5C,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,MAAM;QACzB,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"message-chunker.js","sourceRoot":"","sources":["../../../src/history/internal/message-chunker.ts"],"names":[],"mappings":";;;;AAAA,oDAAmF;AAGnF;;;;;;GAMG;AACH,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAEhC;;;;GAIG;AACH,SAAS,SAAS,CAAC,KAAa;IAC9B,OAAO,MAAM,CAAC,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;AAC1C,CAAC;AAED,SAAS,eAAe,CAAC,UAA6B;IACpD,MAAM,IAAI,GACR,UAAU,CAAC,QAAQ,KAAK,uBAAe,CAAC,MAAM;QAC5C,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,MAAM;QACzB,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IAClC,OAAO,IAAI,GAAG,SAAS,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;AAChD,CAAC;AAED;;;;GAIG;AACH,2BAAkC,IAAqB;IACrD,OAAO,CACL,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;QAClB,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;QAClB,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC;QACzB,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC;QAC7B,mBAAmB,CACpB,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAClB,KAAa,EACb,KAAa,EACb,IAAY,EACZ,GAAW,EACX,QAAgB;IAEhB,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC9B,OAAO,KAAK,IAAI,GAAG,IAAI,KAAK,GAAG,IAAI,GAAG,QAAQ,CAAC;AACjD,CAAC;AAED;;;;GAIG;AACH,qBACE,KAAwB,EACxB,QAAgB,EAChB,QAAgB;IAEhB,MAAM,MAAM,GAAwB,EAAE,CAAC;IACvC,IAAI,OAAO,GAAsB,EAAE,CAAC;IACpC,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI,WAAW,CAAC,OAAO,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC;YACxE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACrB,OAAO,GAAG,EAAE,CAAC;YACb,YAAY,GAAG,CAAC,CAAC;QACnB,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnB,YAAY,IAAI,IAAI,CAAC;IACvB,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC7C,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -17,4 +17,25 @@ import type { HistoryContext } from './setup';
|
|
|
17
17
|
* "TTL expiry" section.
|
|
18
18
|
*/
|
|
19
19
|
export declare function revertSessionCount(context: HistoryContext, sessionId: string, delta: number): Promise<void>;
|
|
20
|
+
/**
|
|
21
|
+
* Undo a rolled-back append's effect on the session row.
|
|
22
|
+
*
|
|
23
|
+
* When this call is the one that created the row — `createdAt` still equals
|
|
24
|
+
* this call's timestamp, and the only messages counted on it are the ones
|
|
25
|
+
* being reverted — the whole row is deleted. Without that, a failed first
|
|
26
|
+
* append left a "ghost session": `title`, `createdAt` and `sessionId` are all
|
|
27
|
+
* written via `if_not_exists`, so they were never reverted and never set
|
|
28
|
+
* again, leaving `listSessions()` reporting a session with `messageCount: 0`
|
|
29
|
+
* whose title still held up to 80 characters of a message the caller was told
|
|
30
|
+
* had not persisted, with no API to clear it.
|
|
31
|
+
*
|
|
32
|
+
* Both conditions are load-bearing. `createdAt = :now` establishes that this
|
|
33
|
+
* call created the row; `messageCount = :total` establishes that nothing else
|
|
34
|
+
* has added to it since. A concurrent append to the same brand-new session
|
|
35
|
+
* fails the count check, because deleting the row would destroy that caller's
|
|
36
|
+
* committed messages — so it falls through to the plain decrement, and then
|
|
37
|
+
* strips just the title this call contributed, which is the only part of the
|
|
38
|
+
* row still carrying rolled-back message content.
|
|
39
|
+
*/
|
|
40
|
+
export declare function revertSessionCreation(context: HistoryContext, sessionId: string, total: number, createdAt: string, title?: string): Promise<void>;
|
|
20
41
|
//# sourceMappingURL=session-count.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-count.d.ts","sourceRoot":"","sources":["../../../src/history/internal/session-count.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"session-count.d.ts","sourceRoot":"","sources":["../../../src/history/internal/session-count.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAe9C;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,cAAc,EACvB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC,CAiBf;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,cAAc,EACvB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EACjB,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAwBf"}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.revertSessionCount = revertSessionCount;
|
|
4
|
+
exports.revertSessionCreation = revertSessionCreation;
|
|
4
5
|
const node_crypto_1 = require("node:crypto");
|
|
5
6
|
const cancellation_1 = require("../../shared/dynamodb/cancellation");
|
|
6
7
|
const retry_1 = require("../../shared/dynamodb/retry");
|
|
7
8
|
const keys_1 = require("./keys");
|
|
9
|
+
const session_title_1 = require("./session-title");
|
|
8
10
|
/**
|
|
9
11
|
* True when a TransactWriteItems cancellation was caused by a
|
|
10
12
|
* ConditionalCheckFailed reason. Named distinctly from
|
|
@@ -55,4 +57,53 @@ async function revertSessionCount(context, sessionId, delta) {
|
|
|
55
57
|
throw error;
|
|
56
58
|
}
|
|
57
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* Undo a rolled-back append's effect on the session row.
|
|
62
|
+
*
|
|
63
|
+
* When this call is the one that created the row — `createdAt` still equals
|
|
64
|
+
* this call's timestamp, and the only messages counted on it are the ones
|
|
65
|
+
* being reverted — the whole row is deleted. Without that, a failed first
|
|
66
|
+
* append left a "ghost session": `title`, `createdAt` and `sessionId` are all
|
|
67
|
+
* written via `if_not_exists`, so they were never reverted and never set
|
|
68
|
+
* again, leaving `listSessions()` reporting a session with `messageCount: 0`
|
|
69
|
+
* whose title still held up to 80 characters of a message the caller was told
|
|
70
|
+
* had not persisted, with no API to clear it.
|
|
71
|
+
*
|
|
72
|
+
* Both conditions are load-bearing. `createdAt = :now` establishes that this
|
|
73
|
+
* call created the row; `messageCount = :total` establishes that nothing else
|
|
74
|
+
* has added to it since. A concurrent append to the same brand-new session
|
|
75
|
+
* fails the count check, because deleting the row would destroy that caller's
|
|
76
|
+
* committed messages — so it falls through to the plain decrement, and then
|
|
77
|
+
* strips just the title this call contributed, which is the only part of the
|
|
78
|
+
* row still carrying rolled-back message content.
|
|
79
|
+
*/
|
|
80
|
+
async function revertSessionCreation(context, sessionId, total, createdAt, title) {
|
|
81
|
+
if (total === 0)
|
|
82
|
+
return;
|
|
83
|
+
const input = {
|
|
84
|
+
TransactItems: [
|
|
85
|
+
{
|
|
86
|
+
Delete: {
|
|
87
|
+
TableName: context.tableName,
|
|
88
|
+
Key: { PK: (0, keys_1.sessionPartition)(sessionId), SK: keys_1.SESSION_SORT_KEY },
|
|
89
|
+
ConditionExpression: '#count = :total AND #c = :now',
|
|
90
|
+
ExpressionAttributeNames: { '#count': 'messageCount', '#c': 'createdAt' },
|
|
91
|
+
ExpressionAttributeValues: { ':total': total, ':now': createdAt },
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
],
|
|
95
|
+
ClientRequestToken: (0, node_crypto_1.randomUUID)(),
|
|
96
|
+
};
|
|
97
|
+
try {
|
|
98
|
+
await (0, retry_1.withDynamoDBRetry)(() => context.client.transactWrite(input));
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
if (!isCancelledByCondition(error))
|
|
103
|
+
throw error;
|
|
104
|
+
}
|
|
105
|
+
await revertSessionCount(context, sessionId, total);
|
|
106
|
+
if (title !== undefined)
|
|
107
|
+
await (0, session_title_1.removeRolledBackTitle)(context, sessionId, createdAt, title);
|
|
108
|
+
}
|
|
58
109
|
//# sourceMappingURL=session-count.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-count.js","sourceRoot":"","sources":["../../../src/history/internal/session-count.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"session-count.js","sourceRoot":"","sources":["../../../src/history/internal/session-count.ts"],"names":[],"mappings":";;;;AAAA,6CAAyC;AAEzC,qEAA4E;AAC5E,uDAAgE;AAChE,iCAA4D;AAC5D,mDAAwD;AAGxD;;;;;;;GAOG;AACH,SAAS,sBAAsB,CAAC,KAAY;IAC1C,MAAM,OAAO,GAAG,IAAA,qCAAsB,EAAC,KAAK,CAAC,CAAC;IAC9C,OAAO,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,KAAK,wBAAwB,CAAC;AACzD,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACI,KAAK,6BACV,OAAuB,EACvB,SAAiB,EACjB,KAAa;IAEb,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO;IACxB,MAAM,MAAM,GAAG;QACb,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,GAAG,EAAE,EAAE,EAAE,EAAE,IAAA,uBAAgB,EAAC,SAAS,CAAC,EAAE,EAAE,EAAE,uBAAgB,EAAE;QAC9D,gBAAgB,EAAE,iBAAiB;QACnC,mBAAmB,EAAE,sBAAsB;QAC3C,wBAAwB,EAAE,EAAE,QAAQ,EAAE,cAAc,EAAE;QACtD,yBAAyB,EAAE,EAAE,MAAM,EAAE,CAAC,KAAK,EAAE;KAC9C,CAAC;IACF,MAAM,KAAK,GAAG,EAAE,aAAa,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,kBAAkB,EAAE,IAAA,wBAAU,GAAE,EAAE,CAAC;IACxF,IAAI,CAAC;QACH,MAAM,IAAA,yBAAiB,EAAC,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC;IACrE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,sBAAsB,CAAC,KAAc,CAAC;YAAE,OAAO;QACnD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACI,KAAK,gCACV,OAAuB,EACvB,SAAiB,EACjB,KAAa,EACb,SAAiB,EACjB,KAAc;IAEd,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO;IACxB,MAAM,KAAK,GAAG;QACZ,aAAa,EAAE;YACb;gBACE,MAAM,EAAE;oBACN,SAAS,EAAE,OAAO,CAAC,SAAS;oBAC5B,GAAG,EAAE,EAAE,EAAE,EAAE,IAAA,uBAAgB,EAAC,SAAS,CAAC,EAAE,EAAE,EAAE,uBAAgB,EAAE;oBAC9D,mBAAmB,EAAE,+BAA+B;oBACpD,wBAAwB,EAAE,EAAE,QAAQ,EAAE,cAAc,EAAE,IAAI,EAAE,WAAW,EAAE;oBACzE,yBAAyB,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE;iBAClE;aACF;SACF;QACD,kBAAkB,EAAE,IAAA,wBAAU,GAAE;KACjC,CAAC;IACF,IAAI,CAAC;QACH,MAAM,IAAA,yBAAiB,EAAC,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC;QACnE,OAAO;IACT,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,sBAAsB,CAAC,KAAc,CAAC;YAAE,MAAM,KAAK,CAAC;IAC3D,CAAC;IACD,MAAM,kBAAkB,CAAC,OAAO,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;IACpD,IAAI,KAAK,KAAK,SAAS;QAAE,MAAM,IAAA,qCAAqB,EAAC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;AAC7F,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { HistoryContext } from './setup';
|
|
2
|
+
/**
|
|
3
|
+
* Strip a title this call contributed to a session row it created, when the
|
|
4
|
+
* row itself could not be deleted because a concurrent append has since added
|
|
5
|
+
* messages to it.
|
|
6
|
+
*
|
|
7
|
+
* Without this, that narrow window reopens exactly the leak C4 closes: the
|
|
8
|
+
* title is derived from the first human message of an append the caller was
|
|
9
|
+
* told had failed, and `if_not_exists` means nothing ever overwrites it — so
|
|
10
|
+
* a row that now belongs to a different caller keeps up to 80 characters of
|
|
11
|
+
* rolled-back message content.
|
|
12
|
+
*
|
|
13
|
+
* Both guards are load-bearing. `createdAt = :now` establishes that this call
|
|
14
|
+
* created the row, and `title = :title` that the title on it is still the one
|
|
15
|
+
* this call wrote — so a pre-existing title, or one a concurrent caller won
|
|
16
|
+
* the `if_not_exists` race for, is never removed. A condition rejection means
|
|
17
|
+
* exactly that and is not an error; anything else is.
|
|
18
|
+
*/
|
|
19
|
+
export declare function removeRolledBackTitle(context: HistoryContext, sessionId: string, createdAt: string, title: string): Promise<void>;
|
|
20
|
+
//# sourceMappingURL=session-title.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-title.d.ts","sourceRoot":"","sources":["../../../src/history/internal/session-title.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAO9C;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,cAAc,EACvB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC,CAgBf"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.removeRolledBackTitle = removeRolledBackTitle;
|
|
4
|
+
const retry_1 = require("../../shared/dynamodb/retry");
|
|
5
|
+
const keys_1 = require("./keys");
|
|
6
|
+
/** True when a plain UpdateItem was turned away by its ConditionExpression. */
|
|
7
|
+
function isConditionRejected(error) {
|
|
8
|
+
return error.name === 'ConditionalCheckFailedException';
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Strip a title this call contributed to a session row it created, when the
|
|
12
|
+
* row itself could not be deleted because a concurrent append has since added
|
|
13
|
+
* messages to it.
|
|
14
|
+
*
|
|
15
|
+
* Without this, that narrow window reopens exactly the leak C4 closes: the
|
|
16
|
+
* title is derived from the first human message of an append the caller was
|
|
17
|
+
* told had failed, and `if_not_exists` means nothing ever overwrites it — so
|
|
18
|
+
* a row that now belongs to a different caller keeps up to 80 characters of
|
|
19
|
+
* rolled-back message content.
|
|
20
|
+
*
|
|
21
|
+
* Both guards are load-bearing. `createdAt = :now` establishes that this call
|
|
22
|
+
* created the row, and `title = :title` that the title on it is still the one
|
|
23
|
+
* this call wrote — so a pre-existing title, or one a concurrent caller won
|
|
24
|
+
* the `if_not_exists` race for, is never removed. A condition rejection means
|
|
25
|
+
* exactly that and is not an error; anything else is.
|
|
26
|
+
*/
|
|
27
|
+
async function removeRolledBackTitle(context, sessionId, createdAt, title) {
|
|
28
|
+
try {
|
|
29
|
+
await (0, retry_1.withDynamoDBRetry)(() => context.client.update({
|
|
30
|
+
TableName: context.tableName,
|
|
31
|
+
Key: { PK: (0, keys_1.sessionPartition)(sessionId), SK: keys_1.SESSION_SORT_KEY },
|
|
32
|
+
UpdateExpression: 'REMOVE #title',
|
|
33
|
+
ConditionExpression: '#c = :now AND #title = :title',
|
|
34
|
+
ExpressionAttributeNames: { '#title': 'title', '#c': 'createdAt' },
|
|
35
|
+
ExpressionAttributeValues: { ':now': createdAt, ':title': title },
|
|
36
|
+
}));
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
if (isConditionRejected(error))
|
|
40
|
+
return;
|
|
41
|
+
throw error;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=session-title.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-title.js","sourceRoot":"","sources":["../../../src/history/internal/session-title.ts"],"names":[],"mappings":";;;AAAA,uDAAgE;AAChE,iCAA4D;AAG5D,+EAA+E;AAC/E,SAAS,mBAAmB,CAAC,KAAY;IACvC,OAAO,KAAK,CAAC,IAAI,KAAK,iCAAiC,CAAC;AAC1D,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACI,KAAK,gCACV,OAAuB,EACvB,SAAiB,EACjB,SAAiB,EACjB,KAAa;IAEb,IAAI,CAAC;QACH,MAAM,IAAA,yBAAiB,EAAC,GAAG,EAAE,CAC3B,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC;YACpB,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,GAAG,EAAE,EAAE,EAAE,EAAE,IAAA,uBAAgB,EAAC,SAAS,CAAC,EAAE,EAAE,EAAE,uBAAgB,EAAE;YAC9D,gBAAgB,EAAE,eAAe;YACjC,mBAAmB,EAAE,+BAA+B;YACpD,wBAAwB,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE;YAClE,yBAAyB,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE;SAClE,CAAC,CACH,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,mBAAmB,CAAC,KAAc,CAAC;YAAE,OAAO;QAChD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC"}
|
|
@@ -5,7 +5,7 @@ import type { CompressionConfig } from '../../shared/codec/compression';
|
|
|
5
5
|
import { S3Offloader } from '../../shared/codec/s3/offloader';
|
|
6
6
|
import { type Logger } from '../../shared/logging/logger';
|
|
7
7
|
import type { TtlOption } from '../../shared/validation/ttl';
|
|
8
|
-
import type { DynamoDBChatMessageHistoryOptions } from '../types';
|
|
8
|
+
import type { CorruptMessagePolicy, DynamoDBChatMessageHistoryOptions } from '../types';
|
|
9
9
|
/** Resolved collaborators shared by every chat-history action. */
|
|
10
10
|
export interface HistoryContext {
|
|
11
11
|
client: DynamoDBDocument;
|
|
@@ -16,6 +16,7 @@ export interface HistoryContext {
|
|
|
16
16
|
ttl?: TtlOption;
|
|
17
17
|
logger: Logger;
|
|
18
18
|
ulid: () => string;
|
|
19
|
+
onCorruptMessage: CorruptMessagePolicy;
|
|
19
20
|
}
|
|
20
21
|
/** Result of wiring up a chat-history adapter from its options. */
|
|
21
22
|
export interface HistorySetup {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../../src/history/internal/setup.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAE1E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAGxE,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAG9D,OAAO,EAAE,KAAK,MAAM,EAAiB,MAAM,6BAA6B,CAAC;AAEzE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,KAAK,EAAE,iCAAiC,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../../src/history/internal/setup.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAE1E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAGxE,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAG9D,OAAO,EAAE,KAAK,MAAM,EAAiB,MAAM,6BAA6B,CAAC;AAEzE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,KAAK,EAAE,oBAAoB,EAAE,iCAAiC,EAAE,MAAM,UAAU,CAAC;AAExF,kEAAkE;AAClE,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,gBAAgB,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,kBAAkB,CAAC;IAC1B,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAChC,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,MAAM,CAAC;IACnB,gBAAgB,EAAE,oBAAoB,CAAC;CACxC;AAED,mEAAmE;AACnE,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,cAAc,CAAC;IACxB,SAAS,EAAE,cAAc,GAAG,SAAS,CAAC;IACtC,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,gFAAgF;AAChF,wBAAgB,YAAY,CAAC,OAAO,EAAE,iCAAiC,GAAG,YAAY,CAuBrF"}
|
|
@@ -26,6 +26,7 @@ function setUpHistory(options) {
|
|
|
26
26
|
ttl: options.ttl,
|
|
27
27
|
logger: (0, logger_1.resolveLogger)(options.logger),
|
|
28
28
|
ulid: (0, ulid_1.createUlidFactory)(),
|
|
29
|
+
onCorruptMessage: options.onCorruptMessage ?? 'skip',
|
|
29
30
|
},
|
|
30
31
|
ddbClient: resolved.ddbClient,
|
|
31
32
|
ownsClient: resolved.ownsClient,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../../src/history/internal/setup.ts"],"names":[],"mappings":";;;AAKA,8DAA2D;AAC3D,yDAAuE;AACvE,+DAA8D;AAC9D,sDAA+D;AAC/D,yDAAqE;AACrE,wDAAyE;AACzE,4CAAsD;
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../../src/history/internal/setup.ts"],"names":[],"mappings":";;;AAKA,8DAA2D;AAC3D,yDAAuE;AACvE,+DAA8D;AAC9D,sDAA+D;AAC/D,yDAAqE;AACrE,wDAAyE;AACzE,4CAAsD;AAwBtD,gFAAgF;AAChF,sBAA6B,OAA0C;IACrE,MAAM,QAAQ,GAAG,IAAA,8BAAqB,EAAC,OAAO,CAAC,CAAC;IAChD,OAAO;QACL,OAAO,EAAE;YACP,MAAM,EAAE,QAAQ,CAAC,MAAM;YACvB,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,uBAAU;YAClC,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,SAAS,EAAE,OAAO,CAAC,EAAE;gBACnB,CAAC,CAAC,IAAI,uBAAW,CAAC;oBACd,GAAG,OAAO,CAAC,EAAE;oBACb,SAAS,EACP,OAAO,CAAC,EAAE,CAAC,SAAS,IAAI,IAAA,gCAAuB,EAAC,iCAAqB,EAAE,SAAS,CAAC;iBACpF,CAAC;gBACJ,CAAC,CAAC,SAAS;YACb,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,MAAM,EAAE,IAAA,sBAAa,EAAC,OAAO,CAAC,MAAM,CAAC;YACrC,IAAI,EAAE,IAAA,wBAAiB,GAAE;YACzB,gBAAgB,EAAE,OAAO,CAAC,gBAAgB,IAAI,MAAM;SACrD;QACD,SAAS,EAAE,QAAQ,CAAC,SAAS;QAC7B,UAAU,EAAE,QAAQ,CAAC,UAAU;KAChC,CAAC;AACJ,CAAC"}
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import type { StoredMessage } from '@langchain/core/messages';
|
|
2
2
|
/**
|
|
3
|
-
* Derive a session title from the first human message's text content,
|
|
4
|
-
*
|
|
3
|
+
* Derive a session title from the first human message's text content, at most
|
|
4
|
+
* {@link MAX_TITLE_LENGTH} characters including the ellipsis. Returns undefined
|
|
5
|
+
* when there is no usable text.
|
|
6
|
+
*
|
|
7
|
+
* Truncation counts *code points*, not UTF-16 code units: slicing by index
|
|
8
|
+
* could cut a surrogate pair in half, leaving a lone surrogate that no longer
|
|
9
|
+
* round-trips through UTF-8. The ellipsis is also counted against the maximum
|
|
10
|
+
* rather than appended past it.
|
|
5
11
|
*/
|
|
6
12
|
export declare function deriveTitle(messages: StoredMessage[]): string | undefined;
|
|
7
13
|
//# sourceMappingURL=title-generator.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"title-generator.d.ts","sourceRoot":"","sources":["../../../src/history/internal/title-generator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAI9D
|
|
1
|
+
{"version":3,"file":"title-generator.d.ts","sourceRoot":"","sources":["../../../src/history/internal/title-generator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAI9D;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,aAAa,EAAE,GAAG,MAAM,GAAG,SAAS,CAOzE"}
|
|
@@ -3,14 +3,23 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.deriveTitle = deriveTitle;
|
|
4
4
|
const MAX_TITLE_LENGTH = 80;
|
|
5
5
|
/**
|
|
6
|
-
* Derive a session title from the first human message's text content,
|
|
7
|
-
*
|
|
6
|
+
* Derive a session title from the first human message's text content, at most
|
|
7
|
+
* {@link MAX_TITLE_LENGTH} characters including the ellipsis. Returns undefined
|
|
8
|
+
* when there is no usable text.
|
|
9
|
+
*
|
|
10
|
+
* Truncation counts *code points*, not UTF-16 code units: slicing by index
|
|
11
|
+
* could cut a surrogate pair in half, leaving a lone surrogate that no longer
|
|
12
|
+
* round-trips through UTF-8. The ellipsis is also counted against the maximum
|
|
13
|
+
* rather than appended past it.
|
|
8
14
|
*/
|
|
9
15
|
function deriveTitle(messages) {
|
|
10
16
|
const firstHuman = messages.find((message) => message.type === 'human');
|
|
11
17
|
const content = firstHuman?.data.content;
|
|
12
18
|
if (typeof content !== 'string' || content.length === 0)
|
|
13
19
|
return undefined;
|
|
14
|
-
|
|
20
|
+
const codePoints = [...content];
|
|
21
|
+
if (codePoints.length <= MAX_TITLE_LENGTH)
|
|
22
|
+
return content;
|
|
23
|
+
return `${codePoints.slice(0, MAX_TITLE_LENGTH - 1).join('')}…`;
|
|
15
24
|
}
|
|
16
25
|
//# sourceMappingURL=title-generator.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"title-generator.js","sourceRoot":"","sources":["../../../src/history/internal/title-generator.ts"],"names":[],"mappings":";;;AAEA,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAE5B
|
|
1
|
+
{"version":3,"file":"title-generator.js","sourceRoot":"","sources":["../../../src/history/internal/title-generator.ts"],"names":[],"mappings":";;;AAEA,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAE5B;;;;;;;;;GASG;AACH,qBAA4B,QAAyB;IACnD,MAAM,UAAU,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC;IACxE,MAAM,OAAO,GAAG,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC;IACzC,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAC1E,MAAM,UAAU,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC;IAChC,IAAI,UAAU,CAAC,MAAM,IAAI,gBAAgB;QAAE,OAAO,OAAO,CAAC;IAC1D,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,gBAAgB,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC;AAClE,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validate a session id is a non-empty, separator- and control-char-free
|
|
3
|
+
* string. Applied on every entry point, not just the write path: a bad value
|
|
4
|
+
* used to reach DynamoDB and surface as a raw AWS SDK exception on reads,
|
|
5
|
+
* while the identical value threw this library's typed `ValidationError` on a
|
|
6
|
+
* write.
|
|
7
|
+
*/
|
|
8
|
+
export declare function validateSessionId(sessionId: string): void;
|
|
9
|
+
//# sourceMappingURL=validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../../src/history/internal/validation.ts"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAEzD"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateSessionId = validateSessionId;
|
|
4
|
+
const primitives_1 = require("../../shared/validation/primitives");
|
|
5
|
+
const keys_1 = require("./keys");
|
|
6
|
+
/**
|
|
7
|
+
* Validate a session id is a non-empty, separator- and control-char-free
|
|
8
|
+
* string. Applied on every entry point, not just the write path: a bad value
|
|
9
|
+
* used to reach DynamoDB and surface as a raw AWS SDK exception on reads,
|
|
10
|
+
* while the identical value threw this library's typed `ValidationError` on a
|
|
11
|
+
* write.
|
|
12
|
+
*/
|
|
13
|
+
function validateSessionId(sessionId) {
|
|
14
|
+
(0, primitives_1.validateIdentifier)(sessionId, keys_1.SORT_KEY_SEPARATOR, 'sessionId');
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../../src/history/internal/validation.ts"],"names":[],"mappings":";;;AAAA,mEAAwE;AACxE,iCAA4C;AAE5C;;;;;;GAMG;AACH,2BAAkC,SAAiB;IACjD,IAAA,+BAAkB,EAAC,SAAS,EAAE,yBAAkB,EAAE,WAAW,CAAC,CAAC;AACjE,CAAC"}
|
package/dist/history/types.d.ts
CHANGED
|
@@ -5,7 +5,19 @@ import type { BaseAdapterOptions, CodecOptions } from '../shared/options';
|
|
|
5
5
|
export type DynamoDBChatMessageHistoryOptions = BaseAdapterOptions & CodecOptions & {
|
|
6
6
|
/** Optional serializer override (defaults to the JSON serializer). */
|
|
7
7
|
serde?: SerializerProtocol;
|
|
8
|
+
/**
|
|
9
|
+
* What `getMessages` does when a stored message cannot be decoded — a
|
|
10
|
+
* decompression-guard trip, an unsupported `serdeType` after a config
|
|
11
|
+
* change, or genuinely corrupted bytes. `'skip'` (the default) drops the
|
|
12
|
+
* item, logs it at `error` with its sort key so an operator can locate
|
|
13
|
+
* it, and returns the rest; `'throw'` fails the whole read, which is
|
|
14
|
+
* all-or-nothing but leaves the session unreadable until the bad row is
|
|
15
|
+
* removed out of band.
|
|
16
|
+
*/
|
|
17
|
+
onCorruptMessage?: CorruptMessagePolicy;
|
|
8
18
|
};
|
|
19
|
+
/** How `getMessages` handles an item it cannot decode. */
|
|
20
|
+
export type CorruptMessagePolicy = 'skip' | 'throw';
|
|
9
21
|
/** Summary of a stored chat session. */
|
|
10
22
|
export interface SessionMetadata {
|
|
11
23
|
sessionId: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/history/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAE1E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,KAAK,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAE1E,sDAAsD;AACtD,MAAM,MAAM,iCAAiC,GAAG,kBAAkB,GAChE,YAAY,GAAG;IACb,sEAAsE;IACtE,KAAK,CAAC,EAAE,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/history/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAE1E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,KAAK,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAE1E,sDAAsD;AACtD,MAAM,MAAM,iCAAiC,GAAG,kBAAkB,GAChE,YAAY,GAAG;IACb,sEAAsE;IACtE,KAAK,CAAC,EAAE,kBAAkB,CAAC;IAC3B;;;;;;;;OAQG;IACH,gBAAgB,CAAC,EAAE,oBAAoB,CAAC;CACzC,CAAC;AAEJ,0DAA0D;AAC1D,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,OAAO,CAAC;AAEpD,wCAAwC;AACxC,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,gFAAgF;AAChF,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,iBAAiB,CAAC;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,kFAAkF;AAClF,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd"}
|
package/dist/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export type { VectorReconcileResult } from './store/actions/reconcile-vector-ind
|
|
|
6
6
|
export type { VectorBackend, VectorMatch, VectorRef } from './store/vector-backend';
|
|
7
7
|
export { DynamoDBChatMessageHistory } from './history/chat-message-history';
|
|
8
8
|
export { DynamoDBSessionChatMessageHistory } from './history/session-adapter';
|
|
9
|
-
export type { DynamoDBChatMessageHistoryOptions, SessionMetadata } from './history/types';
|
|
9
|
+
export type { CorruptMessagePolicy, DynamoDBChatMessageHistoryOptions, SessionMetadata, } from './history/types';
|
|
10
10
|
export { DynamoDBFactory } from './factory/factory';
|
|
11
11
|
export type { CreateAllOptions, CreatedAdapters, FactoryBaseOptions } from './factory/factory';
|
|
12
12
|
export { DynamoDbLangGraphError } from './shared/errors/base-error';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,YAAY,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,YAAY,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAC1D,YAAY,EAAE,qBAAqB,EAAE,MAAM,wCAAwC,CAAC;AACpF,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACpF,OAAO,EAAE,0BAA0B,EAAE,MAAM,gCAAgC,CAAC;AAC5E,OAAO,EAAE,iCAAiC,EAAE,MAAM,2BAA2B,CAAC;AAC9E,YAAY,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,YAAY,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,YAAY,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAC1D,YAAY,EAAE,qBAAqB,EAAE,MAAM,wCAAwC,CAAC;AACpF,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACpF,OAAO,EAAE,0BAA0B,EAAE,MAAM,gCAAgC,CAAC;AAC5E,OAAO,EAAE,iCAAiC,EAAE,MAAM,2BAA2B,CAAC;AAC9E,YAAY,EACV,oBAAoB,EACpB,iCAAiC,EACjC,eAAe,GAChB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAE/F,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,YAAY,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,OAAO,EACL,UAAU,EACV,4BAA4B,EAC5B,yBAAyB,EACzB,uBAAuB,EACvB,aAAa,EACb,oBAAoB,EACpB,mBAAmB,EACnB,eAAe,GAChB,MAAM,wBAAwB,CAAC;AAEhC,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAEzE,YAAY,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACzE,YAAY,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACzD,YAAY,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AACpE,YAAY,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC"}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,8CAAqD;AAA5C,sGAAA,aAAa,OAAA;AAEtB,uCAA8C;AAArC,sGAAA,aAAa,OAAA;AAItB,uEAA4E;AAAnE,kIAAA,0BAA0B,OAAA;AACnC,6DAA8E;AAArE,oIAAA,iCAAiC,OAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,8CAAqD;AAA5C,sGAAA,aAAa,OAAA;AAEtB,uCAA8C;AAArC,sGAAA,aAAa,OAAA;AAItB,uEAA4E;AAAnE,kIAAA,0BAA0B,OAAA;AACnC,6DAA8E;AAArE,oIAAA,iCAAiC,OAAA;AAM1C,6CAAoD;AAA3C,0GAAA,eAAe,OAAA;AAGxB,yDAAoE;AAA3D,oHAAA,sBAAsB,OAAA;AAE/B,yDAAuD;AAA9C,uGAAA,SAAS,OAAA;AAClB,iDASgC;AAR9B,oGAAA,UAAU,OAAA;AACV,sHAAA,4BAA4B,OAAA;AAC5B,mHAAA,yBAAyB,OAAA;AACzB,iHAAA,uBAAuB,OAAA;AACvB,uGAAA,aAAa,OAAA;AACb,8GAAA,oBAAoB,OAAA;AACpB,6GAAA,mBAAmB,OAAA;AACnB,yGAAA,eAAe,OAAA;AAIjB,wDAAyE;AAAhE,yGAAA,YAAY,OAAA;AAAE,0GAAA,aAAa,OAAA"}
|
|
@@ -6,6 +6,7 @@ import { S3OffloadConfig } from './config';
|
|
|
6
6
|
export declare class S3Offloader {
|
|
7
7
|
private clientPromise;
|
|
8
8
|
private resolvedClient;
|
|
9
|
+
private destroyed;
|
|
9
10
|
private readonly bucketName;
|
|
10
11
|
private readonly keyPrefix;
|
|
11
12
|
private readonly thresholdBytes;
|
|
@@ -28,7 +29,12 @@ export declare class S3Offloader {
|
|
|
28
29
|
deleteBatch(keys: string[]): Promise<string[]>;
|
|
29
30
|
/** Ensure a `${ttlDays}`-day expiration lifecycle rule exists for the prefix. */
|
|
30
31
|
ensureLifecycleRule(ttlDays: number): Promise<void>;
|
|
31
|
-
/**
|
|
32
|
+
/**
|
|
33
|
+
* Release the underlying S3 client. Safe at any point in the client's
|
|
34
|
+
* lifecycle: called before construction starts it does nothing, called
|
|
35
|
+
* mid-construction it marks the offloader destroyed so the client is
|
|
36
|
+
* released the moment it resolves, and called after it releases it directly.
|
|
37
|
+
*/
|
|
32
38
|
destroy(): void;
|
|
33
39
|
}
|
|
34
40
|
//# sourceMappingURL=offloader.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"offloader.d.ts","sourceRoot":"","sources":["../../../../src/shared/codec/s3/offloader.ts"],"names":[],"mappings":"AAIA,OAAO,EAAc,eAAe,EAAE,MAAM,UAAU,CAAC;AAKvD;;;GAGG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,aAAa,CAAgC;IACrD,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IAEzC,YAAY,MAAM,EAAE,eAAe,EAOlC;IAED,OAAO,CAAC,SAAS;
|
|
1
|
+
{"version":3,"file":"offloader.d.ts","sourceRoot":"","sources":["../../../../src/shared/codec/s3/offloader.ts"],"names":[],"mappings":"AAIA,OAAO,EAAc,eAAe,EAAE,MAAM,UAAU,CAAC;AAKvD;;;GAGG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,aAAa,CAAgC;IACrD,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IAEzC,YAAY,MAAM,EAAE,eAAe,EAOlC;IAED,OAAO,CAAC,SAAS;IA0BjB,8DAA8D;IAC9D,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAEvC;IAED,gDAAgD;IAChD,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAEzC;IAED,iCAAiC;IACjC,YAAY,IAAI,MAAM,CAErB;IAED,oDAAoD;IAC9C,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAS3D;IAED,6CAA6C;IACvC,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAE/C;IAED,+DAA+D;IACzD,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAEnD;IAED,iFAAiF;IAC3E,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAExD;IAED;;;;;OAKG;IACH,OAAO,IAAI,IAAI,CAGd;CACF"}
|
|
@@ -14,6 +14,7 @@ const read_write_1 = require("./read-write");
|
|
|
14
14
|
class S3Offloader {
|
|
15
15
|
clientPromise;
|
|
16
16
|
resolvedClient;
|
|
17
|
+
destroyed = false;
|
|
17
18
|
bucketName;
|
|
18
19
|
keyPrefix;
|
|
19
20
|
thresholdBytes;
|
|
@@ -35,6 +36,12 @@ class S3Offloader {
|
|
|
35
36
|
? Promise.resolve(this.config.createS3Client({ maxAttempts: 1, ...cfg }))
|
|
36
37
|
: (0, client_1.createDefaultS3Client)(cfg)).then((client) => {
|
|
37
38
|
this.resolvedClient = client;
|
|
39
|
+
/**
|
|
40
|
+
* `destroy()` may have run during this construction, when there was
|
|
41
|
+
* no client yet to release. Release it now instead of leaking it.
|
|
42
|
+
*/
|
|
43
|
+
if (this.destroyed)
|
|
44
|
+
client.destroy();
|
|
38
45
|
return client;
|
|
39
46
|
}, (error) => {
|
|
40
47
|
this.clientPromise = undefined;
|
|
@@ -78,8 +85,14 @@ class S3Offloader {
|
|
|
78
85
|
async ensureLifecycleRule(ttlDays) {
|
|
79
86
|
return (0, lifecycle_1.ensureLifecycleRule)(await this.getClient(), this.bucketName, this.keyPrefix, ttlDays);
|
|
80
87
|
}
|
|
81
|
-
/**
|
|
88
|
+
/**
|
|
89
|
+
* Release the underlying S3 client. Safe at any point in the client's
|
|
90
|
+
* lifecycle: called before construction starts it does nothing, called
|
|
91
|
+
* mid-construction it marks the offloader destroyed so the client is
|
|
92
|
+
* released the moment it resolves, and called after it releases it directly.
|
|
93
|
+
*/
|
|
82
94
|
destroy() {
|
|
95
|
+
this.destroyed = true;
|
|
83
96
|
this.resolvedClient?.destroy();
|
|
84
97
|
}
|
|
85
98
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"offloader.js","sourceRoot":"","sources":["../../../../src/shared/codec/s3/offloader.ts"],"names":[],"mappings":";;;AAEA,+CAAoG;AACpG,qCAAiD;AACjD,qCAAuD;AACvD,qCAAyC;AACzC,2CAAkD;AAClD,6CAA4D;AAE5D;;;GAGG;AACH;IACU,aAAa,CAAgC;IAC7C,cAAc,CAAuB;
|
|
1
|
+
{"version":3,"file":"offloader.js","sourceRoot":"","sources":["../../../../src/shared/codec/s3/offloader.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"batch-write.d.ts","sourceRoot":"","sources":["../../../src/shared/dynamodb/batch-write.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAI9D,OAAO,EAAE,YAAY,EAA0B,MAAM,qBAAqB,CAAC;AAC3E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"batch-write.d.ts","sourceRoot":"","sources":["../../../src/shared/dynamodb/batch-write.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAI9D,OAAO,EAAE,YAAY,EAA0B,MAAM,qBAAqB,CAAC;AAC3E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,gBAAgB,EACxB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,YAAY,EAAE,EACxB,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,IAAI,CAAC,CAgCf"}
|
|
@@ -4,10 +4,6 @@ exports.batchWriteAll = batchWriteAll;
|
|
|
4
4
|
const constants_1 = require("../constants");
|
|
5
5
|
const errors_1 = require("../errors/errors");
|
|
6
6
|
const drain_unprocessed_1 = require("./drain-unprocessed");
|
|
7
|
-
/** True when `error` is a {@link BatchWriteIncompleteError} — checked by name, not `instanceof`. */
|
|
8
|
-
function isBatchWriteIncomplete(error) {
|
|
9
|
-
return error.name === 'BatchWriteIncompleteError';
|
|
10
|
-
}
|
|
11
7
|
/**
|
|
12
8
|
* Write an arbitrary number of requests, chunked into batches of 25 (the
|
|
13
9
|
* BatchWriteItem limit). Every chunk is attempted regardless of an earlier
|
|
@@ -39,10 +35,16 @@ async function batchWriteAll(client, tableName, requests, options = {}) {
|
|
|
39
35
|
succeededCount += chunk.length;
|
|
40
36
|
}
|
|
41
37
|
catch (error) {
|
|
38
|
+
/**
|
|
39
|
+
* drainUnprocessedWrites has exactly three throw sites and every one
|
|
40
|
+
* constructs a BatchWriteIncompleteError with an accurate
|
|
41
|
+
* succeededCount — asserted, not name-checked, since the false case is
|
|
42
|
+
* unreachable and this project enforces 100% branch coverage with no
|
|
43
|
+
* exceptions (see drain-unprocessed.ts).
|
|
44
|
+
*/
|
|
42
45
|
const err = error;
|
|
43
46
|
failedChunks.push(err);
|
|
44
|
-
|
|
45
|
-
succeededCount += err.succeededCount;
|
|
47
|
+
succeededCount += err.succeededCount;
|
|
46
48
|
}
|
|
47
49
|
}
|
|
48
50
|
if (failedChunks.length > 0) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"batch-write.js","sourceRoot":"","sources":["../../../src/shared/dynamodb/batch-write.ts"],"names":[],"mappings":";;;AAEA,4CAA+C;AAC/C,6CAA2F;AAC3F,2DAA2E;AAG3E
|
|
1
|
+
{"version":3,"file":"batch-write.js","sourceRoot":"","sources":["../../../src/shared/dynamodb/batch-write.ts"],"names":[],"mappings":";;;AAEA,4CAA+C;AAC/C,6CAA2F;AAC3F,2DAA2E;AAG3E;;;;;;;;;;;;;;;;;GAiBG;AACI,KAAK,wBACV,MAAwB,EACxB,SAAiB,EACjB,QAAwB,EACxB,OAAO,GAAiB,EAAE;IAE1B,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,2BAAe,CAAC,CAAC;IACjE,IAAI,eAAe,GAAG,CAAC,CAAC;IACxB,IAAI,cAAc,GAAG,CAAC,CAAC;IACvB,MAAM,YAAY,GAAY,EAAE,CAAC;IACjC,KAAK,IAAI,MAAM,GAAG,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC,MAAM,EAAE,MAAM,IAAI,2BAAe,EAAE,CAAC;QACzE,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,2BAAe,CAAC,CAAC;QAC/D,IAAI,CAAC;YACH,MAAM,IAAA,0CAAsB,EAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;YAChE,eAAe,IAAI,CAAC,CAAC;YACrB,cAAc,IAAI,KAAK,CAAC,MAAM,CAAC;QACjC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf;;;;;;eAMG;YACH,MAAM,GAAG,GAAG,KAAkC,CAAC;YAC/C,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACvB,cAAc,IAAI,GAAG,CAAC,cAAc,CAAC;QACvC,CAAC;IACH,CAAC;IACD,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,qCAA4B,CACpC,eAAe,EACf,WAAW,EACX,YAAY,EACZ,cAAc,CACf,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -9,7 +9,11 @@ export interface DrainOptions {
|
|
|
9
9
|
/**
|
|
10
10
|
* Submit `requests` via BatchWriteItem and re-submit UnprocessedItems with
|
|
11
11
|
* full-jitter backoff until the batch drains. Throws
|
|
12
|
-
* {@link BatchWriteIncompleteError} if it cannot drain within the retry budget
|
|
12
|
+
* {@link BatchWriteIncompleteError} if it cannot drain within the retry budget,
|
|
13
|
+
* or if a round's write call or backoff wait throws outright (SDK failure, or
|
|
14
|
+
* the caller's signal aborting) — in every case `succeededCount` reflects
|
|
15
|
+
* every earlier round's confirmed persists, and the triggering error is
|
|
16
|
+
* attached as `cause`.
|
|
13
17
|
*/
|
|
14
18
|
export declare function drainUnprocessedWrites(client: DynamoDBDocument, tableName: string, requests: WriteRequest[], options?: DrainOptions): Promise<void>;
|
|
15
19
|
//# sourceMappingURL=drain-unprocessed.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"drain-unprocessed.d.ts","sourceRoot":"","sources":["../../../src/shared/dynamodb/drain-unprocessed.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAM9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C,yDAAyD;AACzD,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED
|
|
1
|
+
{"version":3,"file":"drain-unprocessed.d.ts","sourceRoot":"","sources":["../../../src/shared/dynamodb/drain-unprocessed.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAM9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C,yDAAyD;AACzD,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;GAQG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,gBAAgB,EACxB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,YAAY,EAAE,EACxB,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,IAAI,CAAC,CA8Bf"}
|