@farukada/aws-langgraph-dynamodb-ts 0.9.0 → 1.0.0-rc.2
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 +1720 -154
- package/dist/backfill/backfill.d.ts +168 -0
- package/dist/backfill/backfill.js +393 -0
- package/dist/checkpointer/actions/delete-thread.d.ts +47 -6
- package/dist/checkpointer/actions/delete-thread.js +58 -21
- package/dist/checkpointer/actions/get-tuple.d.ts +29 -4
- package/dist/checkpointer/actions/get-tuple.js +44 -10
- package/dist/checkpointer/actions/list.d.ts +46 -4
- package/dist/checkpointer/actions/list.js +121 -66
- package/dist/checkpointer/actions/put-writes.d.ts +41 -9
- package/dist/checkpointer/actions/put-writes.js +62 -77
- package/dist/checkpointer/actions/put.d.ts +83 -4
- package/dist/checkpointer/actions/put.js +177 -25
- package/dist/checkpointer/internal/delta-history.d.ts +112 -0
- package/dist/checkpointer/internal/delta-history.js +252 -0
- package/dist/checkpointer/internal/listing.d.ts +149 -0
- package/dist/checkpointer/internal/listing.js +245 -0
- package/dist/checkpointer/internal/parse.d.ts +262 -0
- package/dist/checkpointer/internal/parse.js +372 -0
- package/dist/checkpointer/internal/pending-writes.d.ts +275 -0
- package/dist/checkpointer/internal/pending-writes.js +588 -0
- package/dist/checkpointer/internal/read.d.ts +130 -0
- package/dist/checkpointer/internal/read.js +264 -0
- package/dist/checkpointer/internal/rows.d.ts +571 -0
- package/dist/checkpointer/internal/rows.js +834 -0
- package/dist/checkpointer/internal/setup.d.ts +42 -19
- package/dist/checkpointer/internal/setup.js +65 -29
- package/dist/checkpointer/saver.d.ts +256 -16
- package/dist/checkpointer/saver.js +275 -29
- package/dist/checkpointer/types.d.ts +39 -39
- package/dist/checkpointer/types.js +10 -1
- package/dist/factory/factory.d.ts +134 -28
- package/dist/factory/factory.js +240 -21
- package/dist/factory/types.d.ts +76 -0
- package/dist/factory/types.js +10 -0
- package/dist/history/actions/add-messages.d.ts +31 -4
- package/dist/history/actions/add-messages.js +38 -58
- package/dist/history/actions/clear.d.ts +49 -6
- package/dist/history/actions/clear.js +66 -14
- package/dist/history/actions/get-messages.d.ts +54 -6
- package/dist/history/actions/get-messages.js +126 -43
- package/dist/history/actions/list-sessions.d.ts +52 -10
- package/dist/history/actions/list-sessions.js +139 -40
- package/dist/history/actions/reconcile-count.d.ts +42 -10
- package/dist/history/actions/reconcile-count.js +45 -45
- package/dist/history/chat-message-history.d.ts +220 -33
- package/dist/history/chat-message-history.js +240 -43
- package/dist/history/internal/append.d.ts +212 -0
- package/dist/history/internal/append.js +500 -0
- package/dist/history/internal/message-read.d.ts +84 -0
- package/dist/history/internal/message-read.js +204 -0
- package/dist/history/internal/parse.d.ts +153 -0
- package/dist/history/internal/parse.js +252 -0
- package/dist/history/internal/rows.d.ts +195 -0
- package/dist/history/internal/rows.js +250 -0
- package/dist/history/internal/session.d.ts +331 -0
- package/dist/history/internal/session.js +628 -0
- package/dist/history/internal/setup.d.ts +52 -17
- package/dist/history/internal/setup.js +92 -21
- package/dist/history/session-adapter.d.ts +102 -7
- package/dist/history/session-adapter.js +103 -9
- package/dist/history/types.d.ts +80 -29
- package/dist/history/types.js +10 -1
- package/dist/index.d.ts +42 -11
- package/dist/index.js +33 -12
- package/dist/shared/adapter.d.ts +135 -0
- package/dist/shared/adapter.js +143 -0
- package/dist/shared/clock.d.ts +51 -2
- package/dist/shared/clock.js +57 -2
- package/dist/shared/codec/codec.d.ts +288 -13
- package/dist/shared/codec/codec.js +416 -19
- package/dist/shared/codec/compression.d.ts +43 -7
- package/dist/shared/codec/compression.js +53 -13
- package/dist/shared/codec/json-serde.d.ts +76 -4
- package/dist/shared/codec/json-serde.js +181 -8
- package/dist/shared/codec/s3/client-types.d.ts +53 -0
- package/dist/shared/codec/s3/client-types.js +26 -0
- package/dist/shared/codec/s3/client.d.ts +43 -10
- package/dist/shared/codec/s3/client.js +82 -9
- package/dist/shared/codec/s3/config.d.ts +242 -11
- package/dist/shared/codec/s3/config.js +293 -11
- package/dist/shared/codec/s3/lifecycle.d.ts +164 -6
- package/dist/shared/codec/s3/lifecycle.js +335 -27
- package/dist/shared/codec/s3/offloader.d.ts +393 -18
- package/dist/shared/codec/s3/offloader.js +595 -37
- package/dist/shared/concurrency.d.ts +43 -0
- package/dist/shared/concurrency.js +78 -0
- package/dist/shared/dynamodb/abort.d.ts +47 -0
- package/dist/shared/dynamodb/abort.js +59 -0
- package/dist/shared/dynamodb/batch-write.d.ts +77 -14
- package/dist/shared/dynamodb/batch-write.js +146 -27
- package/dist/shared/dynamodb/cancellation.d.ts +121 -4
- package/dist/shared/dynamodb/cancellation.js +147 -3
- package/dist/shared/dynamodb/client.d.ts +162 -8
- package/dist/shared/dynamodb/client.js +153 -5
- package/dist/shared/dynamodb/idempotent-write.d.ts +551 -0
- package/dist/shared/dynamodb/idempotent-write.js +593 -0
- package/dist/shared/dynamodb/paginate.d.ts +105 -9
- package/dist/shared/dynamodb/paginate.js +175 -7
- package/dist/shared/dynamodb/partition-delete.d.ts +185 -14
- package/dist/shared/dynamodb/partition-delete.js +314 -44
- package/dist/shared/dynamodb/recency-index.d.ts +231 -0
- package/dist/shared/dynamodb/recency-index.js +377 -0
- package/dist/shared/dynamodb/retry.d.ts +276 -8
- package/dist/shared/dynamodb/retry.js +433 -23
- package/dist/shared/dynamodb/table-schema.d.ts +190 -0
- package/dist/shared/dynamodb/table-schema.js +209 -0
- package/dist/shared/errors/base-error.d.ts +184 -10
- package/dist/shared/errors/base-error.js +160 -14
- package/dist/shared/errors/boundary.d.ts +71 -0
- package/dist/shared/errors/boundary.js +143 -0
- package/dist/shared/errors/classify.d.ts +97 -0
- package/dist/shared/errors/classify.js +257 -0
- package/dist/shared/errors/error-code.d.ts +77 -2
- package/dist/shared/errors/error-code.js +83 -1
- package/dist/shared/errors/errors.d.ts +158 -59
- package/dist/shared/errors/errors.js +219 -92
- package/dist/shared/logging/logger.d.ts +69 -3
- package/dist/shared/logging/logger.js +97 -3
- package/dist/shared/logging/redaction.d.ts +92 -8
- package/dist/shared/logging/redaction.js +273 -17
- package/dist/shared/logging/secret-patterns.d.ts +149 -19
- package/dist/shared/logging/secret-patterns.js +188 -27
- package/dist/shared/logging/truncate.d.ts +197 -0
- package/dist/shared/logging/truncate.js +231 -0
- package/dist/shared/options.d.ts +59 -7
- package/dist/shared/options.js +9 -1
- package/dist/shared/ulid.d.ts +77 -7
- package/dist/shared/ulid.js +103 -8
- package/dist/shared/validation/collaborators.d.ts +141 -0
- package/dist/shared/validation/collaborators.js +188 -0
- package/dist/shared/validation/option-shape.d.ts +89 -0
- package/dist/shared/validation/option-shape.js +113 -0
- package/dist/shared/validation/options.d.ts +145 -0
- package/dist/shared/validation/options.js +328 -0
- package/dist/shared/validation/primitives.d.ts +288 -21
- package/dist/shared/validation/primitives.js +353 -50
- package/dist/shared/validation/ttl.d.ts +66 -10
- package/dist/shared/validation/ttl.js +113 -15
- package/dist/store/actions/list-namespaces.d.ts +76 -6
- package/dist/store/actions/list-namespaces.js +166 -24
- package/dist/store/actions/put.d.ts +33 -8
- package/dist/store/actions/put.js +53 -60
- package/dist/store/actions/reconcile-vector-index.d.ts +31 -10
- package/dist/store/actions/reconcile-vector-index.js +34 -15
- package/dist/store/actions/search.d.ts +34 -6
- package/dist/store/actions/search.js +56 -51
- package/dist/store/internal/batch-plan.d.ts +26 -0
- package/dist/store/internal/batch-plan.js +109 -0
- package/dist/store/internal/filter.d.ts +36 -3
- package/dist/store/internal/filter.js +66 -15
- package/dist/store/internal/get-item.d.ts +45 -0
- package/dist/store/internal/get-item.js +115 -0
- package/dist/store/internal/item-write.d.ts +230 -0
- package/dist/store/internal/item-write.js +463 -0
- package/dist/store/internal/parse.d.ts +225 -0
- package/dist/store/internal/parse.js +350 -0
- package/dist/store/internal/rows.d.ts +355 -0
- package/dist/store/internal/rows.js +447 -0
- package/dist/store/internal/semantic-search.d.ts +161 -6
- package/dist/store/internal/semantic-search.js +360 -18
- package/dist/store/internal/setup.d.ts +77 -20
- package/dist/store/internal/setup.js +178 -47
- package/dist/store/internal/table-search.d.ts +100 -0
- package/dist/store/internal/table-search.js +213 -0
- package/dist/store/internal/vector-index.d.ts +247 -0
- package/dist/store/internal/vector-index.js +546 -0
- package/dist/store/store.d.ts +270 -17
- package/dist/store/store.js +329 -38
- package/dist/store/types.d.ts +76 -26
- package/dist/store/types.js +13 -1
- package/dist/store/vector-backend.d.ts +64 -4
- package/dist/store/vector-backend.js +15 -1
- package/package.json +58 -36
- package/dist/checkpointer/actions/delete-thread.d.ts.map +0 -1
- package/dist/checkpointer/actions/delete-thread.js.map +0 -1
- package/dist/checkpointer/actions/get-tuple.d.ts.map +0 -1
- package/dist/checkpointer/actions/get-tuple.js.map +0 -1
- package/dist/checkpointer/actions/list.d.ts.map +0 -1
- package/dist/checkpointer/actions/list.js.map +0 -1
- package/dist/checkpointer/actions/put-writes.d.ts.map +0 -1
- package/dist/checkpointer/actions/put-writes.js.map +0 -1
- package/dist/checkpointer/actions/put.d.ts.map +0 -1
- package/dist/checkpointer/actions/put.js.map +0 -1
- package/dist/checkpointer/internal/assemble.d.ts +0 -10
- package/dist/checkpointer/internal/assemble.d.ts.map +0 -1
- package/dist/checkpointer/internal/assemble.js +0 -37
- package/dist/checkpointer/internal/assemble.js.map +0 -1
- package/dist/checkpointer/internal/configurable.d.ts +0 -13
- package/dist/checkpointer/internal/configurable.d.ts.map +0 -1
- package/dist/checkpointer/internal/configurable.js +0 -23
- package/dist/checkpointer/internal/configurable.js.map +0 -1
- package/dist/checkpointer/internal/fetch.d.ts +0 -10
- package/dist/checkpointer/internal/fetch.d.ts.map +0 -1
- package/dist/checkpointer/internal/fetch.js +0 -46
- package/dist/checkpointer/internal/fetch.js.map +0 -1
- package/dist/checkpointer/internal/filter-match.d.ts +0 -12
- package/dist/checkpointer/internal/filter-match.d.ts.map +0 -1
- package/dist/checkpointer/internal/filter-match.js +0 -14
- package/dist/checkpointer/internal/filter-match.js.map +0 -1
- package/dist/checkpointer/internal/item-reader.d.ts +0 -55
- package/dist/checkpointer/internal/item-reader.d.ts.map +0 -1
- package/dist/checkpointer/internal/item-reader.js +0 -88
- package/dist/checkpointer/internal/item-reader.js.map +0 -1
- package/dist/checkpointer/internal/item-writer.d.ts +0 -26
- package/dist/checkpointer/internal/item-writer.d.ts.map +0 -1
- package/dist/checkpointer/internal/item-writer.js +0 -92
- package/dist/checkpointer/internal/item-writer.js.map +0 -1
- package/dist/checkpointer/internal/keys.d.ts +0 -31
- package/dist/checkpointer/internal/keys.d.ts.map +0 -1
- package/dist/checkpointer/internal/keys.js +0 -87
- package/dist/checkpointer/internal/keys.js.map +0 -1
- package/dist/checkpointer/internal/query.d.ts +0 -20
- package/dist/checkpointer/internal/query.d.ts.map +0 -1
- package/dist/checkpointer/internal/query.js +0 -36
- package/dist/checkpointer/internal/query.js.map +0 -1
- package/dist/checkpointer/internal/setup.d.ts.map +0 -1
- package/dist/checkpointer/internal/setup.js.map +0 -1
- package/dist/checkpointer/internal/special-write-cas.d.ts +0 -30
- package/dist/checkpointer/internal/special-write-cas.d.ts.map +0 -1
- package/dist/checkpointer/internal/special-write-cas.js +0 -104
- package/dist/checkpointer/internal/special-write-cas.js.map +0 -1
- package/dist/checkpointer/internal/special-write-cleanup.d.ts +0 -24
- package/dist/checkpointer/internal/special-write-cleanup.d.ts.map +0 -1
- package/dist/checkpointer/internal/special-write-cleanup.js +0 -47
- package/dist/checkpointer/internal/special-write-cleanup.js.map +0 -1
- package/dist/checkpointer/internal/special-write-verify.d.ts +0 -54
- package/dist/checkpointer/internal/special-write-verify.d.ts.map +0 -1
- package/dist/checkpointer/internal/special-write-verify.js +0 -65
- package/dist/checkpointer/internal/special-write-verify.js.map +0 -1
- package/dist/checkpointer/internal/validation.d.ts +0 -13
- package/dist/checkpointer/internal/validation.d.ts.map +0 -1
- package/dist/checkpointer/internal/validation.js +0 -30
- package/dist/checkpointer/internal/validation.js.map +0 -1
- package/dist/checkpointer/internal/write-guard.d.ts +0 -13
- package/dist/checkpointer/internal/write-guard.d.ts.map +0 -1
- package/dist/checkpointer/internal/write-guard.js +0 -39
- package/dist/checkpointer/internal/write-guard.js.map +0 -1
- package/dist/checkpointer/internal/write-index.d.ts +0 -37
- package/dist/checkpointer/internal/write-index.d.ts.map +0 -1
- package/dist/checkpointer/internal/write-index.js +0 -42
- package/dist/checkpointer/internal/write-index.js.map +0 -1
- package/dist/checkpointer/saver.d.ts.map +0 -1
- package/dist/checkpointer/saver.js.map +0 -1
- package/dist/checkpointer/types.d.ts.map +0 -1
- package/dist/checkpointer/types.js.map +0 -1
- package/dist/factory/factory.d.ts.map +0 -1
- package/dist/factory/factory.js.map +0 -1
- package/dist/history/actions/add-messages.d.ts.map +0 -1
- package/dist/history/actions/add-messages.js.map +0 -1
- package/dist/history/actions/clear.d.ts.map +0 -1
- package/dist/history/actions/clear.js.map +0 -1
- package/dist/history/actions/get-messages.d.ts.map +0 -1
- package/dist/history/actions/get-messages.js.map +0 -1
- package/dist/history/actions/list-sessions.d.ts.map +0 -1
- package/dist/history/actions/list-sessions.js.map +0 -1
- package/dist/history/actions/reconcile-count.d.ts.map +0 -1
- package/dist/history/actions/reconcile-count.js.map +0 -1
- package/dist/history/chat-message-history.d.ts.map +0 -1
- package/dist/history/chat-message-history.js.map +0 -1
- package/dist/history/internal/append-saga.d.ts +0 -20
- package/dist/history/internal/append-saga.d.ts.map +0 -1
- package/dist/history/internal/append-saga.js +0 -35
- package/dist/history/internal/append-saga.js.map +0 -1
- package/dist/history/internal/compensation.d.ts +0 -21
- package/dist/history/internal/compensation.d.ts.map +0 -1
- package/dist/history/internal/compensation.js +0 -84
- package/dist/history/internal/compensation.js.map +0 -1
- package/dist/history/internal/item-mapper.d.ts +0 -12
- package/dist/history/internal/item-mapper.d.ts.map +0 -1
- package/dist/history/internal/item-mapper.js +0 -33
- package/dist/history/internal/item-mapper.js.map +0 -1
- package/dist/history/internal/keys.d.ts +0 -17
- package/dist/history/internal/keys.d.ts.map +0 -1
- package/dist/history/internal/keys.js +0 -49
- package/dist/history/internal/keys.js.map +0 -1
- package/dist/history/internal/message-chunker.d.ts +0 -14
- package/dist/history/internal/message-chunker.d.ts.map +0 -1
- package/dist/history/internal/message-chunker.js +0 -68
- package/dist/history/internal/message-chunker.js.map +0 -1
- package/dist/history/internal/message-transaction.d.ts +0 -26
- package/dist/history/internal/message-transaction.d.ts.map +0 -1
- package/dist/history/internal/message-transaction.js +0 -60
- package/dist/history/internal/message-transaction.js.map +0 -1
- package/dist/history/internal/query.d.ts +0 -10
- package/dist/history/internal/query.d.ts.map +0 -1
- package/dist/history/internal/query.js +0 -31
- package/dist/history/internal/query.js.map +0 -1
- package/dist/history/internal/session-count.d.ts +0 -41
- package/dist/history/internal/session-count.d.ts.map +0 -1
- package/dist/history/internal/session-count.js +0 -109
- package/dist/history/internal/session-count.js.map +0 -1
- package/dist/history/internal/session-title.d.ts +0 -20
- package/dist/history/internal/session-title.d.ts.map +0 -1
- package/dist/history/internal/session-title.js +0 -44
- package/dist/history/internal/session-title.js.map +0 -1
- package/dist/history/internal/session-update.d.ts +0 -28
- package/dist/history/internal/session-update.d.ts.map +0 -1
- package/dist/history/internal/session-update.js +0 -70
- package/dist/history/internal/session-update.js.map +0 -1
- package/dist/history/internal/setup.d.ts.map +0 -1
- package/dist/history/internal/setup.js.map +0 -1
- package/dist/history/internal/title-generator.d.ts +0 -13
- package/dist/history/internal/title-generator.d.ts.map +0 -1
- package/dist/history/internal/title-generator.js +0 -25
- package/dist/history/internal/title-generator.js.map +0 -1
- package/dist/history/internal/ttl-anchor.d.ts +0 -25
- package/dist/history/internal/ttl-anchor.d.ts.map +0 -1
- package/dist/history/internal/ttl-anchor.js +0 -38
- package/dist/history/internal/ttl-anchor.js.map +0 -1
- package/dist/history/internal/validation.d.ts +0 -9
- package/dist/history/internal/validation.d.ts.map +0 -1
- package/dist/history/internal/validation.js +0 -16
- package/dist/history/internal/validation.js.map +0 -1
- package/dist/history/session-adapter.d.ts.map +0 -1
- package/dist/history/session-adapter.js.map +0 -1
- package/dist/history/types.d.ts.map +0 -1
- package/dist/history/types.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/shared/clock.d.ts.map +0 -1
- package/dist/shared/clock.js.map +0 -1
- package/dist/shared/codec/codec.d.ts.map +0 -1
- package/dist/shared/codec/codec.js.map +0 -1
- package/dist/shared/codec/compression.d.ts.map +0 -1
- package/dist/shared/codec/compression.js.map +0 -1
- package/dist/shared/codec/descriptor-keys.d.ts +0 -4
- package/dist/shared/codec/descriptor-keys.d.ts.map +0 -1
- package/dist/shared/codec/descriptor-keys.js +0 -14
- package/dist/shared/codec/descriptor-keys.js.map +0 -1
- package/dist/shared/codec/json-serde.d.ts.map +0 -1
- package/dist/shared/codec/json-serde.js.map +0 -1
- package/dist/shared/codec/s3/client.d.ts.map +0 -1
- package/dist/shared/codec/s3/client.js.map +0 -1
- package/dist/shared/codec/s3/config.d.ts.map +0 -1
- package/dist/shared/codec/s3/config.js.map +0 -1
- package/dist/shared/codec/s3/delete.d.ts +0 -8
- package/dist/shared/codec/s3/delete.d.ts.map +0 -1
- package/dist/shared/codec/s3/delete.js +0 -29
- package/dist/shared/codec/s3/delete.js.map +0 -1
- package/dist/shared/codec/s3/lifecycle.d.ts.map +0 -1
- package/dist/shared/codec/s3/lifecycle.js.map +0 -1
- package/dist/shared/codec/s3/offloader.d.ts.map +0 -1
- package/dist/shared/codec/s3/offloader.js.map +0 -1
- package/dist/shared/codec/s3/orphans.d.ts +0 -18
- package/dist/shared/codec/s3/orphans.d.ts.map +0 -1
- package/dist/shared/codec/s3/orphans.js +0 -58
- package/dist/shared/codec/s3/orphans.js.map +0 -1
- package/dist/shared/codec/s3/read-write.d.ts +0 -14
- package/dist/shared/codec/s3/read-write.d.ts.map +0 -1
- package/dist/shared/codec/s3/read-write.js +0 -43
- package/dist/shared/codec/s3/read-write.js.map +0 -1
- package/dist/shared/codec/s3/retry.d.ts +0 -5
- package/dist/shared/codec/s3/retry.d.ts.map +0 -1
- package/dist/shared/codec/s3/retry.js +0 -25
- package/dist/shared/codec/s3/retry.js.map +0 -1
- package/dist/shared/constants.d.ts +0 -64
- package/dist/shared/constants.d.ts.map +0 -1
- package/dist/shared/constants.js +0 -67
- package/dist/shared/constants.js.map +0 -1
- package/dist/shared/dynamodb/backoff.d.ts +0 -15
- package/dist/shared/dynamodb/backoff.d.ts.map +0 -1
- package/dist/shared/dynamodb/backoff.js +0 -48
- package/dist/shared/dynamodb/backoff.js.map +0 -1
- package/dist/shared/dynamodb/batch-write.d.ts.map +0 -1
- package/dist/shared/dynamodb/batch-write.js.map +0 -1
- package/dist/shared/dynamodb/cancellation.d.ts.map +0 -1
- package/dist/shared/dynamodb/cancellation.js.map +0 -1
- package/dist/shared/dynamodb/client.d.ts.map +0 -1
- package/dist/shared/dynamodb/client.js.map +0 -1
- package/dist/shared/dynamodb/conditional-put.d.ts +0 -51
- package/dist/shared/dynamodb/conditional-put.d.ts.map +0 -1
- package/dist/shared/dynamodb/conditional-put.js +0 -59
- package/dist/shared/dynamodb/conditional-put.js.map +0 -1
- package/dist/shared/dynamodb/drain-unprocessed.d.ts +0 -19
- package/dist/shared/dynamodb/drain-unprocessed.d.ts.map +0 -1
- package/dist/shared/dynamodb/drain-unprocessed.js +0 -44
- package/dist/shared/dynamodb/drain-unprocessed.js.map +0 -1
- package/dist/shared/dynamodb/paginate-core.d.ts +0 -22
- package/dist/shared/dynamodb/paginate-core.d.ts.map +0 -1
- package/dist/shared/dynamodb/paginate-core.js +0 -52
- package/dist/shared/dynamodb/paginate-core.js.map +0 -1
- package/dist/shared/dynamodb/paginate.d.ts.map +0 -1
- package/dist/shared/dynamodb/paginate.js.map +0 -1
- package/dist/shared/dynamodb/partition-delete.d.ts.map +0 -1
- package/dist/shared/dynamodb/partition-delete.js.map +0 -1
- package/dist/shared/dynamodb/retry-classifier.d.ts +0 -9
- package/dist/shared/dynamodb/retry-classifier.d.ts.map +0 -1
- package/dist/shared/dynamodb/retry-classifier.js +0 -87
- package/dist/shared/dynamodb/retry-classifier.js.map +0 -1
- package/dist/shared/dynamodb/retry.d.ts.map +0 -1
- package/dist/shared/dynamodb/retry.js.map +0 -1
- package/dist/shared/dynamodb/scan.d.ts +0 -15
- package/dist/shared/dynamodb/scan.d.ts.map +0 -1
- package/dist/shared/dynamodb/scan.js +0 -20
- package/dist/shared/dynamodb/scan.js.map +0 -1
- package/dist/shared/dynamodb/types.d.ts +0 -24
- package/dist/shared/dynamodb/types.d.ts.map +0 -1
- package/dist/shared/dynamodb/types.js +0 -3
- package/dist/shared/dynamodb/types.js.map +0 -1
- package/dist/shared/errors/base-error.d.ts.map +0 -1
- package/dist/shared/errors/base-error.js.map +0 -1
- package/dist/shared/errors/error-code.d.ts.map +0 -1
- package/dist/shared/errors/error-code.js.map +0 -1
- package/dist/shared/errors/errors.d.ts.map +0 -1
- package/dist/shared/errors/errors.js.map +0 -1
- package/dist/shared/errors/wrap-error.d.ts +0 -16
- package/dist/shared/errors/wrap-error.d.ts.map +0 -1
- package/dist/shared/errors/wrap-error.js +0 -30
- package/dist/shared/errors/wrap-error.js.map +0 -1
- package/dist/shared/logging/logger.d.ts.map +0 -1
- package/dist/shared/logging/logger.js.map +0 -1
- package/dist/shared/logging/redaction-walk.d.ts +0 -23
- package/dist/shared/logging/redaction-walk.d.ts.map +0 -1
- package/dist/shared/logging/redaction-walk.js +0 -92
- package/dist/shared/logging/redaction-walk.js.map +0 -1
- package/dist/shared/logging/redaction.d.ts.map +0 -1
- package/dist/shared/logging/redaction.js.map +0 -1
- package/dist/shared/logging/secret-patterns.d.ts.map +0 -1
- package/dist/shared/logging/secret-patterns.js.map +0 -1
- package/dist/shared/options.d.ts.map +0 -1
- package/dist/shared/options.js.map +0 -1
- package/dist/shared/ulid.d.ts.map +0 -1
- package/dist/shared/ulid.js.map +0 -1
- package/dist/shared/validation/primitives.d.ts.map +0 -1
- package/dist/shared/validation/primitives.js.map +0 -1
- package/dist/shared/validation/ttl.d.ts.map +0 -1
- package/dist/shared/validation/ttl.js.map +0 -1
- package/dist/store/actions/get.d.ts +0 -5
- package/dist/store/actions/get.d.ts.map +0 -1
- package/dist/store/actions/get.js +0 -35
- package/dist/store/actions/get.js.map +0 -1
- package/dist/store/actions/list-namespaces.d.ts.map +0 -1
- package/dist/store/actions/list-namespaces.js.map +0 -1
- package/dist/store/actions/put.d.ts.map +0 -1
- package/dist/store/actions/put.js.map +0 -1
- package/dist/store/actions/reconcile-vector-index.d.ts.map +0 -1
- package/dist/store/actions/reconcile-vector-index.js.map +0 -1
- package/dist/store/actions/search.d.ts.map +0 -1
- package/dist/store/actions/search.js.map +0 -1
- package/dist/store/internal/backend-search.d.ts +0 -5
- package/dist/store/internal/backend-search.d.ts.map +0 -1
- package/dist/store/internal/backend-search.js +0 -68
- package/dist/store/internal/backend-search.js.map +0 -1
- package/dist/store/internal/filter.d.ts.map +0 -1
- package/dist/store/internal/filter.js.map +0 -1
- package/dist/store/internal/index-reconcile.d.ts +0 -22
- package/dist/store/internal/index-reconcile.d.ts.map +0 -1
- package/dist/store/internal/index-reconcile.js +0 -105
- package/dist/store/internal/index-reconcile.js.map +0 -1
- package/dist/store/internal/index-sync.d.ts +0 -11
- package/dist/store/internal/index-sync.d.ts.map +0 -1
- package/dist/store/internal/index-sync.js +0 -26
- package/dist/store/internal/index-sync.js.map +0 -1
- package/dist/store/internal/item-mapper.d.ts +0 -25
- package/dist/store/internal/item-mapper.d.ts.map +0 -1
- package/dist/store/internal/item-mapper.js +0 -53
- package/dist/store/internal/item-mapper.js.map +0 -1
- package/dist/store/internal/keys.d.ts +0 -18
- package/dist/store/internal/keys.d.ts.map +0 -1
- package/dist/store/internal/keys.js +0 -42
- package/dist/store/internal/keys.js.map +0 -1
- package/dist/store/internal/namespace-match.d.ts +0 -12
- package/dist/store/internal/namespace-match.d.ts.map +0 -1
- package/dist/store/internal/namespace-match.js +0 -41
- package/dist/store/internal/namespace-match.js.map +0 -1
- package/dist/store/internal/overwrite-swap.d.ts +0 -33
- package/dist/store/internal/overwrite-swap.d.ts.map +0 -1
- package/dist/store/internal/overwrite-swap.js +0 -62
- package/dist/store/internal/overwrite-swap.js.map +0 -1
- package/dist/store/internal/persist.d.ts +0 -27
- package/dist/store/internal/persist.d.ts.map +0 -1
- package/dist/store/internal/persist.js +0 -59
- package/dist/store/internal/persist.js.map +0 -1
- package/dist/store/internal/query.d.ts +0 -6
- package/dist/store/internal/query.d.ts.map +0 -1
- package/dist/store/internal/query.js +0 -32
- package/dist/store/internal/query.js.map +0 -1
- package/dist/store/internal/ranker.d.ts +0 -13
- package/dist/store/internal/ranker.d.ts.map +0 -1
- package/dist/store/internal/ranker.js +0 -31
- package/dist/store/internal/ranker.js.map +0 -1
- package/dist/store/internal/read-existing.d.ts +0 -19
- package/dist/store/internal/read-existing.d.ts.map +0 -1
- package/dist/store/internal/read-existing.js +0 -29
- package/dist/store/internal/read-existing.js.map +0 -1
- package/dist/store/internal/score-direction.d.ts +0 -32
- package/dist/store/internal/score-direction.d.ts.map +0 -1
- package/dist/store/internal/score-direction.js +0 -39
- package/dist/store/internal/score-direction.js.map +0 -1
- package/dist/store/internal/search-filter.d.ts +0 -4
- package/dist/store/internal/search-filter.d.ts.map +0 -1
- package/dist/store/internal/search-filter.js +0 -11
- package/dist/store/internal/search-filter.js.map +0 -1
- package/dist/store/internal/semantic-search.d.ts.map +0 -1
- package/dist/store/internal/semantic-search.js.map +0 -1
- package/dist/store/internal/setup.d.ts.map +0 -1
- package/dist/store/internal/setup.js.map +0 -1
- package/dist/store/internal/validation.d.ts +0 -13
- package/dist/store/internal/validation.d.ts.map +0 -1
- package/dist/store/internal/validation.js +0 -35
- package/dist/store/internal/validation.js.map +0 -1
- package/dist/store/internal/write-verify.d.ts +0 -37
- package/dist/store/internal/write-verify.d.ts.map +0 -1
- package/dist/store/internal/write-verify.js +0 -68
- package/dist/store/internal/write-verify.js.map +0 -1
- package/dist/store/store.d.ts.map +0 -1
- package/dist/store/store.js.map +0 -1
- package/dist/store/types.d.ts.map +0 -1
- package/dist/store/types.js.map +0 -1
- package/dist/store/vector-backend.d.ts.map +0 -1
- package/dist/store/vector-backend.js.map +0 -1
|
@@ -1,53 +1,463 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Hides when and how a failed request is retried (record 14).
|
|
4
|
+
*
|
|
5
|
+
* Which failures are transient — read from an error's whole cause chain, its
|
|
6
|
+
* HTTP status and its retryable trait, and from a cancelled transaction's
|
|
7
|
+
* reasons — the full-jitter backoff schedule, the attempt budget and the
|
|
8
|
+
* deadline that can cut it short, and the policy an adapter resolves from its
|
|
9
|
+
* options at construction are one decision. Every DynamoDB call goes through
|
|
10
|
+
* it, and so does an S3 object upload and download; the bucket lifecycle calls
|
|
11
|
+
* (`maxAttempts: 1` on the S3 client) and orphan release, which retries on its
|
|
12
|
+
* own loop, do not.
|
|
13
|
+
*/
|
|
2
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
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;
|
|
3
16
|
exports.withRetry = withRetry;
|
|
4
17
|
exports.withDynamoDBRetry = withDynamoDBRetry;
|
|
5
|
-
|
|
18
|
+
exports.isRetryableError = isRetryableError;
|
|
19
|
+
exports.resolveRetryPolicy = resolveRetryPolicy;
|
|
20
|
+
exports.retryFor = retryFor;
|
|
21
|
+
exports.sleep = sleep;
|
|
22
|
+
exports.nextBackoffDelay = nextBackoffDelay;
|
|
23
|
+
exports.fullJitter = fullJitter;
|
|
24
|
+
exports.isTransientS3Error = isTransientS3Error;
|
|
25
|
+
const clock_1 = require("../clock");
|
|
26
|
+
const base_error_1 = require("../errors/base-error");
|
|
27
|
+
const classify_1 = require("../errors/classify");
|
|
6
28
|
const errors_1 = require("../errors/errors");
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const
|
|
29
|
+
const secret_patterns_1 = require("../logging/secret-patterns");
|
|
30
|
+
const truncate_1 = require("../logging/truncate");
|
|
31
|
+
const abort_1 = require("./abort");
|
|
32
|
+
const cancellation_1 = require("./cancellation");
|
|
33
|
+
/** Starting delay for UnprocessedItems / UnprocessedKeys backoff loops. */
|
|
34
|
+
exports.INITIAL_BACKOFF_DELAY_MS = 100;
|
|
35
|
+
/** Maximum backoff delay for retry loops. */
|
|
36
|
+
exports.MAX_BACKOFF_DELAY_MS = 5000;
|
|
37
|
+
/** Default maximum attempts for transient-error retries. */
|
|
38
|
+
exports.DEFAULT_RETRY_MAX_ATTEMPTS = 5;
|
|
39
|
+
/**
|
|
40
|
+
* How long DynamoDB treats a repeated client request token as the same request
|
|
41
|
+
* rather than a new one, so re-sending a tokened write is deduplicated instead
|
|
42
|
+
* of applied twice (10 minutes). Recorded as its own constant so the margin
|
|
43
|
+
* {@link MAX_WRITE_LIFETIME_MS} keeps under it is legible.
|
|
44
|
+
*/
|
|
45
|
+
exports.TOKEN_IDEMPOTENCY_WINDOW_MS = 600_000;
|
|
46
|
+
/**
|
|
47
|
+
* Longest one token-carrying write may keep retrying (5 minutes): half of
|
|
48
|
+
* {@link TOKEN_IDEMPOTENCY_WINDOW_MS}. The other half absorbs the attempt
|
|
49
|
+
* still in flight when the budget ends, clock skew between this client's own
|
|
50
|
+
* clock and DynamoDB's timer, and SDK-internal queueing, so a write that
|
|
51
|
+
* retries to the end still finishes well inside the window its token is
|
|
52
|
+
* honoured for. Its own literal rather than a division of the window:
|
|
53
|
+
* aliasing them would move one whenever the other is retuned (see
|
|
54
|
+
* `LIST_SCAN_WARN_THRESHOLD` (`src/shared/dynamodb/paginate.ts`)).
|
|
55
|
+
*/
|
|
56
|
+
exports.MAX_WRITE_LIFETIME_MS = 300_000;
|
|
57
|
+
/**
|
|
58
|
+
* Whether sleeping `delayMs` now would carry the budget past `deadlineAt`.
|
|
59
|
+
* No deadline, no bound: the schedule is then exactly what it always was.
|
|
60
|
+
*/
|
|
61
|
+
function crossesDeadline(deadlineAt, delayMs) {
|
|
62
|
+
return deadlineAt !== undefined && (0, clock_1.nowMs)() + delayMs >= deadlineAt;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* End the operation the moment the caller's signal has fired.
|
|
66
|
+
*
|
|
67
|
+
* One function for both observation points — before the first attempt, and
|
|
68
|
+
* after every failed one — so the two can never answer a cancel differently.
|
|
69
|
+
*/
|
|
70
|
+
function assertNotAborted(signal) {
|
|
71
|
+
if (signal?.aborted)
|
|
72
|
+
throw (0, abort_1.abortErrorFrom)(signal);
|
|
73
|
+
}
|
|
10
74
|
function delayForAttempt(attempt, base, max, rng) {
|
|
11
75
|
const exponential = base * 2 ** (attempt - 1);
|
|
12
|
-
return
|
|
76
|
+
return fullJitter(Math.min(exponential, max), rng);
|
|
13
77
|
}
|
|
14
78
|
/** Apply defaults to {@link RetryOptions}. */
|
|
15
79
|
function resolveRetryOptions(options) {
|
|
16
80
|
return {
|
|
17
|
-
maxAttempts: options.maxAttempts ??
|
|
18
|
-
baseDelayMs: options.baseDelayMs ??
|
|
19
|
-
maxDelayMs: options.maxDelayMs ??
|
|
20
|
-
|
|
81
|
+
maxAttempts: options.maxAttempts ?? exports.DEFAULT_RETRY_MAX_ATTEMPTS,
|
|
82
|
+
baseDelayMs: options.baseDelayMs ?? exports.INITIAL_BACKOFF_DELAY_MS,
|
|
83
|
+
maxDelayMs: options.maxDelayMs ?? exports.MAX_BACKOFF_DELAY_MS,
|
|
84
|
+
isRetryable: options.isRetryable ??
|
|
85
|
+
((error) => isRetryableError(error, options.retryableErrors ?? classify_1.DEFAULT_RETRYABLE_ERRORS)),
|
|
21
86
|
rng: options.rng ?? Math.random,
|
|
22
87
|
};
|
|
23
88
|
}
|
|
24
89
|
/**
|
|
25
|
-
* Run `fn`, retrying
|
|
26
|
-
*
|
|
27
|
-
* {@link
|
|
90
|
+
* Run `fn`, retrying transient failures with full-jitter exponential backoff.
|
|
91
|
+
*
|
|
92
|
+
* Accepts: `fn` — given the {@link SdkRequestOptions} for the attempt, to pass
|
|
93
|
+
* as the second argument of the SDK call it makes. That argument is what
|
|
94
|
+
* carries `options.signal` into the request, and it is the only way a call
|
|
95
|
+
* site can: `fn` closes over its own parameters, so nothing else reaches it.
|
|
96
|
+
* An `fn` that makes no cancellable call ignores the parameter and is written
|
|
97
|
+
* exactly as it was, since a zero-argument function still satisfies the type.
|
|
98
|
+
*
|
|
99
|
+
* Accepts: `options.maxAttempts` — total attempts including the first, default
|
|
100
|
+
* {@link DEFAULT_RETRY_MAX_ATTEMPTS}; at least 1, which `assertRetryPolicy`
|
|
101
|
+
* enforces for every caller-supplied policy. `options.baseDelayMs` /
|
|
102
|
+
* `maxDelayMs` — the backoff schedule. `options.isRetryable` — replaces
|
|
103
|
+
* `retryableErrors` entirely, so a call site can share one classifier with
|
|
104
|
+
* paths that do not go through here. `options.signal` — checked before the
|
|
105
|
+
* first attempt, handed to every attempt as `abortSignal` so the request in
|
|
106
|
+
* flight is cancelled rather than merely awaited, checked again when an
|
|
107
|
+
* attempt fails, and honoured during every backoff wait. `options.onRetry` —
|
|
108
|
+
* called synchronously before each wait; an exception from it is not caught
|
|
109
|
+
* and ends the operation. `options.deadlineAt` — an internal bound on the
|
|
110
|
+
* whole budget rather than on one attempt: the wait that would carry the
|
|
111
|
+
* operation past it is never started, and the budget ends there instead.
|
|
112
|
+
* Without it the schedule, the attempt count and every error are unchanged.
|
|
113
|
+
*
|
|
114
|
+
* Returns: whatever `fn` resolves to, from the first attempt that succeeds.
|
|
115
|
+
*
|
|
116
|
+
* Throws: the error itself, unchanged, when it is not retryable — a
|
|
117
|
+
* `ValidationException` or a permission failure is never retried;
|
|
118
|
+
* `ABORTED` when the signal fires, including during a wait and
|
|
119
|
+
* including while a request is in flight — the SDK rejects the cancelled
|
|
120
|
+
* request with an error of its own, and a failed attempt whose signal has
|
|
121
|
+
* fired is reported as the cancel it is rather than being classified, retried
|
|
122
|
+
* or wrapped; `RETRY_EXHAUSTED` once the budget ends, carrying the attempt
|
|
123
|
+
* actually reached — not the attempts configured — and the last error as
|
|
124
|
+
* `cause`. Its message quotes the last error **redacted**, because it reaches
|
|
125
|
+
* `err.message`, which an application may print without a redacting logger.
|
|
126
|
+
*
|
|
127
|
+
* A deadline that ends the budget is reported exactly as a spent one, by the
|
|
128
|
+
* same error with the same code: a caller cannot tell the two apart, and
|
|
129
|
+
* nothing needs to, since the handling of both is identical — read the row
|
|
130
|
+
* back, and release only what is confirmed not to have landed.
|
|
131
|
+
*
|
|
132
|
+
* A cancelled wait is also an abort no longer observed. The signal is read
|
|
133
|
+
* before the first attempt, after every failed one, and inside each wait, so
|
|
134
|
+
* ending the budget in place of a wait drops only that last observation point:
|
|
135
|
+
* a signal that fires *after* the deadline has already refused the wait, in
|
|
136
|
+
* the window where the wait would have been running, surfaces as
|
|
137
|
+
* `RETRY_EXHAUSTED` rather than `ABORTED`. One already set
|
|
138
|
+
* at entry, fired during an attempt, or fired during an earlier wait, is still
|
|
139
|
+
* caught.
|
|
140
|
+
*
|
|
141
|
+
* Guarantees: `fn` is called at least once and at most `maxAttempts` times. A
|
|
142
|
+
* thrown non-`Error` is wrapped, so what a caller catches is always an `Error`.
|
|
28
143
|
*/
|
|
29
144
|
async function withRetry(fn, options = {}) {
|
|
30
|
-
const { maxAttempts, baseDelayMs, maxDelayMs,
|
|
31
|
-
|
|
32
|
-
|
|
145
|
+
const { maxAttempts, baseDelayMs, maxDelayMs, isRetryable, rng } = resolveRetryOptions(options);
|
|
146
|
+
assertNotAborted(options.signal);
|
|
147
|
+
// Built once and handed to every attempt. The SDK reads it and keeps
|
|
148
|
+
// nothing, so one object costs one allocation per operation instead of one
|
|
149
|
+
// per attempt, and a re-send cannot differ from the send before it.
|
|
150
|
+
const request = { abortSignal: options.signal };
|
|
33
151
|
let lastError = new Error('Retry failed without error');
|
|
152
|
+
let attempts = 0;
|
|
34
153
|
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
154
|
+
attempts = attempt;
|
|
35
155
|
try {
|
|
36
|
-
return await fn();
|
|
156
|
+
return await fn(request);
|
|
37
157
|
}
|
|
38
158
|
catch (error) {
|
|
39
|
-
|
|
40
|
-
|
|
159
|
+
// Read before the error is classified. A cancelled request rejects with
|
|
160
|
+
// whatever the transport produced — the SDK's own `AbortError` for one
|
|
161
|
+
// cut before the response, a socket error for one cut mid-body — and
|
|
162
|
+
// both would otherwise be classified, retried against a signal that has
|
|
163
|
+
// already fired, and finally reported as a transport failure. A caller
|
|
164
|
+
// who cancelled is owed `ABORTED`, not a diagnosis of its own stop.
|
|
165
|
+
assertNotAborted(options.signal);
|
|
166
|
+
lastError = (0, base_error_1.toError)(error);
|
|
167
|
+
if (!isRetryable(lastError))
|
|
41
168
|
throw lastError;
|
|
42
169
|
if (attempt === maxAttempts)
|
|
43
170
|
break;
|
|
44
|
-
|
|
171
|
+
const delayMs = delayForAttempt(attempt, baseDelayMs, maxDelayMs, rng);
|
|
172
|
+
if (crossesDeadline(options.deadlineAt, delayMs))
|
|
173
|
+
break;
|
|
174
|
+
options.onRetry?.({ attempt, delayMs, error: lastError });
|
|
175
|
+
await sleep(delayMs, options.signal);
|
|
45
176
|
}
|
|
46
177
|
}
|
|
47
|
-
throw
|
|
178
|
+
throw (0, errors_1.retryExhaustedError)(`Operation failed after ${attempts} attempts: ${(0, secret_patterns_1.redactedMessage)(lastError)}`, attempts, lastError);
|
|
48
179
|
}
|
|
49
|
-
/**
|
|
180
|
+
/**
|
|
181
|
+
* {@link withRetry} with this package's DynamoDB defaults.
|
|
182
|
+
*
|
|
183
|
+
* Accepts: `overrides` — merged over `maxAttempts:`
|
|
184
|
+
* {@link DEFAULT_RETRY_MAX_ATTEMPTS}, so an adapter's resolved policy wins.
|
|
185
|
+
*
|
|
186
|
+
* Returns: as {@link withRetry}.
|
|
187
|
+
*
|
|
188
|
+
* Throws: as {@link withRetry}.
|
|
189
|
+
*/
|
|
50
190
|
async function withDynamoDBRetry(fn, overrides) {
|
|
51
|
-
return withRetry(fn, { maxAttempts:
|
|
191
|
+
return withRetry(fn, { maxAttempts: exports.DEFAULT_RETRY_MAX_ATTEMPTS, ...overrides });
|
|
192
|
+
}
|
|
193
|
+
const MAX_CAUSE_DEPTH = 32;
|
|
194
|
+
/** Add one node's signal tokens, HTTP status and retryable trait to `evidence`. */
|
|
195
|
+
function recordNode(fields, evidence) {
|
|
196
|
+
for (const value of [fields.name, fields.code, fields.errno, fields.syscall]) {
|
|
197
|
+
if (typeof value === 'string')
|
|
198
|
+
evidence.signals.push(value);
|
|
199
|
+
}
|
|
200
|
+
if (typeof fields.$metadata?.httpStatusCode === 'number') {
|
|
201
|
+
evidence.statuses.push(fields.$metadata.httpStatusCode);
|
|
202
|
+
}
|
|
203
|
+
if (fields.$retryable !== undefined && fields.$retryable !== null)
|
|
204
|
+
evidence.retryableByTrait = true;
|
|
205
|
+
}
|
|
206
|
+
function collectEvidence(error) {
|
|
207
|
+
const seen = new WeakSet();
|
|
208
|
+
const evidence = { signals: [], statuses: [], retryableByTrait: false };
|
|
209
|
+
const walk = (node, depth) => {
|
|
210
|
+
if (depth > MAX_CAUSE_DEPTH || node === null || typeof node !== 'object' || seen.has(node)) {
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
seen.add(node);
|
|
214
|
+
const fields = node;
|
|
215
|
+
recordNode(fields, evidence);
|
|
216
|
+
if (fields.cause)
|
|
217
|
+
walk(fields.cause, depth + 1);
|
|
218
|
+
};
|
|
219
|
+
walk(error, 0);
|
|
220
|
+
return evidence;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Whether `error`, or any cause in its chain, is transient.
|
|
224
|
+
*
|
|
225
|
+
* Accepts: `error` — an `Error`; its `cause` chain is walked to
|
|
226
|
+
* {@link MAX_CAUSE_DEPTH}, and a cycle in it terminates the walk rather than
|
|
227
|
+
* looping. Anything else a `throw` can produce carries no node to walk and is
|
|
228
|
+
* not retryable. `retryableErrors` — the signal tokens to match; an empty list
|
|
229
|
+
* still admits the trait and status rules below.
|
|
230
|
+
*
|
|
231
|
+
* Returns: true when any of these holds, in this order —
|
|
232
|
+
* 1. the error is a transaction cancellation and **every** reason it carries is
|
|
233
|
+
* transient. This verdict is final either way: a permanent reason arrives
|
|
234
|
+
* with the same HTTP status as a transient one, so the later rules cannot be
|
|
235
|
+
* allowed to overturn it. A cancellation carrying no reasons is not retried.
|
|
236
|
+
* 2. any node carries the SDK's `$retryable` trait;
|
|
237
|
+
* 3. any node's HTTP status is in {@link TRANSIENT_HTTP_STATUSES} — which is
|
|
238
|
+
* what classifies a failure the SDK could not map to a modeled exception,
|
|
239
|
+
* arriving as `name: 'Unknown'` with only a status;
|
|
240
|
+
* 4. any node's `name`, `code`, `errno` or `syscall` equals a token in
|
|
241
|
+
* `retryableErrors`.
|
|
242
|
+
*
|
|
243
|
+
* The token match is exact, never substring: these fields are whole tokens, and
|
|
244
|
+
* a substring rule would let an unrelated name that merely contains one ride
|
|
245
|
+
* along.
|
|
246
|
+
*
|
|
247
|
+
* Throws: **nothing**, for any value a `throw` can produce — see
|
|
248
|
+
* {@link transientCancellation}, which the first rule reads through.
|
|
249
|
+
*/
|
|
250
|
+
function isRetryableError(error, retryableErrors) {
|
|
251
|
+
const cancellation = (0, cancellation_1.transientCancellation)(error);
|
|
252
|
+
if (cancellation !== undefined)
|
|
253
|
+
return cancellation;
|
|
254
|
+
const evidence = collectEvidence(error);
|
|
255
|
+
if (evidence.retryableByTrait)
|
|
256
|
+
return true;
|
|
257
|
+
if (evidence.statuses.some((status) => classify_1.TRANSIENT_HTTP_STATUSES.includes(status)))
|
|
258
|
+
return true;
|
|
259
|
+
return evidence.signals.some((signal) => retryableErrors.includes(signal));
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* The nominal worst case of a policy's backoff schedule, in milliseconds.
|
|
263
|
+
*
|
|
264
|
+
* `withRetry` sleeps *between* attempts, so a budget of `maxAttempts` attempts
|
|
265
|
+
* holds `maxAttempts - 1` sleeps, and full jitter draws the k-th of them from
|
|
266
|
+
* `[0, min(baseDelayMs * 2 ** (k - 1), maxDelayMs))`. The worst case is
|
|
267
|
+
* therefore the **sum of those caps**:
|
|
268
|
+
*
|
|
269
|
+
* `sum over k in 1..maxAttempts-1 of min(baseDelayMs * 2 ** (k - 1), maxDelayMs)`
|
|
270
|
+
*
|
|
271
|
+
* It is stated here because the reading a reader reaches for —
|
|
272
|
+
* `maxAttempts * maxDelayMs` — is wrong in both directions at once: it counts
|
|
273
|
+
* a sleep after the final attempt, which never happens, and it charges the cap
|
|
274
|
+
* for every early sleep the exponential has not yet climbed to. At the
|
|
275
|
+
* defaults - five attempts, so four sleeps - they total 1.5 s where the naive
|
|
276
|
+
* reading says 25 s.
|
|
277
|
+
*
|
|
278
|
+
* Nominal, not actual: each sleep is drawn uniformly below its cap, so a real
|
|
279
|
+
* budget averages about half of this and only approaches it in the limit. The
|
|
280
|
+
* cap is what a bound has to be measured against all the same.
|
|
281
|
+
*/
|
|
282
|
+
function nominalBudgetMs(policy) {
|
|
283
|
+
let total = 0;
|
|
284
|
+
for (let sleep = 1; sleep < policy.maxAttempts; sleep++) {
|
|
285
|
+
total += Math.min(policy.baseDelayMs * 2 ** (sleep - 1), policy.maxDelayMs);
|
|
286
|
+
}
|
|
287
|
+
return total;
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Warn when a policy's nominal budget outlives {@link MAX_WRITE_LIFETIME_MS},
|
|
291
|
+
* the deadline every token-carrying write in this package runs under.
|
|
292
|
+
*
|
|
293
|
+
* Warn, never refuse. A long policy is the caller's own choice, it stays
|
|
294
|
+
* legal, and the deadline already makes it safe — what it is not, without this
|
|
295
|
+
* line, is visible: a deadline that ends a budget early and a budget that is
|
|
296
|
+
* simply spent both surface as the same `RETRY_EXHAUSTED` error, so the first
|
|
297
|
+
* evidence that a configured policy can never run to its end would otherwise
|
|
298
|
+
* be an incident. Said once, at construction, it is said before the first
|
|
299
|
+
* write rather than after.
|
|
300
|
+
*/
|
|
301
|
+
function warnIfOutlivesWriteLifetime(policy, logger) {
|
|
302
|
+
const budgetMs = nominalBudgetMs(policy);
|
|
303
|
+
if (budgetMs <= exports.MAX_WRITE_LIFETIME_MS)
|
|
304
|
+
return;
|
|
305
|
+
logger.warn('retry policy outlives the write lifetime; the budget will be cut short', {
|
|
306
|
+
budgetMs,
|
|
307
|
+
maxWriteLifetimeMs: exports.MAX_WRITE_LIFETIME_MS,
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Resolve an adapter's retry policy once, at construction.
|
|
312
|
+
*
|
|
313
|
+
* Accepts: `policy` — the caller's, already validated, or nothing. `logger` —
|
|
314
|
+
* the adapter's resolved logger.
|
|
315
|
+
*
|
|
316
|
+
* Returns: the options every DynamoDB call of that adapter uses, with each
|
|
317
|
+
* field defaulted and the logger attached, so every retry is visible at `debug`
|
|
318
|
+
* (the attempt, the delay about to be slept, the error's name) instead of only
|
|
319
|
+
* surfacing once the budget is exhausted.
|
|
320
|
+
*
|
|
321
|
+
* Accepts: `attemptFloor` — the lowest attempt count this adapter will actually
|
|
322
|
+
* use, when it raises a caller's below its own. The budget is warned about at
|
|
323
|
+
* that number rather than at the caller's, because it is the one the writes
|
|
324
|
+
* will really spend; an adapter that honours the caller's count passes none.
|
|
325
|
+
*
|
|
326
|
+
* Throws: nothing; the policy was validated where it was given. A policy whose
|
|
327
|
+
* nominal budget outlives {@link MAX_WRITE_LIFETIME_MS} is warned about rather
|
|
328
|
+
* than refused, once per adapter constructed — three adapters built from one
|
|
329
|
+
* long policy each say so for themselves — see
|
|
330
|
+
* {@link warnIfOutlivesWriteLifetime}. The defaults are far inside it and say
|
|
331
|
+
* nothing.
|
|
332
|
+
*/
|
|
333
|
+
function resolveRetryPolicy(policy, logger, attemptFloor = 0) {
|
|
334
|
+
const resolved = {
|
|
335
|
+
maxAttempts: policy?.maxAttempts ?? exports.DEFAULT_RETRY_MAX_ATTEMPTS,
|
|
336
|
+
baseDelayMs: policy?.baseDelayMs ?? exports.INITIAL_BACKOFF_DELAY_MS,
|
|
337
|
+
maxDelayMs: policy?.maxDelayMs ?? exports.MAX_BACKOFF_DELAY_MS,
|
|
338
|
+
};
|
|
339
|
+
// Measured at the attempts the adapter will really make, not at the ones the
|
|
340
|
+
// caller wrote. The history append raises a caller's count to its own floor
|
|
341
|
+
// while keeping the caller's delays, so a policy that only raises
|
|
342
|
+
// `maxDelayMs` produces a budget far past the deadline and would otherwise
|
|
343
|
+
// be warned about nowhere. An adapter with no floor passes none.
|
|
344
|
+
warnIfOutlivesWriteLifetime({ ...resolved, maxAttempts: Math.max(resolved.maxAttempts, attemptFloor) }, logger);
|
|
345
|
+
return {
|
|
346
|
+
...resolved,
|
|
347
|
+
// The name, never the message — and bounded: the transient failure came
|
|
348
|
+
// from the SDK, the transport or a caller's own collaborator, and nothing
|
|
349
|
+
// this package ran checked how long its name is. This line fires once per
|
|
350
|
+
// retry, so an unbounded one is paid for per attempt.
|
|
351
|
+
onRetry: ({ attempt, delayMs, error }) => logger.debug('retrying after a transient error', {
|
|
352
|
+
attempt,
|
|
353
|
+
delayMs,
|
|
354
|
+
error: (0, truncate_1.truncateForLog)((0, base_error_1.failureLabel)(error)),
|
|
355
|
+
}),
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* The context's retry options plus a per-call cancellation signal.
|
|
360
|
+
*
|
|
361
|
+
* Accepts: `context.retry` — the adapter's resolved policy. `signal` — the
|
|
362
|
+
* caller's, when the call takes one.
|
|
363
|
+
*
|
|
364
|
+
* Returns: the adapter's options untouched when there is no signal — the same
|
|
365
|
+
* object, so no per-call allocation on the common path — and a copy carrying it
|
|
366
|
+
* when there is.
|
|
367
|
+
*
|
|
368
|
+
* Throws: nothing.
|
|
369
|
+
*/
|
|
370
|
+
function retryFor(context, signal) {
|
|
371
|
+
return signal === undefined ? context.retry : { ...context.retry, signal };
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Wait `ms` milliseconds, cancellable.
|
|
375
|
+
*
|
|
376
|
+
* Accepts: `ms` — the delay. `signal` — omitted waits uninterruptibly; already
|
|
377
|
+
* aborted rejects before any timer is set; aborting while pending rejects at
|
|
378
|
+
* that moment and clears the timer.
|
|
379
|
+
*
|
|
380
|
+
* Returns: a promise resolving when the delay elapses.
|
|
381
|
+
*
|
|
382
|
+
* Throws: an `ABORTED` error however the signal was aborted —
|
|
383
|
+
* with a `DOMException`, a string or a custom reason (see
|
|
384
|
+
* {@link abortErrorFrom}).
|
|
385
|
+
*
|
|
386
|
+
* Guarantees: exactly one of resolve and reject runs, and neither the timer nor
|
|
387
|
+
* the abort listener outlives the call. The listener is attached before the
|
|
388
|
+
* timer is armed, so a signal whose `addEventListener` throws rejects the wait
|
|
389
|
+
* with nothing left behind — armed first, the timer outlived that rejection
|
|
390
|
+
* and later called `removeEventListener` outside any promise. A listener that
|
|
391
|
+
* runs while it is being attached settles the wait before any timer exists.
|
|
392
|
+
*/
|
|
393
|
+
function sleep(ms, signal) {
|
|
394
|
+
if (signal?.aborted) {
|
|
395
|
+
return Promise.reject((0, abort_1.abortErrorFrom)(signal));
|
|
396
|
+
}
|
|
397
|
+
return new Promise((resolve, reject) => {
|
|
398
|
+
// One holder for both flags, declared before `onAbort` reads the timer:
|
|
399
|
+
// the timer is assigned only once armed, after the listener is attached.
|
|
400
|
+
const wait = { settled: false };
|
|
401
|
+
const onAbort = () => {
|
|
402
|
+
if (wait.settled)
|
|
403
|
+
return;
|
|
404
|
+
wait.settled = true;
|
|
405
|
+
clearTimeout(wait.timer);
|
|
406
|
+
reject((0, abort_1.abortErrorFrom)(signal));
|
|
407
|
+
};
|
|
408
|
+
signal?.addEventListener('abort', onAbort, { once: true });
|
|
409
|
+
if (wait.settled)
|
|
410
|
+
return;
|
|
411
|
+
wait.timer = setTimeout(() => {
|
|
412
|
+
if (wait.settled)
|
|
413
|
+
return;
|
|
414
|
+
wait.settled = true;
|
|
415
|
+
signal?.removeEventListener('abort', onAbort);
|
|
416
|
+
resolve();
|
|
417
|
+
}, ms);
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
/**
|
|
421
|
+
* The next exponential-backoff delay.
|
|
422
|
+
*
|
|
423
|
+
* Accepts: `currentMs` — the delay just used; at least 1, since doubling 0
|
|
424
|
+
* never grows. `maxMs` — the ceiling, default {@link MAX_BACKOFF_DELAY_MS}.
|
|
425
|
+
*
|
|
426
|
+
* Returns: `min(currentMs * 2, maxMs)`.
|
|
427
|
+
*
|
|
428
|
+
* Throws: nothing.
|
|
429
|
+
*/
|
|
430
|
+
function nextBackoffDelay(currentMs, maxMs = exports.MAX_BACKOFF_DELAY_MS) {
|
|
431
|
+
return Math.min(currentMs * 2, maxMs);
|
|
432
|
+
}
|
|
433
|
+
/**
|
|
434
|
+
* AWS's full jitter over a backoff delay.
|
|
435
|
+
*
|
|
436
|
+
* Accepts: `delayMs` — the unjittered delay. `rng` — a seam returning
|
|
437
|
+
* `[0, 1)`, default `Math.random`; tests inject a fixed one.
|
|
438
|
+
*
|
|
439
|
+
* Returns: a value in `[0, delayMs)`, so two clients retrying the same failure
|
|
440
|
+
* do not retry together
|
|
441
|
+
* (https://aws.amazon.com/builders-library/timeouts-retries-and-backoff-with-jitter/).
|
|
442
|
+
*
|
|
443
|
+
* Throws: nothing.
|
|
444
|
+
*/
|
|
445
|
+
function fullJitter(delayMs, rng = Math.random) {
|
|
446
|
+
return rng() * delayMs;
|
|
447
|
+
}
|
|
448
|
+
/**
|
|
449
|
+
* Whether `error` is a transient S3 failure worth retrying.
|
|
450
|
+
*
|
|
451
|
+
* Accepts: `error` — any error, including one carrying no name or code, and
|
|
452
|
+
* equally anything else a `throw` can produce.
|
|
453
|
+
*
|
|
454
|
+
* Returns: {@link isRetryableError} over the shared default tokens, which hold
|
|
455
|
+
* S3's own transient names (`SlowDown`, `InternalError`,
|
|
456
|
+
* `ConditionalRequestConflict`) alongside DynamoDB's — one list, so the two
|
|
457
|
+
* services cannot drift apart on what is transient.
|
|
458
|
+
*
|
|
459
|
+
* Throws: **nothing**, for any value; {@link isRetryableError} is total.
|
|
460
|
+
*/
|
|
461
|
+
function isTransientS3Error(error) {
|
|
462
|
+
return isRetryableError(error, classify_1.DEFAULT_RETRYABLE_ERRORS);
|
|
52
463
|
}
|
|
53
|
-
//# sourceMappingURL=retry.js.map
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hides the conventions every row of the shared table follows, whichever
|
|
3
|
+
* adapter wrote it.
|
|
4
|
+
*
|
|
5
|
+
* The three adapters share one table (record 2), so a few things are decided
|
|
6
|
+
* once for all of them: the two key attributes every row has, the format
|
|
7
|
+
* version every row is stamped with and refused above (record 7), the `ttl`
|
|
8
|
+
* attribute that makes a row absent before DynamoDB's sweep removes it, and the
|
|
9
|
+
* order the server gives string keys. Which segments a feature's keys carry is
|
|
10
|
+
* that feature's `rows` module's decision; that they are written into these
|
|
11
|
+
* attributes and read back in this order is this module's.
|
|
12
|
+
*/
|
|
13
|
+
import type { QueryCommandInput, ScanCommandInput } from '@aws-sdk/lib-dynamodb';
|
|
14
|
+
import type { AttributeMap } from './client';
|
|
15
|
+
/** The attribute every row is partitioned by. */
|
|
16
|
+
export declare const PARTITION_KEY_ATTRIBUTE = "PK";
|
|
17
|
+
/** The attribute every row is sorted by within its partition. */
|
|
18
|
+
export declare const SORT_KEY_ATTRIBUTE = "SK";
|
|
19
|
+
/**
|
|
20
|
+
* Byte caps on caller-supplied identifiers, measured as UTF-8. DynamoDB caps a
|
|
21
|
+
* partition key at 2048 bytes and a sort key at 1024; S3 caps an object key at
|
|
22
|
+
* 1024. These leave room for the adapter prefixes and separators that compose
|
|
23
|
+
* the stored keys, so a value that passes validation fails as a typed error
|
|
24
|
+
* here rather than as a raw AWS ValidationException on the write.
|
|
25
|
+
*
|
|
26
|
+
* Partition-key identifiers: `thread_id` and `sessionId`.
|
|
27
|
+
*/
|
|
28
|
+
export declare const MAX_PARTITION_ID_BYTES = 1024;
|
|
29
|
+
/**
|
|
30
|
+
* Sort-key segments: `checkpoint_ns`, `checkpoint_id`, `taskId`, a pending-write
|
|
31
|
+
* channel, a store namespace element and a store `key`.
|
|
32
|
+
*/
|
|
33
|
+
export declare const MAX_KEY_SEGMENT_BYTES = 256;
|
|
34
|
+
/**
|
|
35
|
+
* DynamoDB cap on a whole sort key; composed keys are checked against it too.
|
|
36
|
+
*
|
|
37
|
+
* @see https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html
|
|
38
|
+
*/
|
|
39
|
+
export declare const MAX_SORT_KEY_BYTES = 1024;
|
|
40
|
+
/**
|
|
41
|
+
* The separator between the segments of every key this package composes. No
|
|
42
|
+
* caller-supplied identifier may contain it (the parsers refuse it), which is
|
|
43
|
+
* what lets a key be read back into its parts and matched by prefix (record 2).
|
|
44
|
+
*/
|
|
45
|
+
export declare const KEY_SEPARATOR = "#";
|
|
46
|
+
/**
|
|
47
|
+
* The tag each adapter's partition keys open with. The three differ in their
|
|
48
|
+
* first character, so no two adapters' partitions can collide on a shared
|
|
49
|
+
* table, whatever identifiers their callers reuse (record 2).
|
|
50
|
+
*/
|
|
51
|
+
export declare const ADAPTER_TAGS: {
|
|
52
|
+
readonly checkpointer: 'CHKPT';
|
|
53
|
+
readonly store: 'STORE';
|
|
54
|
+
readonly history: 'HIST';
|
|
55
|
+
};
|
|
56
|
+
/** A row's primary key, as a `Key` document and as the key half of an item. */
|
|
57
|
+
export interface RowKey {
|
|
58
|
+
PK: string;
|
|
59
|
+
SK: string;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* The key of a row already in hand.
|
|
63
|
+
*
|
|
64
|
+
* Accepts: `row` — an item read from, or about to be written to, the table.
|
|
65
|
+
*
|
|
66
|
+
* Returns: its `PK` and `SK`, and nothing else, so it can be sent as a `Key`
|
|
67
|
+
* without the rest of the item.
|
|
68
|
+
*
|
|
69
|
+
* Throws: nothing.
|
|
70
|
+
*/
|
|
71
|
+
export declare function rowKeyOf(row: AttributeMap): RowKey;
|
|
72
|
+
/** The only attribute this module reads: a row's own format version. */
|
|
73
|
+
export interface VersionedRow {
|
|
74
|
+
v?: number;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* The format version this package stamps on every row it writes.
|
|
78
|
+
*
|
|
79
|
+
* Before it existed, "written by an older version" was inferred from a missing
|
|
80
|
+
* attribute — `rev`, `occurrence`, `writeGroup`, `storedChannels`. That
|
|
81
|
+
* inference is unreadable to a maintainer and it is not even expressible: a
|
|
82
|
+
* lookup cannot tell an attribute that is *absent* from one that is *present
|
|
83
|
+
* and undefined*, which reversed first-write-wins for pending writes across an
|
|
84
|
+
* upgrade. A row states its own version instead.
|
|
85
|
+
*/
|
|
86
|
+
export declare const ROW_FORMAT_VERSION = 1;
|
|
87
|
+
/** The highest version this package knows how to read. */
|
|
88
|
+
export declare const SUPPORTED_ROW_FORMAT_VERSION = 1;
|
|
89
|
+
/**
|
|
90
|
+
* A row's format version.
|
|
91
|
+
*
|
|
92
|
+
* Accepts: `row` — any row. One carrying no numeric `v` predates the attribute.
|
|
93
|
+
*
|
|
94
|
+
* Returns: the stamped version, or `0` for a row without one — the version
|
|
95
|
+
* whose rules applied when it was written.
|
|
96
|
+
*
|
|
97
|
+
* Throws: nothing.
|
|
98
|
+
*/
|
|
99
|
+
export declare function rowVersionOf(row: VersionedRow): number;
|
|
100
|
+
/**
|
|
101
|
+
* Refuse a row written by a newer version of this package.
|
|
102
|
+
*
|
|
103
|
+
* Accepts: `row` — any row; one at or below
|
|
104
|
+
* {@link SUPPORTED_ROW_FORMAT_VERSION} is accepted, which includes every row
|
|
105
|
+
* written before the attribute existed. `what` — the row kind, named in the
|
|
106
|
+
* message.
|
|
107
|
+
*
|
|
108
|
+
* Returns: nothing: `row` is kept under its declared type, and this checks
|
|
109
|
+
* it.
|
|
110
|
+
*
|
|
111
|
+
* Throws: `FORMAT_UNSUPPORTED` naming the field `v`. Guessing at a shape this
|
|
112
|
+
* version does not know is how a reader returns a checkpoint with silently
|
|
113
|
+
* missing state, so the caller is told to upgrade instead.
|
|
114
|
+
*/
|
|
115
|
+
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
|
+
/**
|
|
129
|
+
* Whether a row has reached its TTL.
|
|
130
|
+
*
|
|
131
|
+
* Accepts: `row` — any row; one without a `ttl` attribute never expires.
|
|
132
|
+
* `nowSeconds` — the current epoch **second**, the unit the attribute uses.
|
|
133
|
+
*
|
|
134
|
+
* Returns: true when `ttl <= nowSeconds`, so the expiry instant itself counts
|
|
135
|
+
* as expired.
|
|
136
|
+
*
|
|
137
|
+
* Throws: nothing.
|
|
138
|
+
*
|
|
139
|
+
* Guarantees: an expired row is absent to every reader even while DynamoDB's
|
|
140
|
+
* own sweep lags, which it may by up to 48 hours
|
|
141
|
+
* (https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/howitworks-ttl.html).
|
|
142
|
+
*/
|
|
143
|
+
export declare function isExpiredRow(row: {
|
|
144
|
+
ttl?: number;
|
|
145
|
+
}, nowSeconds: number): boolean;
|
|
146
|
+
/**
|
|
147
|
+
* The same query with expired rows filtered out server-side.
|
|
148
|
+
*
|
|
149
|
+
* Accepts: `params` — a Query or Scan input, with or without a
|
|
150
|
+
* `FilterExpression`; an existing one is ANDed rather than replaced.
|
|
151
|
+
* `nowSeconds` — the epoch second to compare against.
|
|
152
|
+
*
|
|
153
|
+
* Returns: a copy carrying the added filter and the `#ttl` / `:now` aliases. No
|
|
154
|
+
* other call site in this package uses those two names, so the merge cannot
|
|
155
|
+
* shadow a caller's own alias.
|
|
156
|
+
*
|
|
157
|
+
* Throws: nothing.
|
|
158
|
+
*
|
|
159
|
+
* Guarantees: this trims transfer only. It never replaces the in-process
|
|
160
|
+
* {@link isExpiredRow} check, because the query is built and its rows are read
|
|
161
|
+
* at two different instants, and DynamoDB applies a filter *after* `Limit`.
|
|
162
|
+
*/
|
|
163
|
+
export declare function withoutExpired<T extends QueryCommandInput | ScanCommandInput>(params: T, nowSeconds: number): T;
|
|
164
|
+
/**
|
|
165
|
+
* Order two DynamoDB string sort keys the way the server orders them.
|
|
166
|
+
*
|
|
167
|
+
* DynamoDB compares a string key by the bytes of its UTF-8 encoding.
|
|
168
|
+
* JavaScript's `<` and `>` compare UTF-16 code units, and the two disagree
|
|
169
|
+
* wherever an astral character meets one in U+E000-U+FFFF: an astral character
|
|
170
|
+
* is a surrogate pair starting at U+D800, so `'A\u{1F600}' < 'A!'` in
|
|
171
|
+
* JavaScript and the reverse on the server. Any listing that merges or bounds
|
|
172
|
+
* rows in memory and then resumes with a key condition has to use this order,
|
|
173
|
+
* or the boundary it draws is not the boundary the next query reads from, and
|
|
174
|
+
* a row is skipped or handed out twice.
|
|
175
|
+
*
|
|
176
|
+
* The comparison is written on the bytes rather than on code points. The two
|
|
177
|
+
* agree — UTF-8 was designed so that byte order is code-point order — but the
|
|
178
|
+
* bytes are what DynamoDB documents itself as comparing, so the code states the
|
|
179
|
+
* server's rule instead of a property that happens to coincide with it.
|
|
180
|
+
*
|
|
181
|
+
* Accepts: `left`, `right` — any two strings; well-formedness is not required,
|
|
182
|
+
* since an unpaired surrogate encodes to the replacement character's bytes and
|
|
183
|
+
* so still compares deterministically.
|
|
184
|
+
*
|
|
185
|
+
* Returns: a negative number when `left` sorts before `right`, a positive one
|
|
186
|
+
* when it sorts after, and `0` when the two encode to the same bytes.
|
|
187
|
+
*
|
|
188
|
+
* Throws: nothing.
|
|
189
|
+
*/
|
|
190
|
+
export declare function compareSortKeys(left: string, right: string): number;
|