@farukada/aws-langgraph-dynamodb-ts 0.7.0 → 0.9.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 +52 -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 +38 -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 +15 -24
- package/dist/checkpointer/actions/put-writes.js.map +1 -1
- package/dist/checkpointer/internal/item-reader.d.ts +45 -0
- package/dist/checkpointer/internal/item-reader.d.ts.map +1 -1
- package/dist/checkpointer/internal/item-reader.js +63 -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 +16 -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-cas.d.ts +30 -0
- package/dist/checkpointer/internal/special-write-cas.d.ts.map +1 -0
- package/dist/checkpointer/internal/special-write-cas.js +104 -0
- package/dist/checkpointer/internal/special-write-cas.js.map +1 -0
- package/dist/checkpointer/internal/special-write-cleanup.d.ts +18 -12
- package/dist/checkpointer/internal/special-write-cleanup.d.ts.map +1 -1
- package/dist/checkpointer/internal/special-write-cleanup.js +31 -86
- package/dist/checkpointer/internal/special-write-cleanup.js.map +1 -1
- package/dist/checkpointer/internal/special-write-verify.d.ts +54 -0
- package/dist/checkpointer/internal/special-write-verify.d.ts.map +1 -0
- package/dist/checkpointer/internal/special-write-verify.js +65 -0
- package/dist/checkpointer/internal/special-write-verify.js.map +1 -0
- 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 +13 -0
- package/dist/checkpointer/internal/write-guard.d.ts.map +1 -0
- package/dist/checkpointer/internal/write-guard.js +39 -0
- package/dist/checkpointer/internal/write-guard.js.map +1 -0
- package/dist/checkpointer/internal/write-index.d.ts +37 -0
- package/dist/checkpointer/internal/write-index.d.ts.map +1 -0
- package/dist/checkpointer/internal/write-index.js +42 -0
- package/dist/checkpointer/internal/write-index.js.map +1 -0
- package/dist/checkpointer/types.d.ts +8 -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 +9 -1
- package/dist/history/internal/keys.d.ts.map +1 -1
- package/dist/history/internal/keys.js +21 -4
- 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/constants.d.ts +15 -0
- package/dist/shared/constants.d.ts.map +1 -1
- package/dist/shared/constants.js +16 -1
- package/dist/shared/constants.js.map +1 -1
- package/dist/shared/dynamodb/conditional-put.d.ts +51 -0
- package/dist/shared/dynamodb/conditional-put.d.ts.map +1 -0
- package/dist/shared/dynamodb/conditional-put.js +59 -0
- package/dist/shared/dynamodb/conditional-put.js.map +1 -0
- 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/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 +26 -17
- package/dist/shared/logging/redaction.d.ts.map +1 -1
- package/dist/shared/logging/redaction.js +24 -48
- package/dist/shared/logging/redaction.js.map +1 -1
- package/dist/shared/logging/secret-patterns.d.ts +74 -0
- package/dist/shared/logging/secret-patterns.d.ts.map +1 -0
- package/dist/shared/logging/secret-patterns.js +107 -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 +24 -18
- 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 +68 -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 +46 -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 +41 -5
- package/dist/store/internal/index-reconcile.js.map +1 -1
- package/dist/store/internal/item-mapper.d.ts +1 -0
- package/dist/store/internal/item-mapper.d.ts.map +1 -1
- package/dist/store/internal/item-mapper.js +2 -0
- package/dist/store/internal/item-mapper.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/overwrite-swap.d.ts +33 -0
- package/dist/store/internal/overwrite-swap.d.ts.map +1 -0
- package/dist/store/internal/overwrite-swap.js +62 -0
- package/dist/store/internal/overwrite-swap.js.map +1 -0
- package/dist/store/internal/persist.d.ts +22 -6
- package/dist/store/internal/persist.d.ts.map +1 -1
- package/dist/store/internal/persist.js +41 -20
- package/dist/store/internal/persist.js.map +1 -1
- package/dist/store/internal/read-existing.d.ts +19 -0
- package/dist/store/internal/read-existing.d.ts.map +1 -0
- package/dist/store/internal/read-existing.js +29 -0
- package/dist/store/internal/read-existing.js.map +1 -0
- package/dist/store/internal/score-direction.d.ts +32 -0
- package/dist/store/internal/score-direction.d.ts.map +1 -0
- package/dist/store/internal/score-direction.js +39 -0
- package/dist/store/internal/score-direction.js.map +1 -0
- 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 +13 -1
- package/dist/store/internal/setup.d.ts.map +1 -1
- package/dist/store/internal/setup.js +57 -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 +31 -6
- package/dist/store/internal/write-verify.d.ts.map +1 -1
- package/dist/store/internal/write-verify.js +48 -8
- package/dist/store/internal/write-verify.js.map +1 -1
- package/dist/store/types.d.ts +16 -0
- package/dist/store/types.d.ts.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
|
@@ -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":";;;AAEA,+CAAoG;AACpG,qCAAiD;AACjD,qCAAuD;AACvD,qCAAyC;AACzC,2CAAkD;AAClD,6CAA4D;AAE5D;;;GAGG;AACH;IACU,aAAa,CAAgC;IAC7C,cAAc,CAAuB;IACrC,SAAS,GAAG,KAAK,CAAC;IACT,UAAU,CAAS;IACnB,SAAS,CAAS;IAClB,cAAc,CAAS;IACvB,GAAG,CAAS;IACZ,WAAW,CAAU;IACrB,MAAM,CAAkB;IAEzC,YAAY,MAAuB;QACjC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;QACpC,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,IAAI,iCAAqB,CAAC;QAC3D,IAAI,CAAC,cAAc,GAAG,MAAM,CAAC,cAAc,IAAI,sCAA0B,CAAC;QAC1E,IAAI,CAAC,GAAG,GAAG,MAAM,CAAC,oBAAoB,IAAI,0BAAc,CAAC;QACzD,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC;IACxC,CAAC;IAEO,SAAS;QACf,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;YACxB,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY,IAAI,EAAE,CAAC;YAC3C,IAAI,CAAC,aAAa,GAAG,CACnB,IAAI,CAAC,MAAM,CAAC,cAAc;gBACxB,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,GAAG,GAAG,EAAE,CAAC,CAAC;gBACzE,CAAC,CAAC,IAAA,8BAAqB,EAAC,GAAG,CAAC,CAC/B,CAAC,IAAI,CACJ,CAAC,MAAM,EAAE,EAAE;gBACT,IAAI,CAAC,cAAc,GAAG,MAAM,CAAC;gBAC7B;;;mBAGG;gBACH,IAAI,IAAI,CAAC,SAAS;oBAAE,MAAM,CAAC,OAAO,EAAE,CAAC;gBACrC,OAAO,MAAM,CAAC;YAChB,CAAC,EACD,CAAC,KAAY,EAAE,EAAE;gBACf,IAAI,CAAC,aAAa,GAAG,SAAS,CAAC;gBAC/B,MAAM,KAAK,CAAC;YACd,CAAC,CACF,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC,aAAa,CAAC;IAC5B,CAAC;IAED,8DAA8D;IAC9D,aAAa,CAAC,IAAgB;QAC5B,OAAO,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,cAAc,CAAC;IAC5C,CAAC;IAED,gDAAgD;IAChD,QAAQ,CAAC,KAAwB;QAC/B,OAAO,IAAA,mBAAU,EAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAC3C,CAAC;IAED,iCAAiC;IACjC,YAAY;QACV,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED,oDAAoD;IACpD,KAAK,CAAC,MAAM,CAAC,GAAW,EAAE,IAAgB;QACxC,MAAM,IAAA,yBAAY,EAAC,MAAM,IAAI,CAAC,SAAS,EAAE,EAAE;YACzC,MAAM,EAAE,IAAI,CAAC,UAAU;YACvB,GAAG;YACH,IAAI;YACJ,oBAAoB,EAAE,IAAI,CAAC,GAAG;YAC9B,WAAW,EAAE,IAAI,CAAC,WAAW;SAC9B,CAAC,CAAC;QACH,OAAO,GAAG,CAAC;IACb,CAAC;IAED,6CAA6C;IAC7C,KAAK,CAAC,QAAQ,CAAC,GAAW;QACxB,OAAO,IAAA,2BAAc,EAAC,MAAM,IAAI,CAAC,SAAS,EAAE,EAAE,IAAI,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;IACtE,CAAC;IAED,+DAA+D;IAC/D,KAAK,CAAC,WAAW,CAAC,IAAc;QAC9B,OAAO,IAAA,sBAAa,EAAC,MAAM,IAAI,CAAC,SAAS,EAAE,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;IACtE,CAAC;IAED,iFAAiF;IACjF,KAAK,CAAC,mBAAmB,CAAC,OAAe;QACvC,OAAO,IAAA,+BAAmB,EAAC,MAAM,IAAI,CAAC,SAAS,EAAE,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAC/F,CAAC;IAED;;;;;OAKG;IACH,OAAO;QACL,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,cAAc,EAAE,OAAO,EAAE,CAAC;IACjC,CAAC;CACF"}
|
|
@@ -46,4 +46,19 @@ export declare const DEFAULT_RETRY_MAX_ATTEMPTS = 5;
|
|
|
46
46
|
export declare const MESSAGE_APPEND_RETRY_MAX_ATTEMPTS = 18;
|
|
47
47
|
/** Default cap on candidates the in-DB semantic ranker will score. */
|
|
48
48
|
export declare const DEFAULT_MAX_SEARCH_CANDIDATES = 1000;
|
|
49
|
+
/**
|
|
50
|
+
* Raw rows a single `listCheckpoints` call may pull before it warns. The read
|
|
51
|
+
* itself is deliberately unbounded — capping it counted raw rows rather than
|
|
52
|
+
* filter-matched ones, which turned a caller asking for a handful of rare
|
|
53
|
+
* matches over a large thread into a hard error instead of the true answer.
|
|
54
|
+
* The warning restores the operational signal without restoring the wrong
|
|
55
|
+
* error.
|
|
56
|
+
*
|
|
57
|
+
* Its own literal, deliberately: this is the point at which a scan is worth
|
|
58
|
+
* telling an operator about, which is independent of
|
|
59
|
+
* {@link MAX_TOTAL_ITEMS_IN_MEMORY}'s hard collection cap. Aliasing the two
|
|
60
|
+
* meant retuning the memory cap silently moved the warning as well, and it
|
|
61
|
+
* left the pair reported as a duplicate export.
|
|
62
|
+
*/
|
|
63
|
+
export declare const LIST_SCAN_WARN_THRESHOLD = 10000;
|
|
49
64
|
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/shared/constants.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,eAAO,MAAM,YAAY,QAAU,CAAC;AAEpC,oDAAoD;AACpD,eAAO,MAAM,eAAe,QAA2B,CAAC;AAExD,yEAAyE;AACzE,eAAO,MAAM,mBAAmB,OAAO,CAAC;AAExC,wEAAwE;AACxE,eAAO,MAAM,yBAAyB,QAAQ,CAAC;AAE/C,yDAAyD;AACzD,eAAO,MAAM,eAAe,KAAK,CAAC;AAElC,mDAAmD;AACnD,eAAO,MAAM,aAAa,MAAM,CAAC;AAEjC,mEAAmE;AACnE,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAE1C,2EAA2E;AAC3E,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAE5C,6CAA6C;AAC7C,eAAO,MAAM,oBAAoB,OAAO,CAAC;AAEzC,iDAAiD;AACjD,eAAO,MAAM,mBAAmB,OAAO,CAAC;AAExC,8FAA8F;AAC9F,eAAO,MAAM,0BAA0B,QAAa,CAAC;AAErD,oDAAoD;AACpD,eAAO,MAAM,qBAAqB,2BAA2B,CAAC;AAE9D,mDAAmD;AACnD,eAAO,MAAM,cAAc,WAAW,CAAC;AAEvC,yEAAyE;AACzE,eAAO,MAAM,6BAA6B,OAAO,CAAC;AAElD,6DAA6D;AAC7D,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAE3C,qEAAqE;AACrE,eAAO,MAAM,8BAA8B,QAAmB,CAAC;AAE/D,4DAA4D;AAC5D,eAAO,MAAM,0BAA0B,IAAI,CAAC;AAE5C;;;;;;;;;;GAUG;AACH,eAAO,MAAM,iCAAiC,KAAK,CAAC;AAEpD,sEAAsE;AACtE,eAAO,MAAM,6BAA6B,OAAO,CAAC"}
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/shared/constants.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,eAAO,MAAM,YAAY,QAAU,CAAC;AAEpC,oDAAoD;AACpD,eAAO,MAAM,eAAe,QAA2B,CAAC;AAExD,yEAAyE;AACzE,eAAO,MAAM,mBAAmB,OAAO,CAAC;AAExC,wEAAwE;AACxE,eAAO,MAAM,yBAAyB,QAAQ,CAAC;AAE/C,yDAAyD;AACzD,eAAO,MAAM,eAAe,KAAK,CAAC;AAElC,mDAAmD;AACnD,eAAO,MAAM,aAAa,MAAM,CAAC;AAEjC,mEAAmE;AACnE,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAE1C,2EAA2E;AAC3E,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAE5C,6CAA6C;AAC7C,eAAO,MAAM,oBAAoB,OAAO,CAAC;AAEzC,iDAAiD;AACjD,eAAO,MAAM,mBAAmB,OAAO,CAAC;AAExC,8FAA8F;AAC9F,eAAO,MAAM,0BAA0B,QAAa,CAAC;AAErD,oDAAoD;AACpD,eAAO,MAAM,qBAAqB,2BAA2B,CAAC;AAE9D,mDAAmD;AACnD,eAAO,MAAM,cAAc,WAAW,CAAC;AAEvC,yEAAyE;AACzE,eAAO,MAAM,6BAA6B,OAAO,CAAC;AAElD,6DAA6D;AAC7D,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAE3C,qEAAqE;AACrE,eAAO,MAAM,8BAA8B,QAAmB,CAAC;AAE/D,4DAA4D;AAC5D,eAAO,MAAM,0BAA0B,IAAI,CAAC;AAE5C;;;;;;;;;;GAUG;AACH,eAAO,MAAM,iCAAiC,KAAK,CAAC;AAEpD,sEAAsE;AACtE,eAAO,MAAM,6BAA6B,OAAO,CAAC;AAElD;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,wBAAwB,QAAQ,CAAC"}
|
package/dist/shared/constants.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DEFAULT_MAX_SEARCH_CANDIDATES = exports.MESSAGE_APPEND_RETRY_MAX_ATTEMPTS = exports.DEFAULT_RETRY_MAX_ATTEMPTS = exports.DEFAULT_MAX_DECOMPRESSED_BYTES = exports.DEFAULT_COMPRESSION_LEVEL = exports.DEFAULT_COMPRESSION_MIN_BYTES = exports.DEFAULT_S3_SSE = exports.DEFAULT_S3_KEY_PREFIX = exports.DEFAULT_S3_THRESHOLD_BYTES = exports.S3_DELETE_BATCH_MAX = exports.MAX_BACKOFF_DELAY_MS = exports.INITIAL_BACKOFF_DELAY_MS = exports.MAX_UNPROCESSED_RETRIES = exports.BATCH_GET_MAX = exports.BATCH_WRITE_MAX = exports.MAX_TOTAL_ITEMS_IN_MEMORY = exports.MAX_LOOP_ITERATIONS = exports.MAX_TTL_SECONDS = exports.MAX_TTL_DAYS = void 0;
|
|
3
|
+
exports.LIST_SCAN_WARN_THRESHOLD = exports.DEFAULT_MAX_SEARCH_CANDIDATES = exports.MESSAGE_APPEND_RETRY_MAX_ATTEMPTS = exports.DEFAULT_RETRY_MAX_ATTEMPTS = exports.DEFAULT_MAX_DECOMPRESSED_BYTES = exports.DEFAULT_COMPRESSION_LEVEL = exports.DEFAULT_COMPRESSION_MIN_BYTES = exports.DEFAULT_S3_SSE = exports.DEFAULT_S3_KEY_PREFIX = exports.DEFAULT_S3_THRESHOLD_BYTES = exports.S3_DELETE_BATCH_MAX = exports.MAX_BACKOFF_DELAY_MS = exports.INITIAL_BACKOFF_DELAY_MS = exports.MAX_UNPROCESSED_RETRIES = exports.BATCH_GET_MAX = exports.BATCH_WRITE_MAX = exports.MAX_TOTAL_ITEMS_IN_MEMORY = exports.MAX_LOOP_ITERATIONS = exports.MAX_TTL_SECONDS = exports.MAX_TTL_DAYS = void 0;
|
|
4
4
|
/** Maximum TTL expressed in days (5 years). */
|
|
5
5
|
exports.MAX_TTL_DAYS = 365 * 5;
|
|
6
6
|
/** Maximum TTL expressed in seconds (100 years). */
|
|
@@ -49,4 +49,19 @@ exports.DEFAULT_RETRY_MAX_ATTEMPTS = 5;
|
|
|
49
49
|
exports.MESSAGE_APPEND_RETRY_MAX_ATTEMPTS = 18;
|
|
50
50
|
/** Default cap on candidates the in-DB semantic ranker will score. */
|
|
51
51
|
exports.DEFAULT_MAX_SEARCH_CANDIDATES = 1000;
|
|
52
|
+
/**
|
|
53
|
+
* Raw rows a single `listCheckpoints` call may pull before it warns. The read
|
|
54
|
+
* itself is deliberately unbounded — capping it counted raw rows rather than
|
|
55
|
+
* filter-matched ones, which turned a caller asking for a handful of rare
|
|
56
|
+
* matches over a large thread into a hard error instead of the true answer.
|
|
57
|
+
* The warning restores the operational signal without restoring the wrong
|
|
58
|
+
* error.
|
|
59
|
+
*
|
|
60
|
+
* Its own literal, deliberately: this is the point at which a scan is worth
|
|
61
|
+
* telling an operator about, which is independent of
|
|
62
|
+
* {@link MAX_TOTAL_ITEMS_IN_MEMORY}'s hard collection cap. Aliasing the two
|
|
63
|
+
* meant retuning the memory cap silently moved the warning as well, and it
|
|
64
|
+
* left the pair reported as a duplicate export.
|
|
65
|
+
*/
|
|
66
|
+
exports.LIST_SCAN_WARN_THRESHOLD = 10000;
|
|
52
67
|
//# sourceMappingURL=constants.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/shared/constants.ts"],"names":[],"mappings":";;;AAAA,+CAA+C;AAClC,QAAA,YAAY,GAAG,GAAG,GAAG,CAAC,CAAC;AAEpC,oDAAoD;AACvC,QAAA,eAAe,GAAG,GAAG,GAAG,GAAG,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;AAExD,yEAAyE;AAC5D,QAAA,mBAAmB,GAAG,IAAI,CAAC;AAExC,wEAAwE;AAC3D,QAAA,yBAAyB,GAAG,KAAK,CAAC;AAE/C,yDAAyD;AAC5C,QAAA,eAAe,GAAG,EAAE,CAAC;AAElC,mDAAmD;AACtC,QAAA,aAAa,GAAG,GAAG,CAAC;AAEjC,mEAAmE;AACtD,QAAA,uBAAuB,GAAG,EAAE,CAAC;AAE1C,2EAA2E;AAC9D,QAAA,wBAAwB,GAAG,GAAG,CAAC;AAE5C,6CAA6C;AAChC,QAAA,oBAAoB,GAAG,IAAI,CAAC;AAEzC,iDAAiD;AACpC,QAAA,mBAAmB,GAAG,IAAI,CAAC;AAExC,8FAA8F;AACjF,QAAA,0BAA0B,GAAG,GAAG,GAAG,IAAI,CAAC;AAErD,oDAAoD;AACvC,QAAA,qBAAqB,GAAG,wBAAwB,CAAC;AAE9D,mDAAmD;AACtC,QAAA,cAAc,GAAG,QAAQ,CAAC;AAEvC,yEAAyE;AAC5D,QAAA,6BAA6B,GAAG,IAAI,CAAC;AAElD,6DAA6D;AAChD,QAAA,yBAAyB,GAAG,CAAC,CAAC;AAE3C,qEAAqE;AACxD,QAAA,8BAA8B,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;AAE/D,4DAA4D;AAC/C,QAAA,0BAA0B,GAAG,CAAC,CAAC;AAE5C;;;;;;;;;;GAUG;AACU,QAAA,iCAAiC,GAAG,EAAE,CAAC;AAEpD,sEAAsE;AACzD,QAAA,6BAA6B,GAAG,IAAI,CAAC"}
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/shared/constants.ts"],"names":[],"mappings":";;;AAAA,+CAA+C;AAClC,QAAA,YAAY,GAAG,GAAG,GAAG,CAAC,CAAC;AAEpC,oDAAoD;AACvC,QAAA,eAAe,GAAG,GAAG,GAAG,GAAG,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;AAExD,yEAAyE;AAC5D,QAAA,mBAAmB,GAAG,IAAI,CAAC;AAExC,wEAAwE;AAC3D,QAAA,yBAAyB,GAAG,KAAK,CAAC;AAE/C,yDAAyD;AAC5C,QAAA,eAAe,GAAG,EAAE,CAAC;AAElC,mDAAmD;AACtC,QAAA,aAAa,GAAG,GAAG,CAAC;AAEjC,mEAAmE;AACtD,QAAA,uBAAuB,GAAG,EAAE,CAAC;AAE1C,2EAA2E;AAC9D,QAAA,wBAAwB,GAAG,GAAG,CAAC;AAE5C,6CAA6C;AAChC,QAAA,oBAAoB,GAAG,IAAI,CAAC;AAEzC,iDAAiD;AACpC,QAAA,mBAAmB,GAAG,IAAI,CAAC;AAExC,8FAA8F;AACjF,QAAA,0BAA0B,GAAG,GAAG,GAAG,IAAI,CAAC;AAErD,oDAAoD;AACvC,QAAA,qBAAqB,GAAG,wBAAwB,CAAC;AAE9D,mDAAmD;AACtC,QAAA,cAAc,GAAG,QAAQ,CAAC;AAEvC,yEAAyE;AAC5D,QAAA,6BAA6B,GAAG,IAAI,CAAC;AAElD,6DAA6D;AAChD,QAAA,yBAAyB,GAAG,CAAC,CAAC;AAE3C,qEAAqE;AACxD,QAAA,8BAA8B,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;AAE/D,4DAA4D;AAC/C,QAAA,0BAA0B,GAAG,CAAC,CAAC;AAE5C;;;;;;;;;;GAUG;AACU,QAAA,iCAAiC,GAAG,EAAE,CAAC;AAEpD,sEAAsE;AACzD,QAAA,6BAA6B,GAAG,IAAI,CAAC;AAElD;;;;;;;;;;;;;GAaG;AACU,QAAA,wBAAwB,GAAG,KAAK,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Attribute holding a row's revision token on adapters that need one. The
|
|
3
|
+
* checkpointer's special writes reuse their existing per-call `writeGroup`
|
|
4
|
+
* instead, so `revisionGuard` takes the attribute name rather than assuming it.
|
|
5
|
+
*/
|
|
6
|
+
export declare const REVISION_ATTRIBUTE = "rev";
|
|
7
|
+
/**
|
|
8
|
+
* Compare-and-swap attempts before a caller gives up and overwrites
|
|
9
|
+
* unconditionally. Kept small on purpose: DynamoDB charges write capacity for a
|
|
10
|
+
* *failed* conditional write too, sized on the existing item, so an aggressive
|
|
11
|
+
* loop turns contention into cost. Three attempts settle every realistic race,
|
|
12
|
+
* and the fallback is exactly the pre-0.9.0 behaviour rather than an error.
|
|
13
|
+
*/
|
|
14
|
+
export declare const OVERWRITE_CAS_MAX_ATTEMPTS = 3;
|
|
15
|
+
/** What a caller saw at the row before it tried to overwrite it. */
|
|
16
|
+
export interface ObservedRow {
|
|
17
|
+
exists: boolean;
|
|
18
|
+
revision?: string;
|
|
19
|
+
}
|
|
20
|
+
/** Condition fragments to spread into a `PutCommand` input. */
|
|
21
|
+
export interface RevisionGuard {
|
|
22
|
+
ConditionExpression: string;
|
|
23
|
+
ExpressionAttributeNames?: Record<string, string>;
|
|
24
|
+
ExpressionAttributeValues?: Record<string, string>;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Build the condition admitting a write only while the row still holds the
|
|
28
|
+
* revision this caller observed.
|
|
29
|
+
*
|
|
30
|
+
* Without it, two concurrent overwrites both read the same previous payload
|
|
31
|
+
* descriptor, both commit their own nonced upload, and both delete that same
|
|
32
|
+
* previous object — leaving the loser's upload orphaned with nothing left
|
|
33
|
+
* recording that it ever existed. A post-commit read-back cannot repair that,
|
|
34
|
+
* because neither writer can learn of an object it never saw; only refusing the
|
|
35
|
+
* second write until it re-reads can.
|
|
36
|
+
*
|
|
37
|
+
* A row with no revision attribute was written before 0.9.0. Pinning its
|
|
38
|
+
* *absence* is what makes the swap correct across an upgrade: the first writer
|
|
39
|
+
* to touch such a row stamps one, and any racer still holding the pre-upgrade
|
|
40
|
+
* observation is turned away.
|
|
41
|
+
*/
|
|
42
|
+
export declare function revisionGuard(attribute: string, observed: ObservedRow): RevisionGuard;
|
|
43
|
+
/**
|
|
44
|
+
* True when the guard rejected a write — NOT evidence a competitor won: a
|
|
45
|
+
* `PutCommand` retried after its response was lost can re-hit its own
|
|
46
|
+
* committed row and fail identically; the two cases are indistinguishable.
|
|
47
|
+
*/
|
|
48
|
+
export declare function isConditionalCheckFailed(error: {
|
|
49
|
+
name?: string;
|
|
50
|
+
}): boolean;
|
|
51
|
+
//# sourceMappingURL=conditional-put.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conditional-put.d.ts","sourceRoot":"","sources":["../../../src/shared/dynamodb/conditional-put.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,QAAQ,CAAC;AAExC;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B,IAAI,CAAC;AAE5C,oEAAoE;AACpE,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,+DAA+D;AAC/D,MAAM,WAAW,aAAa;IAC5B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,wBAAwB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClD,yBAAyB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACpD;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,GAAG,aAAa,CAarF;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAE1E"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OVERWRITE_CAS_MAX_ATTEMPTS = exports.REVISION_ATTRIBUTE = void 0;
|
|
4
|
+
exports.revisionGuard = revisionGuard;
|
|
5
|
+
exports.isConditionalCheckFailed = isConditionalCheckFailed;
|
|
6
|
+
/**
|
|
7
|
+
* Attribute holding a row's revision token on adapters that need one. The
|
|
8
|
+
* checkpointer's special writes reuse their existing per-call `writeGroup`
|
|
9
|
+
* instead, so `revisionGuard` takes the attribute name rather than assuming it.
|
|
10
|
+
*/
|
|
11
|
+
exports.REVISION_ATTRIBUTE = 'rev';
|
|
12
|
+
/**
|
|
13
|
+
* Compare-and-swap attempts before a caller gives up and overwrites
|
|
14
|
+
* unconditionally. Kept small on purpose: DynamoDB charges write capacity for a
|
|
15
|
+
* *failed* conditional write too, sized on the existing item, so an aggressive
|
|
16
|
+
* loop turns contention into cost. Three attempts settle every realistic race,
|
|
17
|
+
* and the fallback is exactly the pre-0.9.0 behaviour rather than an error.
|
|
18
|
+
*/
|
|
19
|
+
exports.OVERWRITE_CAS_MAX_ATTEMPTS = 3;
|
|
20
|
+
/**
|
|
21
|
+
* Build the condition admitting a write only while the row still holds the
|
|
22
|
+
* revision this caller observed.
|
|
23
|
+
*
|
|
24
|
+
* Without it, two concurrent overwrites both read the same previous payload
|
|
25
|
+
* descriptor, both commit their own nonced upload, and both delete that same
|
|
26
|
+
* previous object — leaving the loser's upload orphaned with nothing left
|
|
27
|
+
* recording that it ever existed. A post-commit read-back cannot repair that,
|
|
28
|
+
* because neither writer can learn of an object it never saw; only refusing the
|
|
29
|
+
* second write until it re-reads can.
|
|
30
|
+
*
|
|
31
|
+
* A row with no revision attribute was written before 0.9.0. Pinning its
|
|
32
|
+
* *absence* is what makes the swap correct across an upgrade: the first writer
|
|
33
|
+
* to touch such a row stamps one, and any racer still holding the pre-upgrade
|
|
34
|
+
* observation is turned away.
|
|
35
|
+
*/
|
|
36
|
+
function revisionGuard(attribute, observed) {
|
|
37
|
+
if (!observed.exists)
|
|
38
|
+
return { ConditionExpression: 'attribute_not_exists(PK)' };
|
|
39
|
+
if (observed.revision === undefined) {
|
|
40
|
+
return {
|
|
41
|
+
ConditionExpression: 'attribute_not_exists(#rev)',
|
|
42
|
+
ExpressionAttributeNames: { '#rev': attribute },
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
ConditionExpression: '#rev = :rev',
|
|
47
|
+
ExpressionAttributeNames: { '#rev': attribute },
|
|
48
|
+
ExpressionAttributeValues: { ':rev': observed.revision },
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* True when the guard rejected a write — NOT evidence a competitor won: a
|
|
53
|
+
* `PutCommand` retried after its response was lost can re-hit its own
|
|
54
|
+
* committed row and fail identically; the two cases are indistinguishable.
|
|
55
|
+
*/
|
|
56
|
+
function isConditionalCheckFailed(error) {
|
|
57
|
+
return error.name === 'ConditionalCheckFailedException';
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=conditional-put.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conditional-put.js","sourceRoot":"","sources":["../../../src/shared/dynamodb/conditional-put.ts"],"names":[],"mappings":";;;;;AAAA;;;;GAIG;AACU,QAAA,kBAAkB,GAAG,KAAK,CAAC;AAExC;;;;;;GAMG;AACU,QAAA,0BAA0B,GAAG,CAAC,CAAC;AAe5C;;;;;;;;;;;;;;;GAeG;AACH,uBAA8B,SAAiB,EAAE,QAAqB;IACpE,IAAI,CAAC,QAAQ,CAAC,MAAM;QAAE,OAAO,EAAE,mBAAmB,EAAE,0BAA0B,EAAE,CAAC;IACjF,IAAI,QAAQ,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QACpC,OAAO;YACL,mBAAmB,EAAE,4BAA4B;YACjD,wBAAwB,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE;SAChD,CAAC;IACJ,CAAC;IACD,OAAO;QACL,mBAAmB,EAAE,aAAa;QAClC,wBAAwB,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE;QAC/C,yBAAyB,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,QAAQ,EAAE;KACzD,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,kCAAyC,KAAwB;IAC/D,OAAO,KAAK,CAAC,IAAI,KAAK,iCAAiC,CAAC;AAC1D,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { DynamoDBDocument, QueryCommandInput } from '@aws-sdk/lib-dynamodb';
|
|
2
|
+
import type { PayloadDescriptor } from '../codec/codec';
|
|
3
|
+
import type { S3Offloader } from '../codec/s3/offloader';
|
|
4
|
+
import type { Logger } from '../logging/logger';
|
|
5
|
+
import type { DocItem } from './types';
|
|
6
|
+
/** Collaborators and per-adapter policy for one partition-wide delete. */
|
|
7
|
+
export interface PartitionDeleteOptions {
|
|
8
|
+
client: DynamoDBDocument;
|
|
9
|
+
tableName: string;
|
|
10
|
+
params: QueryCommandInput;
|
|
11
|
+
logger: Logger;
|
|
12
|
+
offloader?: S3Offloader;
|
|
13
|
+
/** Label for log lines and S3-cleanup diagnostics, e.g. `deleteThread`. */
|
|
14
|
+
operation: string;
|
|
15
|
+
/**
|
|
16
|
+
* True when a sort key belongs to the calling adapter. A partition query
|
|
17
|
+
* carries no sort-key condition, so without this a shared-table partition
|
|
18
|
+
* holding a foreign row would have that row deleted too.
|
|
19
|
+
*/
|
|
20
|
+
ownsSortKey: (sortKey: string) => boolean;
|
|
21
|
+
/** The offloaded payload descriptors a row references, if any. */
|
|
22
|
+
descriptorsOf: (row: DocItem) => (PayloadDescriptor | undefined)[];
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Delete every row in a partition that belongs to the calling adapter,
|
|
26
|
+
* best-effort deleting any offloaded S3 objects. Streams the partition with
|
|
27
|
+
* unbounded pagination and flushes in batches, so a partition of any size is
|
|
28
|
+
* deleted to completion with bounded memory — never silently truncated at the
|
|
29
|
+
* in-memory page caps, and never discarding already-flushed progress if a
|
|
30
|
+
* later batch fails. Returns the number of rows deleted.
|
|
31
|
+
*/
|
|
32
|
+
export declare function deletePartitionRows(options: PartitionDeleteOptions): Promise<number>;
|
|
33
|
+
//# sourceMappingURL=partition-delete.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"partition-delete.d.ts","sourceRoot":"","sources":["../../../src/shared/dynamodb/partition-delete.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAEjF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAExD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAIzD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAGhD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEvC,0EAA0E;AAC1E,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,gBAAgB,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,2EAA2E;IAC3E,SAAS,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;IAC1C,kEAAkE;IAClE,aAAa,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,CAAC,iBAAiB,GAAG,SAAS,CAAC,EAAE,CAAC;CACpE;AA2DD;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,MAAM,CAAC,CA2B1F"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.deletePartitionRows = deletePartitionRows;
|
|
4
|
+
const descriptor_keys_1 = require("../codec/descriptor-keys");
|
|
5
|
+
const orphans_1 = require("../codec/s3/orphans");
|
|
6
|
+
const constants_1 = require("../constants");
|
|
7
|
+
const errors_1 = require("../errors/errors");
|
|
8
|
+
const batch_write_1 = require("./batch-write");
|
|
9
|
+
const paginate_1 = require("./paginate");
|
|
10
|
+
/** Delete the buffered keys, best-effort clean their S3 objects, then clear it. */
|
|
11
|
+
async function flushBuffer(options, buffer, progress) {
|
|
12
|
+
if (buffer.keys.length === 0)
|
|
13
|
+
return;
|
|
14
|
+
const chunks = Math.ceil(buffer.keys.length / constants_1.BATCH_WRITE_MAX);
|
|
15
|
+
try {
|
|
16
|
+
await (0, batch_write_1.batchWriteAll)(options.client, options.tableName, buffer.keys.map((Key) => ({ DeleteRequest: { Key } })));
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
/** batchWriteAll's only throw is a BatchWriteAllIncompleteError (see batch-write.ts). */
|
|
20
|
+
const failure = error;
|
|
21
|
+
throw new errors_1.BatchWriteAllIncompleteError(progress.succeededChunks + failure.succeededChunks, progress.totalChunks + failure.totalChunks, failure.failedChunks, progress.writes + failure.succeededCount);
|
|
22
|
+
}
|
|
23
|
+
progress.writes += buffer.keys.length;
|
|
24
|
+
progress.succeededChunks += chunks;
|
|
25
|
+
progress.totalChunks += chunks;
|
|
26
|
+
if (options.offloader) {
|
|
27
|
+
await (0, orphans_1.cleanUpS3Orphans)(options.offloader, (0, descriptor_keys_1.collectS3Keys)(buffer.descriptors), options.operation, options.logger);
|
|
28
|
+
}
|
|
29
|
+
buffer.keys = [];
|
|
30
|
+
buffer.descriptors = [];
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Delete every row in a partition that belongs to the calling adapter,
|
|
34
|
+
* best-effort deleting any offloaded S3 objects. Streams the partition with
|
|
35
|
+
* unbounded pagination and flushes in batches, so a partition of any size is
|
|
36
|
+
* deleted to completion with bounded memory — never silently truncated at the
|
|
37
|
+
* in-memory page caps, and never discarding already-flushed progress if a
|
|
38
|
+
* later batch fails. Returns the number of rows deleted.
|
|
39
|
+
*/
|
|
40
|
+
async function deletePartitionRows(options) {
|
|
41
|
+
const buffer = { keys: [], descriptors: [] };
|
|
42
|
+
const progress = { writes: 0, succeededChunks: 0, totalChunks: 0 };
|
|
43
|
+
let skipped = 0;
|
|
44
|
+
const pages = (0, paginate_1.paginateQuery)({
|
|
45
|
+
client: options.client,
|
|
46
|
+
params: options.params,
|
|
47
|
+
maxItems: Number.POSITIVE_INFINITY,
|
|
48
|
+
maxIterations: Number.POSITIVE_INFINITY,
|
|
49
|
+
});
|
|
50
|
+
for await (const row of pages) {
|
|
51
|
+
if (!options.ownsSortKey(row.SK)) {
|
|
52
|
+
skipped += 1;
|
|
53
|
+
options.logger.warn(`${options.operation}: left a foreign row in place`, {
|
|
54
|
+
sortKey: row.SK,
|
|
55
|
+
});
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
buffer.keys.push({ PK: row.PK, SK: row.SK });
|
|
59
|
+
for (const descriptor of options.descriptorsOf(row)) {
|
|
60
|
+
if (descriptor)
|
|
61
|
+
buffer.descriptors.push(descriptor);
|
|
62
|
+
}
|
|
63
|
+
if (buffer.keys.length >= constants_1.BATCH_WRITE_MAX)
|
|
64
|
+
await flushBuffer(options, buffer, progress);
|
|
65
|
+
}
|
|
66
|
+
await flushBuffer(options, buffer, progress);
|
|
67
|
+
options.logger.info(`${options.operation}: deleted rows`, { deleted: progress.writes, skipped });
|
|
68
|
+
return progress.writes;
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=partition-delete.js.map
|