@farukada/aws-langgraph-dynamodb-ts 1.0.0-rc.2 → 1.0.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 +390 -193
- package/dist/{backfill → cjs/backfill}/backfill.d.ts +15 -12
- package/dist/cjs/backfill/backfill.js +177 -0
- package/dist/{checkpointer → cjs/checkpointer}/actions/delete-thread.d.ts +1 -1
- package/dist/cjs/checkpointer/actions/delete-thread.js +26 -0
- package/dist/{checkpointer → cjs/checkpointer}/actions/get-tuple.d.ts +4 -3
- package/dist/cjs/checkpointer/actions/get-tuple.js +22 -0
- package/dist/{checkpointer → cjs/checkpointer}/actions/list.d.ts +7 -4
- package/dist/cjs/checkpointer/actions/list.js +70 -0
- package/dist/{checkpointer → cjs/checkpointer}/actions/put-writes.d.ts +8 -6
- package/dist/cjs/checkpointer/actions/put-writes.js +21 -0
- package/dist/{checkpointer → cjs/checkpointer}/actions/put.d.ts +21 -15
- package/dist/cjs/checkpointer/actions/put.js +79 -0
- package/dist/{checkpointer → cjs/checkpointer}/internal/delta-history.d.ts +38 -26
- package/dist/cjs/checkpointer/internal/delta-history.js +131 -0
- package/dist/{checkpointer → cjs/checkpointer}/internal/listing.d.ts +4 -4
- package/dist/cjs/checkpointer/internal/listing.js +104 -0
- package/dist/{checkpointer → cjs/checkpointer}/internal/parse.d.ts +51 -15
- package/dist/cjs/checkpointer/internal/parse.js +184 -0
- package/dist/{checkpointer → cjs/checkpointer}/internal/pending-writes.d.ts +64 -25
- package/dist/cjs/checkpointer/internal/pending-writes.js +241 -0
- package/dist/{checkpointer → cjs/checkpointer}/internal/read.d.ts +15 -10
- package/dist/cjs/checkpointer/internal/read.js +132 -0
- package/dist/{checkpointer → cjs/checkpointer}/internal/rows.d.ts +94 -21
- package/dist/cjs/checkpointer/internal/rows.js +356 -0
- package/dist/{checkpointer → cjs/checkpointer}/internal/setup.d.ts +13 -20
- package/dist/cjs/checkpointer/internal/setup.js +25 -0
- package/dist/{checkpointer → cjs/checkpointer}/saver.d.ts +72 -36
- package/dist/cjs/checkpointer/saver.js +56 -0
- package/dist/{checkpointer → cjs/checkpointer}/types.d.ts +1 -1
- package/dist/cjs/checkpointer/types.js +2 -0
- package/dist/{factory → cjs/factory}/factory.d.ts +25 -20
- package/dist/cjs/factory/factory.js +137 -0
- package/dist/{factory → cjs/factory}/types.d.ts +12 -12
- package/dist/cjs/factory/types.js +2 -0
- package/dist/{history → cjs/history}/actions/add-messages.d.ts +18 -10
- package/dist/cjs/history/actions/add-messages.js +17 -0
- package/dist/{history → cjs/history}/actions/clear.d.ts +1 -1
- package/dist/cjs/history/actions/clear.js +29 -0
- package/dist/{history → cjs/history}/actions/get-messages.d.ts +11 -9
- package/dist/cjs/history/actions/get-messages.js +58 -0
- package/dist/{history → cjs/history}/actions/list-sessions.d.ts +3 -3
- package/dist/cjs/history/actions/list-sessions.js +67 -0
- package/dist/{history → cjs/history}/actions/reconcile-count.d.ts +13 -9
- package/dist/cjs/history/actions/reconcile-count.js +8 -0
- package/dist/{history → cjs/history}/chat-message-history.d.ts +62 -30
- package/dist/cjs/history/chat-message-history.js +61 -0
- package/dist/{history → cjs/history}/internal/append.d.ts +64 -32
- package/dist/cjs/history/internal/append.js +267 -0
- package/dist/{history → cjs/history}/internal/message-read.d.ts +3 -3
- package/dist/cjs/history/internal/message-read.js +93 -0
- package/dist/{history → cjs/history}/internal/parse.d.ts +2 -2
- package/dist/cjs/history/internal/parse.js +113 -0
- package/dist/{history → cjs/history}/internal/rows.d.ts +11 -10
- package/dist/cjs/history/internal/rows.js +96 -0
- package/dist/{history → cjs/history}/internal/session.d.ts +41 -22
- package/dist/cjs/history/internal/session.js +296 -0
- package/dist/{history → cjs/history}/internal/setup.d.ts +2 -2
- package/dist/cjs/history/internal/setup.js +60 -0
- package/dist/{history → cjs/history}/session-adapter.d.ts +0 -6
- package/dist/cjs/history/session-adapter.js +38 -0
- package/dist/{history → cjs/history}/types.d.ts +18 -15
- package/dist/cjs/history/types.js +2 -0
- package/dist/{index.d.ts → cjs/index.d.ts} +27 -27
- package/dist/cjs/index.js +25 -0
- package/dist/cjs/package.json +1 -0
- package/dist/{shared → cjs/shared}/adapter.d.ts +27 -16
- package/dist/cjs/shared/adapter.js +70 -0
- package/dist/cjs/shared/clock.js +14 -0
- package/dist/{shared → cjs/shared}/codec/codec.d.ts +37 -20
- package/dist/cjs/shared/codec/codec.js +162 -0
- package/dist/{shared → cjs/shared}/codec/compression.d.ts +9 -4
- package/dist/cjs/shared/codec/compression.js +45 -0
- package/dist/cjs/shared/codec/json-serde.js +58 -0
- package/dist/{shared → cjs/shared}/codec/s3/client-types.d.ts +2 -1
- package/dist/cjs/shared/codec/s3/client-types.js +6 -0
- package/dist/{shared → cjs/shared}/codec/s3/client.d.ts +25 -7
- package/dist/cjs/shared/codec/s3/client.js +78 -0
- package/dist/{shared → cjs/shared}/codec/s3/config.d.ts +12 -7
- package/dist/cjs/shared/codec/s3/config.js +92 -0
- package/dist/{shared → cjs/shared}/codec/s3/lifecycle.d.ts +71 -17
- package/dist/cjs/shared/codec/s3/lifecycle.js +223 -0
- package/dist/{shared → cjs/shared}/codec/s3/offloader.d.ts +42 -29
- package/dist/cjs/shared/codec/s3/offloader.js +289 -0
- package/dist/cjs/shared/concurrency.js +31 -0
- package/dist/{shared → cjs/shared}/dynamodb/abort.d.ts +2 -2
- package/dist/cjs/shared/dynamodb/abort.js +16 -0
- package/dist/{shared → cjs/shared}/dynamodb/batch-write.d.ts +2 -2
- package/dist/cjs/shared/dynamodb/batch-write.js +79 -0
- package/dist/cjs/shared/dynamodb/cancellation.js +37 -0
- package/dist/{shared → cjs/shared}/dynamodb/client.d.ts +24 -22
- package/dist/cjs/shared/dynamodb/client.js +40 -0
- package/dist/{shared → cjs/shared}/dynamodb/idempotent-write.d.ts +64 -19
- package/dist/cjs/shared/dynamodb/idempotent-write.js +173 -0
- package/dist/{shared → cjs/shared}/dynamodb/paginate.d.ts +2 -2
- package/dist/cjs/shared/dynamodb/paginate.js +90 -0
- package/dist/{shared → cjs/shared}/dynamodb/partition-delete.d.ts +6 -6
- package/dist/cjs/shared/dynamodb/partition-delete.js +177 -0
- package/dist/{shared → cjs/shared}/dynamodb/recency-index.d.ts +27 -15
- package/dist/cjs/shared/dynamodb/recency-index.js +146 -0
- package/dist/{shared → cjs/shared}/dynamodb/retry.d.ts +37 -6
- package/dist/cjs/shared/dynamodb/retry.js +193 -0
- package/dist/cjs/shared/dynamodb/row-size.d.ts +33 -0
- package/dist/cjs/shared/dynamodb/row-size.js +30 -0
- package/dist/{shared → cjs/shared}/dynamodb/table-schema.d.ts +27 -18
- package/dist/cjs/shared/dynamodb/table-schema.js +52 -0
- package/dist/{shared → cjs/shared}/errors/base-error.d.ts +42 -7
- package/dist/cjs/shared/errors/base-error.js +73 -0
- package/dist/{shared → cjs/shared}/errors/boundary.d.ts +29 -14
- package/dist/cjs/shared/errors/boundary.js +61 -0
- package/dist/cjs/shared/errors/classify.d.ts +206 -0
- package/dist/cjs/shared/errors/classify.js +232 -0
- package/dist/{shared → cjs/shared}/errors/error-code.d.ts +17 -10
- package/dist/cjs/shared/errors/error-code.js +27 -0
- package/dist/{shared → cjs/shared}/errors/errors.d.ts +75 -9
- package/dist/cjs/shared/errors/errors.js +123 -0
- package/dist/cjs/shared/logging/logger.js +30 -0
- package/dist/{shared → cjs/shared}/logging/redaction.d.ts +8 -4
- package/dist/cjs/shared/logging/redaction.js +145 -0
- package/dist/{shared → cjs/shared}/logging/secret-patterns.d.ts +30 -7
- package/dist/cjs/shared/logging/secret-patterns.js +93 -0
- package/dist/cjs/shared/logging/truncate.js +31 -0
- package/dist/{shared → cjs/shared}/options.d.ts +27 -11
- package/dist/cjs/shared/options.js +2 -0
- package/dist/cjs/shared/ulid.js +83 -0
- package/dist/{shared → cjs/shared}/validation/collaborators.d.ts +21 -2
- package/dist/cjs/shared/validation/collaborators.js +79 -0
- package/dist/{shared → cjs/shared}/validation/option-shape.d.ts +7 -5
- package/dist/cjs/shared/validation/option-shape.js +31 -0
- package/dist/{shared → cjs/shared}/validation/options.d.ts +4 -4
- package/dist/cjs/shared/validation/options.js +166 -0
- package/dist/cjs/shared/validation/primitives.js +114 -0
- package/dist/{shared → cjs/shared}/validation/ttl.d.ts +26 -9
- package/dist/cjs/shared/validation/ttl.js +52 -0
- package/dist/{store → cjs/store}/actions/list-namespaces.d.ts +5 -5
- package/dist/cjs/store/actions/list-namespaces.js +92 -0
- package/dist/{store → cjs/store}/actions/put.d.ts +11 -4
- package/dist/cjs/store/actions/put.js +49 -0
- package/dist/{store → cjs/store}/actions/reconcile-vector-index.d.ts +5 -5
- package/dist/cjs/store/actions/reconcile-vector-index.js +13 -0
- package/dist/{store → cjs/store}/actions/search.d.ts +2 -2
- package/dist/cjs/store/actions/search.js +26 -0
- package/dist/cjs/store/internal/batch-plan.d.ts +56 -0
- package/dist/cjs/store/internal/batch-plan.js +32 -0
- package/dist/{store → cjs/store}/internal/filter.d.ts +3 -3
- package/dist/cjs/store/internal/filter.js +64 -0
- package/dist/cjs/store/internal/get-item.d.ts +77 -0
- package/dist/cjs/store/internal/get-item.js +58 -0
- package/dist/{store → cjs/store}/internal/item-write.d.ts +72 -32
- package/dist/cjs/store/internal/item-write.js +181 -0
- package/dist/{store → cjs/store}/internal/parse.d.ts +15 -10
- package/dist/cjs/store/internal/parse.js +180 -0
- package/dist/{store → cjs/store}/internal/rows.d.ts +38 -34
- package/dist/cjs/store/internal/rows.js +166 -0
- package/dist/{store → cjs/store}/internal/semantic-search.d.ts +2 -2
- package/dist/cjs/store/internal/semantic-search.js +211 -0
- package/dist/{store → cjs/store}/internal/setup.d.ts +10 -15
- package/dist/cjs/store/internal/setup.js +103 -0
- package/dist/{store → cjs/store}/internal/table-search.d.ts +5 -5
- package/dist/cjs/store/internal/table-search.js +123 -0
- package/dist/{store → cjs/store}/internal/vector-index.d.ts +26 -15
- package/dist/cjs/store/internal/vector-index.js +269 -0
- package/dist/{store → cjs/store}/store.d.ts +82 -39
- package/dist/cjs/store/store.js +97 -0
- package/dist/{store → cjs/store}/types.d.ts +25 -10
- package/dist/cjs/store/types.js +2 -0
- package/dist/cjs/store/vector-backend.js +4 -0
- package/dist/esm/backfill/backfill.d.ts +171 -0
- package/dist/esm/backfill/backfill.js +170 -0
- package/dist/{checkpointer/actions/delete-thread.js → esm/checkpointer/actions/delete-thread.d.ts} +4 -26
- package/dist/esm/checkpointer/actions/delete-thread.js +23 -0
- package/dist/{checkpointer/actions/get-tuple.js → esm/checkpointer/actions/get-tuple.d.ts} +7 -24
- package/dist/esm/checkpointer/actions/get-tuple.js +19 -0
- package/dist/esm/checkpointer/actions/list.d.ts +55 -0
- package/dist/esm/checkpointer/actions/list.js +67 -0
- package/dist/{checkpointer/actions/put-writes.js → esm/checkpointer/actions/put-writes.d.ts} +10 -37
- package/dist/esm/checkpointer/actions/put-writes.js +18 -0
- package/dist/esm/checkpointer/actions/put.d.ts +95 -0
- package/dist/esm/checkpointer/actions/put.js +75 -0
- package/dist/esm/checkpointer/internal/delta-history.d.ts +124 -0
- package/dist/esm/checkpointer/internal/delta-history.js +126 -0
- package/dist/{checkpointer/internal/listing.js → esm/checkpointer/internal/listing.d.ts} +22 -118
- package/dist/esm/checkpointer/internal/listing.js +95 -0
- package/dist/esm/checkpointer/internal/parse.d.ts +298 -0
- package/dist/esm/checkpointer/internal/parse.js +169 -0
- package/dist/esm/checkpointer/internal/pending-writes.d.ts +314 -0
- package/dist/esm/checkpointer/internal/pending-writes.js +229 -0
- package/dist/esm/checkpointer/internal/read.d.ts +135 -0
- package/dist/esm/checkpointer/internal/read.js +125 -0
- package/dist/esm/checkpointer/internal/rows.d.ts +644 -0
- package/dist/esm/checkpointer/internal/rows.js +323 -0
- package/dist/esm/checkpointer/internal/setup.d.ts +47 -0
- package/dist/esm/checkpointer/internal/setup.js +21 -0
- package/dist/{checkpointer/saver.js → esm/checkpointer/saver.d.ts} +84 -87
- package/dist/esm/checkpointer/saver.js +52 -0
- package/dist/esm/checkpointer/types.d.ts +51 -0
- package/dist/esm/checkpointer/types.js +1 -0
- package/dist/esm/factory/factory.d.ts +154 -0
- package/dist/esm/factory/factory.js +133 -0
- package/dist/esm/factory/types.d.ts +76 -0
- package/dist/esm/factory/types.js +1 -0
- package/dist/{history/actions/add-messages.js → esm/history/actions/add-messages.d.ts} +20 -26
- package/dist/esm/history/actions/add-messages.js +14 -0
- package/dist/{history/actions/clear.js → esm/history/actions/clear.d.ts} +4 -35
- package/dist/esm/history/actions/clear.js +26 -0
- package/dist/esm/history/actions/get-messages.d.ts +60 -0
- package/dist/esm/history/actions/get-messages.js +55 -0
- package/dist/esm/history/actions/list-sessions.d.ts +55 -0
- package/dist/esm/history/actions/list-sessions.js +64 -0
- package/dist/{history/actions/reconcile-count.js → esm/history/actions/reconcile-count.d.ts} +14 -16
- package/dist/esm/history/actions/reconcile-count.js +5 -0
- package/dist/{history/chat-message-history.js → esm/history/chat-message-history.d.ts} +76 -87
- package/dist/esm/history/chat-message-history.js +57 -0
- package/dist/esm/history/internal/append.d.ts +244 -0
- package/dist/esm/history/internal/append.js +259 -0
- package/dist/esm/history/internal/message-read.d.ts +84 -0
- package/dist/esm/history/internal/message-read.js +89 -0
- package/dist/esm/history/internal/parse.d.ts +153 -0
- package/dist/esm/history/internal/parse.js +105 -0
- package/dist/{history/internal/rows.js → esm/history/internal/rows.d.ts} +58 -112
- package/dist/esm/history/internal/rows.js +83 -0
- package/dist/esm/history/internal/session.d.ts +350 -0
- package/dist/esm/history/internal/session.js +285 -0
- package/dist/esm/history/internal/setup.d.ts +64 -0
- package/dist/esm/history/internal/setup.js +56 -0
- package/dist/{history/session-adapter.js → esm/history/session-adapter.d.ts} +25 -39
- package/dist/esm/history/session-adapter.js +34 -0
- package/dist/esm/history/types.d.ts +102 -0
- package/dist/esm/history/types.js +1 -0
- package/dist/esm/index.d.ts +53 -0
- package/dist/esm/index.js +10 -0
- package/dist/esm/shared/adapter.d.ts +146 -0
- package/dist/esm/shared/adapter.js +65 -0
- package/dist/{shared/clock.js → esm/shared/clock.d.ts} +3 -14
- package/dist/esm/shared/clock.js +9 -0
- package/dist/esm/shared/codec/codec.d.ts +336 -0
- package/dist/esm/shared/codec/codec.js +150 -0
- package/dist/esm/shared/codec/compression.d.ts +66 -0
- package/dist/esm/shared/codec/compression.js +40 -0
- package/dist/esm/shared/codec/json-serde.d.ts +80 -0
- package/dist/esm/shared/codec/json-serde.js +54 -0
- package/dist/esm/shared/codec/s3/client-types.d.ts +54 -0
- package/dist/esm/shared/codec/s3/client-types.js +3 -0
- package/dist/esm/shared/codec/s3/client.d.ts +63 -0
- package/dist/esm/shared/codec/s3/client.js +40 -0
- package/dist/{shared/codec/s3/config.js → esm/shared/codec/s3/config.d.ts} +45 -93
- package/dist/esm/shared/codec/s3/config.js +79 -0
- package/dist/esm/shared/codec/s3/lifecycle.d.ts +220 -0
- package/dist/esm/shared/codec/s3/lifecycle.js +214 -0
- package/dist/esm/shared/codec/s3/offloader.d.ts +428 -0
- package/dist/esm/shared/codec/s3/offloader.js +278 -0
- package/dist/{shared/concurrency.js → esm/shared/concurrency.d.ts} +2 -37
- package/dist/esm/shared/concurrency.js +27 -0
- package/dist/{shared/dynamodb/abort.js → esm/shared/dynamodb/abort.d.ts} +4 -16
- package/dist/esm/shared/dynamodb/abort.js +12 -0
- package/dist/esm/shared/dynamodb/batch-write.d.ts +86 -0
- package/dist/esm/shared/dynamodb/batch-write.js +74 -0
- package/dist/{shared/dynamodb/cancellation.js → esm/shared/dynamodb/cancellation.d.ts} +25 -53
- package/dist/esm/shared/dynamodb/cancellation.js +30 -0
- package/dist/{shared/dynamodb/client.js → esm/shared/dynamodb/client.d.ts} +74 -64
- package/dist/esm/shared/dynamodb/client.js +35 -0
- package/dist/{shared/dynamodb/idempotent-write.js → esm/shared/dynamodb/idempotent-write.d.ts} +172 -169
- package/dist/esm/shared/dynamodb/idempotent-write.js +153 -0
- package/dist/esm/shared/dynamodb/paginate.d.ts +111 -0
- package/dist/esm/shared/dynamodb/paginate.js +84 -0
- package/dist/esm/shared/dynamodb/partition-delete.d.ts +204 -0
- package/dist/esm/shared/dynamodb/partition-delete.js +171 -0
- package/dist/esm/shared/dynamodb/recency-index.d.ts +243 -0
- package/dist/esm/shared/dynamodb/recency-index.js +136 -0
- package/dist/esm/shared/dynamodb/retry.d.ts +317 -0
- package/dist/esm/shared/dynamodb/retry.js +180 -0
- package/dist/esm/shared/dynamodb/row-size.d.ts +33 -0
- package/dist/esm/shared/dynamodb/row-size.js +26 -0
- package/dist/{shared/dynamodb/table-schema.js → esm/shared/dynamodb/table-schema.d.ts} +57 -67
- package/dist/esm/shared/dynamodb/table-schema.js +43 -0
- package/dist/esm/shared/errors/base-error.d.ts +231 -0
- package/dist/esm/shared/errors/base-error.js +64 -0
- package/dist/esm/shared/errors/boundary.d.ts +86 -0
- package/dist/esm/shared/errors/boundary.js +54 -0
- package/dist/esm/shared/errors/classify.d.ts +206 -0
- package/dist/esm/shared/errors/classify.js +220 -0
- package/dist/{shared/errors/error-code.js → esm/shared/errors/error-code.d.ts} +39 -43
- package/dist/esm/shared/errors/error-code.js +24 -0
- package/dist/{shared/errors/errors.js → esm/shared/errors/errors.d.ts} +92 -98
- package/dist/esm/shared/errors/errors.js +110 -0
- package/dist/{shared/logging/logger.js → esm/shared/logging/logger.d.ts} +22 -52
- package/dist/esm/shared/logging/logger.js +25 -0
- package/dist/esm/shared/logging/redaction.d.ts +123 -0
- package/dist/esm/shared/logging/redaction.js +140 -0
- package/dist/{shared/logging/secret-patterns.js → esm/shared/logging/secret-patterns.d.ts} +46 -87
- package/dist/esm/shared/logging/secret-patterns.js +83 -0
- package/dist/{shared/logging/truncate.js → esm/shared/logging/truncate.d.ts} +6 -40
- package/dist/esm/shared/logging/truncate.js +25 -0
- package/dist/esm/shared/options.d.ts +100 -0
- package/dist/esm/shared/options.js +1 -0
- package/dist/{shared/ulid.js → esm/shared/ulid.d.ts} +4 -84
- package/dist/esm/shared/ulid.js +77 -0
- package/dist/{shared/validation/collaborators.js → esm/shared/validation/collaborators.d.ts} +37 -65
- package/dist/esm/shared/validation/collaborators.js +70 -0
- package/dist/{shared/validation/option-shape.js → esm/shared/validation/option-shape.d.ts} +14 -36
- package/dist/esm/shared/validation/option-shape.js +24 -0
- package/dist/esm/shared/validation/options.d.ts +145 -0
- package/dist/esm/shared/validation/options.js +156 -0
- package/dist/{shared/validation/primitives.js → esm/shared/validation/primitives.d.ts} +30 -125
- package/dist/esm/shared/validation/primitives.js +100 -0
- package/dist/esm/shared/validation/ttl.d.ts +94 -0
- package/dist/esm/shared/validation/ttl.js +46 -0
- package/dist/esm/store/actions/list-namespaces.d.ts +79 -0
- package/dist/esm/store/actions/list-namespaces.js +86 -0
- package/dist/esm/store/actions/put.d.ts +43 -0
- package/dist/esm/store/actions/put.js +46 -0
- package/dist/{store/actions/reconcile-vector-index.js → esm/store/actions/reconcile-vector-index.d.ts} +8 -16
- package/dist/esm/store/actions/reconcile-vector-index.js +10 -0
- package/dist/esm/store/actions/search.d.ts +38 -0
- package/dist/esm/store/actions/search.js +23 -0
- package/dist/esm/store/internal/batch-plan.d.ts +56 -0
- package/dist/esm/store/internal/batch-plan.js +28 -0
- package/dist/esm/store/internal/filter.d.ts +43 -0
- package/dist/esm/store/internal/filter.js +60 -0
- package/dist/esm/store/internal/get-item.d.ts +77 -0
- package/dist/esm/store/internal/get-item.js +54 -0
- package/dist/esm/store/internal/item-write.d.ts +270 -0
- package/dist/esm/store/internal/item-write.js +173 -0
- package/dist/esm/store/internal/parse.d.ts +230 -0
- package/dist/esm/store/internal/parse.js +169 -0
- package/dist/{store/internal/rows.js → esm/store/internal/rows.d.ts} +111 -199
- package/dist/esm/store/internal/rows.js +147 -0
- package/dist/esm/store/internal/semantic-search.d.ts +168 -0
- package/dist/esm/store/internal/semantic-search.js +200 -0
- package/dist/esm/store/internal/setup.d.ts +96 -0
- package/dist/esm/store/internal/setup.js +98 -0
- package/dist/esm/store/internal/table-search.d.ts +100 -0
- package/dist/esm/store/internal/table-search.js +119 -0
- package/dist/esm/store/internal/vector-index.d.ts +258 -0
- package/dist/esm/store/internal/vector-index.js +256 -0
- package/dist/{store/store.js → esm/store/store.d.ts} +99 -133
- package/dist/esm/store/store.js +93 -0
- package/dist/esm/store/types.d.ts +111 -0
- package/dist/esm/store/types.js +1 -0
- package/dist/esm/store/vector-backend.d.ts +104 -0
- package/dist/esm/store/vector-backend.js +1 -0
- package/package.json +50 -44
- package/dist/backfill/backfill.js +0 -393
- package/dist/checkpointer/actions/list.js +0 -142
- package/dist/checkpointer/actions/put.js +0 -195
- package/dist/checkpointer/internal/delta-history.js +0 -252
- package/dist/checkpointer/internal/parse.js +0 -372
- package/dist/checkpointer/internal/pending-writes.js +0 -588
- package/dist/checkpointer/internal/read.js +0 -264
- package/dist/checkpointer/internal/rows.js +0 -834
- package/dist/checkpointer/internal/setup.js +0 -72
- package/dist/checkpointer/types.js +0 -12
- package/dist/factory/factory.js +0 -266
- package/dist/factory/types.js +0 -10
- package/dist/history/actions/get-messages.js +0 -141
- package/dist/history/actions/list-sessions.js +0 -156
- package/dist/history/internal/append.js +0 -500
- package/dist/history/internal/message-read.js +0 -204
- package/dist/history/internal/parse.js +0 -252
- package/dist/history/internal/session.js +0 -628
- package/dist/history/internal/setup.js +0 -106
- package/dist/history/types.js +0 -12
- package/dist/index.js +0 -51
- package/dist/shared/adapter.js +0 -143
- package/dist/shared/codec/codec.js +0 -441
- package/dist/shared/codec/compression.js +0 -89
- package/dist/shared/codec/json-serde.js +0 -191
- package/dist/shared/codec/s3/client-types.js +0 -26
- package/dist/shared/codec/s3/client.js +0 -97
- package/dist/shared/codec/s3/lifecycle.js +0 -355
- package/dist/shared/codec/s3/offloader.js +0 -658
- package/dist/shared/dynamodb/batch-write.js +0 -173
- package/dist/shared/dynamodb/paginate.js +0 -188
- package/dist/shared/dynamodb/partition-delete.js +0 -340
- package/dist/shared/dynamodb/recency-index.js +0 -377
- package/dist/shared/dynamodb/retry.js +0 -463
- package/dist/shared/errors/base-error.js +0 -174
- package/dist/shared/errors/boundary.js +0 -143
- package/dist/shared/errors/classify.d.ts +0 -97
- package/dist/shared/errors/classify.js +0 -257
- package/dist/shared/logging/redaction.js +0 -316
- package/dist/shared/options.js +0 -11
- package/dist/shared/validation/options.js +0 -328
- package/dist/shared/validation/ttl.js +0 -132
- package/dist/store/actions/list-namespaces.js +0 -197
- package/dist/store/actions/put.js +0 -78
- package/dist/store/actions/search.js +0 -66
- package/dist/store/internal/batch-plan.d.ts +0 -26
- package/dist/store/internal/batch-plan.js +0 -109
- package/dist/store/internal/filter.js +0 -137
- package/dist/store/internal/get-item.d.ts +0 -45
- package/dist/store/internal/get-item.js +0 -115
- package/dist/store/internal/item-write.js +0 -463
- package/dist/store/internal/parse.js +0 -350
- package/dist/store/internal/semantic-search.js +0 -389
- package/dist/store/internal/setup.js +0 -223
- package/dist/store/internal/table-search.js +0 -213
- package/dist/store/internal/vector-index.js +0 -546
- package/dist/store/types.js +0 -15
- package/dist/store/vector-backend.js +0 -17
- /package/dist/{shared → cjs/shared}/clock.d.ts +0 -0
- /package/dist/{shared → cjs/shared}/codec/json-serde.d.ts +0 -0
- /package/dist/{shared → cjs/shared}/concurrency.d.ts +0 -0
- /package/dist/{shared → cjs/shared}/dynamodb/cancellation.d.ts +0 -0
- /package/dist/{shared → cjs/shared}/logging/logger.d.ts +0 -0
- /package/dist/{shared → cjs/shared}/logging/truncate.d.ts +0 -0
- /package/dist/{shared → cjs/shared}/ulid.d.ts +0 -0
- /package/dist/{shared → cjs/shared}/validation/primitives.d.ts +0 -0
- /package/dist/{store → cjs/store}/vector-backend.d.ts +0 -0
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
* merges them newest first, and hands out an opaque cursor that resumes the
|
|
8
8
|
* merge. The shard function, the key format and the merge are decided here.
|
|
9
9
|
*/
|
|
10
|
-
import { type PageLimit } from '../validation/primitives';
|
|
11
|
-
import type { AttributeMap, DynamoDBDocumentLike } from './client';
|
|
12
|
-
import { type RetryOptions } from './retry';
|
|
10
|
+
import { type PageLimit } from '../validation/primitives.js';
|
|
11
|
+
import type { AttributeMap, DynamoDBDocumentLike } from './client.js';
|
|
12
|
+
import { type RetryOptions } from './retry.js';
|
|
13
13
|
/** One page of a recency listing, and where the next one resumes. */
|
|
14
14
|
export interface IndexPage {
|
|
15
15
|
items: AttributeMap[];
|
|
@@ -81,8 +81,12 @@ export declare function queryRecencyIndex(options: IndexQueryOptions): Promise<I
|
|
|
81
81
|
* Throws: as {@link queryRecencyIndex}.
|
|
82
82
|
*/
|
|
83
83
|
export declare function iterateRecencyIndex(options: Omit<IndexQueryOptions, 'limit' | 'cursor'>): AsyncGenerator<AttributeMap>;
|
|
84
|
-
/**
|
|
85
|
-
|
|
84
|
+
/**
|
|
85
|
+
* The adapter tags that scope GSI1: the checkpointer's own partition tag, and
|
|
86
|
+
* `SESS` for the history's session rows — not its `HIST` partition tag, which
|
|
87
|
+
* names a whole conversation where this index lists one row of it.
|
|
88
|
+
*/
|
|
89
|
+
export type IndexTag = 'CHKPT' | 'SESS';
|
|
86
90
|
/** How a row appears in the recency index: its adapter's tag, its identity, and its time. */
|
|
87
91
|
export interface IndexTarget {
|
|
88
92
|
tag: IndexTag;
|
|
@@ -101,10 +105,14 @@ export declare const BACKFILLED_AT = "1970-01-01T00:00:00.000Z";
|
|
|
101
105
|
* Throws: nothing.
|
|
102
106
|
*/
|
|
103
107
|
export declare function backfilledAt(recorded: AttributeMap[string]): string;
|
|
108
|
+
/** The index's partition-key attribute: `<tag>#<shard>`, the one name every writer, the backfill and the listing spell. */
|
|
109
|
+
export declare const INDEX_PARTITION_ATTRIBUTE = "gsi1pk";
|
|
110
|
+
/** The index's sort-key attribute: `<updatedAt>#<id>`, or the digest form past the sort-key cap. */
|
|
111
|
+
export declare const INDEX_SORT_ATTRIBUTE = "gsi1sk";
|
|
104
112
|
/** The two attributes a row carries to appear in GSI1. */
|
|
105
113
|
export interface IndexKeys {
|
|
106
|
-
|
|
107
|
-
|
|
114
|
+
[INDEX_PARTITION_ATTRIBUTE]: string;
|
|
115
|
+
[INDEX_SORT_ATTRIBUTE]: string;
|
|
108
116
|
}
|
|
109
117
|
/** Default number of index partitions per adapter. */
|
|
110
118
|
export declare const DEFAULT_INDEX_SHARDS = 8;
|
|
@@ -128,17 +136,21 @@ export declare const MAX_INDEX_SHARDS = 1024;
|
|
|
128
136
|
*
|
|
129
137
|
* The sort key leads with an ISO-8601 timestamp, used unparsed: its byte order
|
|
130
138
|
* already is its chronological order, so a recency listing is a key condition
|
|
131
|
-
* rather than an in-memory sort. The row's own id
|
|
132
|
-
*
|
|
133
|
-
*
|
|
139
|
+
* rather than an in-memory sort. The row's own id, or its SHA-256 digest once
|
|
140
|
+
* the composed key would pass DynamoDB's 1024-byte sort-key cap
|
|
141
|
+
* ({@link indexSortKey}), follows it, which makes the key total — two rows
|
|
142
|
+
* written in the same millisecond still order, so a cursor can never loop.
|
|
134
143
|
*
|
|
135
144
|
* Accepts: `tag` — the adapter's. `id` — the row's own identifier, which
|
|
136
145
|
* decides its shard and breaks ties in the sort key. `at` — an ISO-8601
|
|
137
|
-
* instant. `shards` — index partitions per adapter, at least 1; fixed
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
*
|
|
141
|
-
*
|
|
146
|
+
* instant. `shards` — index partitions per adapter, at least 1; fixed for the
|
|
147
|
+
* table's life once rows carry keys, since `backfillRecencyIndex` writes keys
|
|
148
|
+
* only to rows that have none and so can never move a row already on a
|
|
149
|
+
* shard — raising the count is safe, since a listing still queries the old
|
|
150
|
+
* shards too, and lowering it hides the rows already on a dropped shard.
|
|
151
|
+
*
|
|
152
|
+
* Returns: the two index attributes; an id whose composed sort key would pass
|
|
153
|
+
* 1024 bytes is carried as its SHA-256 digest.
|
|
142
154
|
*
|
|
143
155
|
* Throws: `VALIDATION` naming `indexShards` for a count below 1 — the read
|
|
144
156
|
* side built an empty partition list from such a value and reported an empty
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MAX_INDEX_SHARDS = exports.DEFAULT_INDEX_SHARDS = exports.INDEX_SORT_ATTRIBUTE = exports.INDEX_PARTITION_ATTRIBUTE = exports.BACKFILLED_AT = void 0;
|
|
4
|
+
exports.queryRecencyIndex = queryRecencyIndex;
|
|
5
|
+
exports.iterateRecencyIndex = iterateRecencyIndex;
|
|
6
|
+
exports.backfilledAt = backfilledAt;
|
|
7
|
+
exports.indexKeys = indexKeys;
|
|
8
|
+
exports.indexPartitions = indexPartitions;
|
|
9
|
+
exports.shardReader = shardReader;
|
|
10
|
+
exports.readShardPage = readShardPage;
|
|
11
|
+
const node_crypto_1 = require("node:crypto");
|
|
12
|
+
const concurrency_js_1 = require("../concurrency.js");
|
|
13
|
+
const errors_js_1 = require("../errors/errors.js");
|
|
14
|
+
const primitives_js_1 = require("../validation/primitives.js");
|
|
15
|
+
const paginate_js_1 = require("./paginate.js");
|
|
16
|
+
const retry_js_1 = require("./retry.js");
|
|
17
|
+
const table_schema_js_1 = require("./table-schema.js");
|
|
18
|
+
function encodeCursor(sortKey) {
|
|
19
|
+
return Buffer.from(sortKey, 'utf8').toString('base64url');
|
|
20
|
+
}
|
|
21
|
+
function decodeCursor(cursor) {
|
|
22
|
+
const decoded = Buffer.from(cursor, 'base64url').toString('utf8');
|
|
23
|
+
if (!decoded.includes('#')) {
|
|
24
|
+
throw (0, errors_js_1.validationError)('cursor is not one this adapter issued', 'cursor');
|
|
25
|
+
}
|
|
26
|
+
return decoded;
|
|
27
|
+
}
|
|
28
|
+
function isDry(reader) {
|
|
29
|
+
return reader.buffer.length === 0 && !reader.exhausted;
|
|
30
|
+
}
|
|
31
|
+
async function refillDryShards(options, readers, before, needed) {
|
|
32
|
+
for (let dry = readers.filter(isDry); dry.length > 0; dry = readers.filter(isDry)) {
|
|
33
|
+
await (0, concurrency_js_1.mapWithConcurrency)(dry, options.concurrency, (reader) => readShardPage(options, reader, before, needed));
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function takeNewest(readers) {
|
|
37
|
+
let newest;
|
|
38
|
+
let newestKey = '';
|
|
39
|
+
for (const reader of readers) {
|
|
40
|
+
const head = reader.buffer[reader.buffer.length - 1];
|
|
41
|
+
if (head !== undefined && (0, table_schema_js_1.compareSortKeys)(head.gsi1sk, newestKey) > 0) {
|
|
42
|
+
newest = reader;
|
|
43
|
+
newestKey = head.gsi1sk;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return newest?.buffer.pop();
|
|
47
|
+
}
|
|
48
|
+
async function queryRecencyIndex(options) {
|
|
49
|
+
if (options.limit === 0)
|
|
50
|
+
return { items: [] };
|
|
51
|
+
const before = options.cursor === undefined ? undefined : decodeCursor(options.cursor);
|
|
52
|
+
const readers = indexPartitions(options.tag, options.shards).map((partition) => shardReader(partition));
|
|
53
|
+
const items = [];
|
|
54
|
+
while (items.length < options.limit) {
|
|
55
|
+
await refillDryShards(options, readers, before, options.limit - items.length);
|
|
56
|
+
const row = takeNewest(readers);
|
|
57
|
+
if (row === undefined)
|
|
58
|
+
break;
|
|
59
|
+
items.push(row);
|
|
60
|
+
}
|
|
61
|
+
const remain = readers.some((reader) => reader.buffer.length > 0 || !reader.exhausted);
|
|
62
|
+
return {
|
|
63
|
+
items,
|
|
64
|
+
...(remain ? { nextCursor: encodeCursor(items[items.length - 1].gsi1sk) } : {}),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
const STREAM_PAGE_SIZE = (0, primitives_js_1.parseLimit)(100, 0);
|
|
68
|
+
async function* iterateRecencyIndex(options) {
|
|
69
|
+
let cursor;
|
|
70
|
+
do {
|
|
71
|
+
const page = await queryRecencyIndex({ ...options, limit: STREAM_PAGE_SIZE, cursor });
|
|
72
|
+
for (const item of page.items)
|
|
73
|
+
yield item;
|
|
74
|
+
cursor = page.nextCursor;
|
|
75
|
+
} while (cursor !== undefined);
|
|
76
|
+
}
|
|
77
|
+
exports.BACKFILLED_AT = '1970-01-01T00:00:00.000Z';
|
|
78
|
+
function backfilledAt(recorded) {
|
|
79
|
+
return typeof recorded === 'string' ? recorded : exports.BACKFILLED_AT;
|
|
80
|
+
}
|
|
81
|
+
exports.INDEX_PARTITION_ATTRIBUTE = 'gsi1pk';
|
|
82
|
+
exports.INDEX_SORT_ATTRIBUTE = 'gsi1sk';
|
|
83
|
+
exports.DEFAULT_INDEX_SHARDS = 8;
|
|
84
|
+
exports.MAX_INDEX_SHARDS = 1024;
|
|
85
|
+
function fnv1a(value) {
|
|
86
|
+
let hash = 0x811c9dc5;
|
|
87
|
+
for (let i = 0; i < value.length; i++) {
|
|
88
|
+
hash ^= value.charCodeAt(i);
|
|
89
|
+
hash = Math.imul(hash, 0x01000193) >>> 0;
|
|
90
|
+
}
|
|
91
|
+
return hash >>> 0;
|
|
92
|
+
}
|
|
93
|
+
function assertShardCount(shards) {
|
|
94
|
+
if (!Number.isInteger(shards) || shards < 1) {
|
|
95
|
+
throw (0, errors_js_1.validationError)(`indexShards must be a positive integer (received ${shards}); a non-positive value would ` +
|
|
96
|
+
'make every row share one index partition or produce an unusable key', 'indexShards');
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function indexSortKey(at, id) {
|
|
100
|
+
const verbatim = `${at}#${id}`;
|
|
101
|
+
if (Buffer.byteLength(verbatim, 'utf8') <= table_schema_js_1.MAX_SORT_KEY_BYTES)
|
|
102
|
+
return verbatim;
|
|
103
|
+
return `${at}#sha256:${(0, node_crypto_1.createHash)('sha256').update(id, 'utf8').digest('hex')}`;
|
|
104
|
+
}
|
|
105
|
+
function indexKeys(tag, id, at, shards) {
|
|
106
|
+
assertShardCount(shards);
|
|
107
|
+
return {
|
|
108
|
+
gsi1pk: `${tag}#${fnv1a(id) % shards}`,
|
|
109
|
+
gsi1sk: indexSortKey(at, id),
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
function indexPartitions(tag, shards) {
|
|
113
|
+
assertShardCount(shards);
|
|
114
|
+
return Array.from({ length: shards }, (_unused, shard) => `${tag}#${shard}`);
|
|
115
|
+
}
|
|
116
|
+
function shardReader(partition) {
|
|
117
|
+
return { partition, buffer: [], startKey: undefined, exhausted: false, pages: 0 };
|
|
118
|
+
}
|
|
119
|
+
function shardQuery(options, reader, before, limit) {
|
|
120
|
+
return {
|
|
121
|
+
TableName: options.tableName,
|
|
122
|
+
IndexName: options.indexName,
|
|
123
|
+
KeyConditionExpression: before === undefined ? '#pk = :pk' : '#pk = :pk AND #sk < :before',
|
|
124
|
+
ExpressionAttributeNames: {
|
|
125
|
+
'#pk': exports.INDEX_PARTITION_ATTRIBUTE,
|
|
126
|
+
...(before === undefined ? {} : { '#sk': exports.INDEX_SORT_ATTRIBUTE }),
|
|
127
|
+
},
|
|
128
|
+
ExpressionAttributeValues: {
|
|
129
|
+
':pk': reader.partition,
|
|
130
|
+
...(before === undefined ? {} : { ':before': before }),
|
|
131
|
+
},
|
|
132
|
+
ScanIndexForward: false,
|
|
133
|
+
Limit: limit,
|
|
134
|
+
...(reader.startKey === undefined ? {} : { ExclusiveStartKey: reader.startKey }),
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
async function readShardPage(options, reader, before, limit) {
|
|
138
|
+
if (reader.pages >= paginate_js_1.MAX_LOOP_ITERATIONS) {
|
|
139
|
+
throw (0, errors_js_1.resultTruncatedError)('maxIterations', paginate_js_1.MAX_LOOP_ITERATIONS);
|
|
140
|
+
}
|
|
141
|
+
const result = await (0, retry_js_1.withDynamoDBRetry)((request) => options.client.query(shardQuery(options, reader, before, limit), request), { ...options.retry, signal: options.signal });
|
|
142
|
+
reader.pages += 1;
|
|
143
|
+
reader.buffer = (result.Items ?? []).slice().reverse();
|
|
144
|
+
reader.startKey = result.LastEvaluatedKey;
|
|
145
|
+
reader.exhausted = reader.startKey === undefined;
|
|
146
|
+
}
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* (`maxAttempts: 1` on the S3 client) and orphan release, which retries on its
|
|
11
11
|
* own loop, do not.
|
|
12
12
|
*/
|
|
13
|
-
import type { Logger } from '../logging/logger';
|
|
13
|
+
import type { Logger } from '../logging/logger.js';
|
|
14
14
|
/** Starting delay for UnprocessedItems / UnprocessedKeys backoff loops. */
|
|
15
15
|
export declare const INITIAL_BACKOFF_DELAY_MS = 100;
|
|
16
16
|
/** Maximum backoff delay for retry loops. */
|
|
@@ -76,6 +76,22 @@ export interface RetryOptions {
|
|
|
76
76
|
signal?: AbortSignal;
|
|
77
77
|
rng?: () => number;
|
|
78
78
|
}
|
|
79
|
+
/**
|
|
80
|
+
* The cap a backoff schedule runs under.
|
|
81
|
+
*
|
|
82
|
+
* Accepts: `baseDelayMs` — the schedule's first delay, already defaulted.
|
|
83
|
+
* `maxDelayMs` — the cap the caller named, if it named one.
|
|
84
|
+
*
|
|
85
|
+
* Returns: the named cap; without one, {@link MAX_BACKOFF_DELAY_MS} raised to
|
|
86
|
+
* a base above it.
|
|
87
|
+
*
|
|
88
|
+
* Throws: nothing.
|
|
89
|
+
*
|
|
90
|
+
* Guarantees: a base delay given without a cap is the delay the schedule
|
|
91
|
+
* starts from. Held under the default cap it would be cut to five seconds on
|
|
92
|
+
* every sleep: an option accepted and then ignored.
|
|
93
|
+
*/
|
|
94
|
+
export declare function backoffCapMs(baseDelayMs: number, maxDelayMs: number | undefined): number;
|
|
79
95
|
/**
|
|
80
96
|
* Run `fn`, retrying transient failures with full-jitter exponential backoff.
|
|
81
97
|
*
|
|
@@ -89,7 +105,8 @@ export interface RetryOptions {
|
|
|
89
105
|
* Accepts: `options.maxAttempts` — total attempts including the first, default
|
|
90
106
|
* {@link DEFAULT_RETRY_MAX_ATTEMPTS}; at least 1, which `assertRetryPolicy`
|
|
91
107
|
* enforces for every caller-supplied policy. `options.baseDelayMs` /
|
|
92
|
-
* `maxDelayMs` — the backoff schedule
|
|
108
|
+
* `maxDelayMs` — the backoff schedule, its cap defaulted by
|
|
109
|
+
* {@link backoffCapMs}. `options.isRetryable` — replaces
|
|
93
110
|
* `retryableErrors` entirely, so a call site can share one classifier with
|
|
94
111
|
* paths that do not go through here. `options.signal` — checked before the
|
|
95
112
|
* first attempt, handed to every attempt as `abortSignal` so the request in
|
|
@@ -113,6 +130,14 @@ export interface RetryOptions {
|
|
|
113
130
|
* actually reached — not the attempts configured — and the last error as
|
|
114
131
|
* `cause`. Its message quotes the last error **redacted**, because it reaches
|
|
115
132
|
* `err.message`, which an application may print without a redacting logger.
|
|
133
|
+
* That error also records, for `mayStillLand` to read back
|
|
134
|
+
* (`retryBudgetMayStillLand`), whether *any* attempt of the budget — not only
|
|
135
|
+
* the last — left DynamoDB free to apply it later: one that ended on this
|
|
136
|
+
* side before an answer, one DynamoDB answered `TransactionInProgressException`
|
|
137
|
+
* to (its own earlier attempt under the same token still being processed), or
|
|
138
|
+
* one it answered with a server error (see `mayStillBeInFlight`). An attempt
|
|
139
|
+
* answered some other way settles nothing by itself, whatever attempt beside
|
|
140
|
+
* it did.
|
|
116
141
|
*
|
|
117
142
|
* A deadline that ends the budget is reported exactly as a spent one, by the
|
|
118
143
|
* same error with the same code: a caller cannot tell the two apart, and
|
|
@@ -128,8 +153,10 @@ export interface RetryOptions {
|
|
|
128
153
|
* at entry, fired during an attempt, or fired during an earlier wait, is still
|
|
129
154
|
* caught.
|
|
130
155
|
*
|
|
131
|
-
* Guarantees: `fn` is called at
|
|
132
|
-
*
|
|
156
|
+
* Guarantees: `fn` is called at most `maxAttempts` times, and at least once
|
|
157
|
+
* unless the signal was already aborted at entry, when it is not called at
|
|
158
|
+
* all. A thrown non-`Error` is wrapped, so what a caller catches is always an
|
|
159
|
+
* `Error`.
|
|
133
160
|
*/
|
|
134
161
|
export declare function withRetry<T>(fn: (request: SdkRequestOptions) => Promise<T>, options?: RetryOptions): Promise<T>;
|
|
135
162
|
/**
|
|
@@ -157,7 +184,8 @@ export declare function withDynamoDBRetry<T>(fn: (request: SdkRequestOptions) =>
|
|
|
157
184
|
* transient. This verdict is final either way: a permanent reason arrives
|
|
158
185
|
* with the same HTTP status as a transient one, so the later rules cannot be
|
|
159
186
|
* allowed to overturn it. A cancellation carrying no reasons is not retried.
|
|
160
|
-
* 2. any node carries the SDK's `$retryable` trait
|
|
187
|
+
* 2. any node carries the SDK's `$retryable` trait, or is a signing failure
|
|
188
|
+
* the SDK corrected its clock for or reports expired (`isCorrectedClockSkew`);
|
|
161
189
|
* 3. any node's HTTP status is in {@link TRANSIENT_HTTP_STATUSES} — which is
|
|
162
190
|
* what classifies a failure the SDK could not map to a modeled exception,
|
|
163
191
|
* arriving as `name: 'Unknown'` with only a status;
|
|
@@ -183,7 +211,10 @@ export interface RetryPolicy {
|
|
|
183
211
|
maxAttempts?: number;
|
|
184
212
|
/** First backoff delay in milliseconds (default 100). */
|
|
185
213
|
baseDelayMs?: number;
|
|
186
|
-
/**
|
|
214
|
+
/**
|
|
215
|
+
* Cap on a single backoff delay in milliseconds (default 5000, or
|
|
216
|
+
* `baseDelayMs` when that is given above it).
|
|
217
|
+
*/
|
|
187
218
|
maxDelayMs?: number;
|
|
188
219
|
}
|
|
189
220
|
/**
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MAX_WRITE_LIFETIME_MS = exports.TOKEN_IDEMPOTENCY_WINDOW_MS = exports.DEFAULT_RETRY_MAX_ATTEMPTS = exports.MAX_BACKOFF_DELAY_MS = exports.INITIAL_BACKOFF_DELAY_MS = void 0;
|
|
4
|
+
exports.backoffCapMs = backoffCapMs;
|
|
5
|
+
exports.withRetry = withRetry;
|
|
6
|
+
exports.withDynamoDBRetry = withDynamoDBRetry;
|
|
7
|
+
exports.isRetryableError = isRetryableError;
|
|
8
|
+
exports.resolveRetryPolicy = resolveRetryPolicy;
|
|
9
|
+
exports.retryFor = retryFor;
|
|
10
|
+
exports.sleep = sleep;
|
|
11
|
+
exports.nextBackoffDelay = nextBackoffDelay;
|
|
12
|
+
exports.fullJitter = fullJitter;
|
|
13
|
+
exports.isTransientS3Error = isTransientS3Error;
|
|
14
|
+
const clock_js_1 = require("../clock.js");
|
|
15
|
+
const base_error_js_1 = require("../errors/base-error.js");
|
|
16
|
+
const classify_js_1 = require("../errors/classify.js");
|
|
17
|
+
const errors_js_1 = require("../errors/errors.js");
|
|
18
|
+
const secret_patterns_js_1 = require("../logging/secret-patterns.js");
|
|
19
|
+
const truncate_js_1 = require("../logging/truncate.js");
|
|
20
|
+
const abort_js_1 = require("./abort.js");
|
|
21
|
+
const cancellation_js_1 = require("./cancellation.js");
|
|
22
|
+
exports.INITIAL_BACKOFF_DELAY_MS = 100;
|
|
23
|
+
exports.MAX_BACKOFF_DELAY_MS = 5000;
|
|
24
|
+
exports.DEFAULT_RETRY_MAX_ATTEMPTS = 5;
|
|
25
|
+
exports.TOKEN_IDEMPOTENCY_WINDOW_MS = 600_000;
|
|
26
|
+
exports.MAX_WRITE_LIFETIME_MS = 300_000;
|
|
27
|
+
function crossesDeadline(deadlineAt, delayMs) {
|
|
28
|
+
return deadlineAt !== undefined && (0, clock_js_1.nowMs)() + delayMs >= deadlineAt;
|
|
29
|
+
}
|
|
30
|
+
function assertNotAborted(signal) {
|
|
31
|
+
if (signal?.aborted)
|
|
32
|
+
throw (0, abort_js_1.abortErrorFrom)(signal);
|
|
33
|
+
}
|
|
34
|
+
function delayForAttempt(attempt, base, max, rng) {
|
|
35
|
+
const exponential = base * 2 ** (attempt - 1);
|
|
36
|
+
return fullJitter(Math.min(exponential, max), rng);
|
|
37
|
+
}
|
|
38
|
+
function backoffCapMs(baseDelayMs, maxDelayMs) {
|
|
39
|
+
return maxDelayMs ?? Math.max(exports.MAX_BACKOFF_DELAY_MS, baseDelayMs);
|
|
40
|
+
}
|
|
41
|
+
function resolveRetryOptions(options) {
|
|
42
|
+
const baseDelayMs = options.baseDelayMs ?? exports.INITIAL_BACKOFF_DELAY_MS;
|
|
43
|
+
return {
|
|
44
|
+
maxAttempts: options.maxAttempts ?? exports.DEFAULT_RETRY_MAX_ATTEMPTS,
|
|
45
|
+
baseDelayMs,
|
|
46
|
+
maxDelayMs: backoffCapMs(baseDelayMs, options.maxDelayMs),
|
|
47
|
+
isRetryable: options.isRetryable ??
|
|
48
|
+
((error) => isRetryableError(error, options.retryableErrors ?? classify_js_1.DEFAULT_RETRYABLE_ERRORS)),
|
|
49
|
+
rng: options.rng ?? Math.random,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
async function withRetry(fn, options = {}) {
|
|
53
|
+
const { maxAttempts, baseDelayMs, maxDelayMs, isRetryable, rng } = resolveRetryOptions(options);
|
|
54
|
+
assertNotAborted(options.signal);
|
|
55
|
+
const request = { abortSignal: options.signal };
|
|
56
|
+
let lastError = new Error('Retry failed without error');
|
|
57
|
+
let attempts = 0;
|
|
58
|
+
let mayStillLand = false;
|
|
59
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
60
|
+
attempts = attempt;
|
|
61
|
+
try {
|
|
62
|
+
return await fn(request);
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
assertNotAborted(options.signal);
|
|
66
|
+
lastError = (0, base_error_js_1.toError)(error);
|
|
67
|
+
if ((0, classify_js_1.mayStillBeInFlight)(lastError))
|
|
68
|
+
mayStillLand = true;
|
|
69
|
+
if (!isRetryable(lastError))
|
|
70
|
+
throw mayStillLand ? (0, errors_js_1.markMayStillLand)(lastError) : lastError;
|
|
71
|
+
if (attempt === maxAttempts)
|
|
72
|
+
break;
|
|
73
|
+
const delayMs = delayForAttempt(attempt, baseDelayMs, maxDelayMs, rng);
|
|
74
|
+
if (crossesDeadline(options.deadlineAt, delayMs))
|
|
75
|
+
break;
|
|
76
|
+
options.onRetry?.({ attempt, delayMs, error: lastError });
|
|
77
|
+
await sleep(delayMs, options.signal);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
throw (0, errors_js_1.retryExhaustedError)(`Operation failed after ${attempts} attempts: ${(0, secret_patterns_js_1.redactedMessage)(lastError)}`, attempts, lastError, mayStillLand);
|
|
81
|
+
}
|
|
82
|
+
async function withDynamoDBRetry(fn, overrides) {
|
|
83
|
+
return withRetry(fn, { maxAttempts: exports.DEFAULT_RETRY_MAX_ATTEMPTS, ...overrides });
|
|
84
|
+
}
|
|
85
|
+
function recordNode(fields, evidence) {
|
|
86
|
+
for (const value of [fields.name, fields.code, fields.errno, fields.syscall]) {
|
|
87
|
+
if (typeof value === 'string')
|
|
88
|
+
evidence.signals.push(value);
|
|
89
|
+
}
|
|
90
|
+
if (typeof fields.$metadata?.httpStatusCode === 'number') {
|
|
91
|
+
evidence.statuses.push(fields.$metadata.httpStatusCode);
|
|
92
|
+
}
|
|
93
|
+
const byTrait = fields.$retryable !== undefined && fields.$retryable !== null;
|
|
94
|
+
if (byTrait || (0, classify_js_1.isCorrectedClockSkew)(fields))
|
|
95
|
+
evidence.retryableByTrait = true;
|
|
96
|
+
}
|
|
97
|
+
function collectEvidence(error) {
|
|
98
|
+
const seen = new WeakSet();
|
|
99
|
+
const evidence = { signals: [], statuses: [], retryableByTrait: false };
|
|
100
|
+
const walk = (node, depth) => {
|
|
101
|
+
if (depth > classify_js_1.MAX_CAUSE_DEPTH || node === null || typeof node !== 'object' || seen.has(node)) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
seen.add(node);
|
|
105
|
+
const fields = node;
|
|
106
|
+
recordNode(fields, evidence);
|
|
107
|
+
if (fields.cause)
|
|
108
|
+
walk(fields.cause, depth + 1);
|
|
109
|
+
};
|
|
110
|
+
walk(error, 0);
|
|
111
|
+
return evidence;
|
|
112
|
+
}
|
|
113
|
+
function isRetryableError(error, retryableErrors) {
|
|
114
|
+
const cancellation = (0, cancellation_js_1.transientCancellation)(error);
|
|
115
|
+
if (cancellation !== undefined)
|
|
116
|
+
return cancellation;
|
|
117
|
+
const evidence = collectEvidence(error);
|
|
118
|
+
if (evidence.retryableByTrait)
|
|
119
|
+
return true;
|
|
120
|
+
if (evidence.statuses.some((status) => classify_js_1.TRANSIENT_HTTP_STATUSES.includes(status)))
|
|
121
|
+
return true;
|
|
122
|
+
return evidence.signals.some((signal) => retryableErrors.includes(signal));
|
|
123
|
+
}
|
|
124
|
+
function nominalBudgetMs(policy) {
|
|
125
|
+
let total = 0;
|
|
126
|
+
for (let sleep = 1; sleep < policy.maxAttempts; sleep++) {
|
|
127
|
+
total += Math.min(policy.baseDelayMs * 2 ** (sleep - 1), policy.maxDelayMs);
|
|
128
|
+
}
|
|
129
|
+
return total;
|
|
130
|
+
}
|
|
131
|
+
function warnIfOutlivesWriteLifetime(policy, logger) {
|
|
132
|
+
const budgetMs = nominalBudgetMs(policy);
|
|
133
|
+
if (budgetMs <= exports.MAX_WRITE_LIFETIME_MS)
|
|
134
|
+
return;
|
|
135
|
+
logger.warn('retry policy outlives the write lifetime; the budget will be cut short', {
|
|
136
|
+
budgetMs,
|
|
137
|
+
maxWriteLifetimeMs: exports.MAX_WRITE_LIFETIME_MS,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
function resolveRetryPolicy(policy, logger, attemptFloor = 0) {
|
|
141
|
+
const baseDelayMs = policy?.baseDelayMs ?? exports.INITIAL_BACKOFF_DELAY_MS;
|
|
142
|
+
const resolved = {
|
|
143
|
+
maxAttempts: policy?.maxAttempts ?? exports.DEFAULT_RETRY_MAX_ATTEMPTS,
|
|
144
|
+
baseDelayMs,
|
|
145
|
+
maxDelayMs: backoffCapMs(baseDelayMs, policy?.maxDelayMs),
|
|
146
|
+
};
|
|
147
|
+
warnIfOutlivesWriteLifetime({ ...resolved, maxAttempts: Math.max(resolved.maxAttempts, attemptFloor) }, logger);
|
|
148
|
+
return {
|
|
149
|
+
...resolved,
|
|
150
|
+
onRetry: ({ attempt, delayMs, error }) => logger.debug('retrying after a transient error', {
|
|
151
|
+
attempt,
|
|
152
|
+
delayMs,
|
|
153
|
+
error: (0, truncate_js_1.truncateForLog)((0, base_error_js_1.failureLabel)(error)),
|
|
154
|
+
}),
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
function retryFor(context, signal) {
|
|
158
|
+
return signal === undefined ? context.retry : { ...context.retry, signal };
|
|
159
|
+
}
|
|
160
|
+
function sleep(ms, signal) {
|
|
161
|
+
if (signal?.aborted) {
|
|
162
|
+
return Promise.reject((0, abort_js_1.abortErrorFrom)(signal));
|
|
163
|
+
}
|
|
164
|
+
return new Promise((resolve, reject) => {
|
|
165
|
+
const wait = { settled: false };
|
|
166
|
+
const onAbort = () => {
|
|
167
|
+
if (wait.settled)
|
|
168
|
+
return;
|
|
169
|
+
wait.settled = true;
|
|
170
|
+
clearTimeout(wait.timer);
|
|
171
|
+
reject((0, abort_js_1.abortErrorFrom)(signal));
|
|
172
|
+
};
|
|
173
|
+
signal?.addEventListener('abort', onAbort, { once: true });
|
|
174
|
+
if (wait.settled)
|
|
175
|
+
return;
|
|
176
|
+
wait.timer = setTimeout(() => {
|
|
177
|
+
if (wait.settled)
|
|
178
|
+
return;
|
|
179
|
+
wait.settled = true;
|
|
180
|
+
signal?.removeEventListener('abort', onAbort);
|
|
181
|
+
resolve();
|
|
182
|
+
}, ms);
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
function nextBackoffDelay(currentMs, maxMs = exports.MAX_BACKOFF_DELAY_MS) {
|
|
186
|
+
return Math.min(currentMs * 2, maxMs);
|
|
187
|
+
}
|
|
188
|
+
function fullJitter(delayMs, rng = Math.random) {
|
|
189
|
+
return rng() * delayMs;
|
|
190
|
+
}
|
|
191
|
+
function isTransientS3Error(error) {
|
|
192
|
+
return isRetryableError(error, classify_js_1.DEFAULT_RETRYABLE_ERRORS);
|
|
193
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hides how DynamoDB measures a row against its 400 KB item limit.
|
|
3
|
+
*
|
|
4
|
+
* DynamoDB does not measure a row by its JSON length: every attribute name
|
|
5
|
+
* counts, a number costs a byte per two significant digits and one more,
|
|
6
|
+
* binary counts its raw bytes, and a list or a map adds three bytes and one
|
|
7
|
+
* per element. A write that would cross the limit is refused here, by those
|
|
8
|
+
* rules, before anything is sent, so the caller learns which input made the
|
|
9
|
+
* row too large instead of reading an `AWS_REJECTED` error after the work that
|
|
10
|
+
* built the row — an embedding, an upload — was already done.
|
|
11
|
+
*/
|
|
12
|
+
import type { AttributeMap } from './client.js';
|
|
13
|
+
/** DynamoDB's cap on one item, 400 KB, in the binary kilobytes its documentation counts in. */
|
|
14
|
+
export declare const MAX_ROW_BYTES: number;
|
|
15
|
+
/**
|
|
16
|
+
* The size DynamoDB counts a row at against its item limit.
|
|
17
|
+
*
|
|
18
|
+
* Accepts: `row` — a row this package is about to write, as the document
|
|
19
|
+
* client would marshall it: strings, numbers, booleans, `null`, binary,
|
|
20
|
+
* arrays and plain objects, nested to any depth. An `undefined` attribute is
|
|
21
|
+
* counted as one byte although the client drops it, which only errs high.
|
|
22
|
+
*
|
|
23
|
+
* Returns: the sum, over every attribute, of its name's UTF-8 bytes and its
|
|
24
|
+
* value's size: a string's UTF-8 bytes; a number's significant digits halved
|
|
25
|
+
* and rounded up, plus one; binary's raw bytes; one byte for a boolean or a
|
|
26
|
+
* null; and for a list or a map three bytes, plus each element's size and one
|
|
27
|
+
* byte per element, a map's element also paying its name. The rules are
|
|
28
|
+
* AWS's own
|
|
29
|
+
* (https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/CapacityUnitCalculations.html).
|
|
30
|
+
*
|
|
31
|
+
* Throws: nothing.
|
|
32
|
+
*/
|
|
33
|
+
export declare function rowSizeBytes(row: AttributeMap): number;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MAX_ROW_BYTES = void 0;
|
|
4
|
+
exports.rowSizeBytes = rowSizeBytes;
|
|
5
|
+
exports.MAX_ROW_BYTES = 400 * 1024;
|
|
6
|
+
function nameBytes(name) {
|
|
7
|
+
return Buffer.byteLength(name, 'utf8');
|
|
8
|
+
}
|
|
9
|
+
function significantDigits(value) {
|
|
10
|
+
const mantissa = String(Math.abs(value)).split(/e/i)[0].replace('.', '');
|
|
11
|
+
const trimmed = mantissa.replace(/^0+/, '').replace(/0+$/, '');
|
|
12
|
+
return Math.max(trimmed.length, 1);
|
|
13
|
+
}
|
|
14
|
+
function valueBytes(value) {
|
|
15
|
+
if (typeof value === 'string')
|
|
16
|
+
return Buffer.byteLength(value, 'utf8');
|
|
17
|
+
if (typeof value === 'number')
|
|
18
|
+
return Math.ceil(significantDigits(value) / 2) + 1;
|
|
19
|
+
if (typeof value === 'boolean' || value === null || value === undefined)
|
|
20
|
+
return 1;
|
|
21
|
+
if (ArrayBuffer.isView(value))
|
|
22
|
+
return value.byteLength;
|
|
23
|
+
if (Array.isArray(value)) {
|
|
24
|
+
return value.reduce((sum, element) => sum + valueBytes(element) + 1, 3);
|
|
25
|
+
}
|
|
26
|
+
return Object.entries(value).reduce((sum, [name, element]) => sum + nameBytes(name) + valueBytes(element) + 1, 3);
|
|
27
|
+
}
|
|
28
|
+
function rowSizeBytes(row) {
|
|
29
|
+
return Object.entries(row).reduce((sum, [name, value]) => sum + nameBytes(name) + valueBytes(value), 0);
|
|
30
|
+
}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* attributes and read back in this order is this module's.
|
|
12
12
|
*/
|
|
13
13
|
import type { QueryCommandInput, ScanCommandInput } from '@aws-sdk/lib-dynamodb';
|
|
14
|
-
import type { AttributeMap } from './client';
|
|
14
|
+
import type { AttributeMap } from './client.js';
|
|
15
15
|
/** The attribute every row is partitioned by. */
|
|
16
16
|
export declare const PARTITION_KEY_ATTRIBUTE = "PK";
|
|
17
17
|
/** The attribute every row is sorted by within its partition. */
|
|
@@ -27,10 +27,30 @@ export declare const SORT_KEY_ATTRIBUTE = "SK";
|
|
|
27
27
|
*/
|
|
28
28
|
export declare const MAX_PARTITION_ID_BYTES = 1024;
|
|
29
29
|
/**
|
|
30
|
-
* Sort-key segments
|
|
31
|
-
* channel
|
|
30
|
+
* Sort-key segments other than the checkpoint namespace and a pending-write
|
|
31
|
+
* channel: `checkpoint_id`, `taskId`, a store namespace element and a store
|
|
32
|
+
* `key`.
|
|
32
33
|
*/
|
|
33
34
|
export declare const MAX_KEY_SEGMENT_BYTES = 256;
|
|
35
|
+
/**
|
|
36
|
+
* A pending-write channel's own cap. Every other segment is one identifier,
|
|
37
|
+
* but LangGraph names the channel behind a static fan-in after every source
|
|
38
|
+
* node — `join:<a>+<b>+…:<end>` — so a channel is as long as a graph's node
|
|
39
|
+
* names together, and nine sources with ordinary names pass 256 bytes. The
|
|
40
|
+
* channel is the last segment of the WRITE sort key, so DynamoDB's cap on the
|
|
41
|
+
* whole key is the bound that matters, and the composed-key check enforces it
|
|
42
|
+
* against the namespace, checkpoint id and task id the channel sits behind.
|
|
43
|
+
*/
|
|
44
|
+
export declare const MAX_WRITE_CHANNEL_BYTES = 1024;
|
|
45
|
+
/**
|
|
46
|
+
* The checkpoint namespace's own cap. LangGraph names a subgraph's namespace
|
|
47
|
+
* after its parent's, a separator, the node's name and a 36-character task id
|
|
48
|
+
* (`${parent}|${node}:${taskId}`), so each level of nesting adds roughly forty
|
|
49
|
+
* bytes plus the node name; 256 bytes stopped a graph at its fifth or sixth
|
|
50
|
+
* level. Twice that keeps the rows a namespace composes inside DynamoDB's
|
|
51
|
+
* sort-key cap, which the composed-key checks enforce either way.
|
|
52
|
+
*/
|
|
53
|
+
export declare const MAX_CHECKPOINT_NS_BYTES = 512;
|
|
34
54
|
/**
|
|
35
55
|
* DynamoDB cap on a whole sort key; composed keys are checked against it too.
|
|
36
56
|
*
|
|
@@ -113,18 +133,6 @@ export declare function rowVersionOf(row: VersionedRow): number;
|
|
|
113
133
|
* missing state, so the caller is told to upgrade instead.
|
|
114
134
|
*/
|
|
115
135
|
export declare function assertReadableRow(row: VersionedRow, what: string): void;
|
|
116
|
-
/**
|
|
117
|
-
* The item with this release's format version stamped on it.
|
|
118
|
-
*
|
|
119
|
-
* Accepts: `item` — any item about to be written; an existing `v` is replaced.
|
|
120
|
-
*
|
|
121
|
-
* Returns: a copy carrying `v`, leaving the input untouched.
|
|
122
|
-
*
|
|
123
|
-
* Throws: nothing.
|
|
124
|
-
*/
|
|
125
|
-
export declare function withRowVersion<T extends AttributeMap>(item: T): T & {
|
|
126
|
-
v: number;
|
|
127
|
-
};
|
|
128
136
|
/**
|
|
129
137
|
* Whether a row has reached its TTL.
|
|
130
138
|
*
|
|
@@ -136,9 +144,10 @@ export declare function withRowVersion<T extends AttributeMap>(item: T): T & {
|
|
|
136
144
|
*
|
|
137
145
|
* Throws: nothing.
|
|
138
146
|
*
|
|
139
|
-
* Guarantees:
|
|
140
|
-
* own sweep lags, which
|
|
141
|
-
*
|
|
147
|
+
* Guarantees: a caller that applies this hides an expired row even while
|
|
148
|
+
* DynamoDB's own sweep lags, which AWS documents as typically within a few days of the
|
|
149
|
+
* `ttl`, with no fixed bound
|
|
150
|
+
* (https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/TTL.html).
|
|
142
151
|
*/
|
|
143
152
|
export declare function isExpiredRow(row: {
|
|
144
153
|
ttl?: number;
|