@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
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ROOT_NAMESPACE = void 0;
|
|
4
|
+
exports.parseThreadId = parseThreadId;
|
|
5
|
+
exports.parseCheckpointNs = parseCheckpointNs;
|
|
6
|
+
exports.parseCheckpointId = parseCheckpointId;
|
|
7
|
+
exports.parseTaskId = parseTaskId;
|
|
8
|
+
exports.parseWriteChannel = parseWriteChannel;
|
|
9
|
+
exports.parseTaskPath = parseTaskPath;
|
|
10
|
+
exports.parseConfig = parseConfig;
|
|
11
|
+
exports.parseThreadConfig = parseThreadConfig;
|
|
12
|
+
exports.parsePutRequest = parsePutRequest;
|
|
13
|
+
exports.parsePutWritesRequest = parsePutWritesRequest;
|
|
14
|
+
exports.parseListScope = parseListScope;
|
|
15
|
+
exports.parseDeltaHistoryRequest = parseDeltaHistoryRequest;
|
|
16
|
+
const table_schema_js_1 = require("../../shared/dynamodb/table-schema.js");
|
|
17
|
+
const errors_js_1 = require("../../shared/errors/errors.js");
|
|
18
|
+
const collaborators_js_1 = require("../../shared/validation/collaborators.js");
|
|
19
|
+
const option_shape_js_1 = require("../../shared/validation/option-shape.js");
|
|
20
|
+
const primitives_js_1 = require("../../shared/validation/primitives.js");
|
|
21
|
+
const rows_js_1 = require("./rows.js");
|
|
22
|
+
function parseThreadId(value) {
|
|
23
|
+
return (0, primitives_js_1.parseIdentifier)(value, table_schema_js_1.KEY_SEPARATOR, 'thread_id', table_schema_js_1.MAX_PARTITION_ID_BYTES);
|
|
24
|
+
}
|
|
25
|
+
function parseCheckpointNs(value) {
|
|
26
|
+
return (0, primitives_js_1.parseKeySegment)(value, table_schema_js_1.KEY_SEPARATOR, 'checkpoint_ns', table_schema_js_1.MAX_CHECKPOINT_NS_BYTES);
|
|
27
|
+
}
|
|
28
|
+
function parseCheckpointId(value, field = 'checkpoint_id') {
|
|
29
|
+
return (0, primitives_js_1.parseIdentifier)(value, table_schema_js_1.KEY_SEPARATOR, field, table_schema_js_1.MAX_KEY_SEGMENT_BYTES);
|
|
30
|
+
}
|
|
31
|
+
function parseTaskId(value) {
|
|
32
|
+
return (0, primitives_js_1.parseIdentifier)(value, table_schema_js_1.KEY_SEPARATOR, 'taskId', table_schema_js_1.MAX_KEY_SEGMENT_BYTES);
|
|
33
|
+
}
|
|
34
|
+
function parseWriteChannel(value) {
|
|
35
|
+
return (0, primitives_js_1.parseIdentifier)(value, table_schema_js_1.KEY_SEPARATOR, 'channel', table_schema_js_1.MAX_WRITE_CHANNEL_BYTES);
|
|
36
|
+
}
|
|
37
|
+
function parseTaskPath(value) {
|
|
38
|
+
if (value === undefined)
|
|
39
|
+
return undefined;
|
|
40
|
+
if (typeof value !== 'string')
|
|
41
|
+
throw (0, errors_js_1.validationError)('taskPath must be a string', 'taskPath');
|
|
42
|
+
return value;
|
|
43
|
+
}
|
|
44
|
+
exports.ROOT_NAMESPACE = parseCheckpointNs('');
|
|
45
|
+
function isAbsentId(value) {
|
|
46
|
+
return value === undefined || value === null || value === '';
|
|
47
|
+
}
|
|
48
|
+
function assertConfigShape(config) {
|
|
49
|
+
(0, option_shape_js_1.assertObjectShape)(config, 'config');
|
|
50
|
+
if (config.configurable !== undefined)
|
|
51
|
+
(0, option_shape_js_1.assertObjectShape)(config.configurable, 'configurable');
|
|
52
|
+
(0, collaborators_js_1.assertSignalLike)(config.signal);
|
|
53
|
+
}
|
|
54
|
+
function configurableOf(config) {
|
|
55
|
+
assertConfigShape(config);
|
|
56
|
+
return (config.configurable ?? {});
|
|
57
|
+
}
|
|
58
|
+
function namespaceOf(configurable) {
|
|
59
|
+
if (configurable.checkpoint_ns === undefined)
|
|
60
|
+
return undefined;
|
|
61
|
+
return parseCheckpointNs(configurable.checkpoint_ns ?? '');
|
|
62
|
+
}
|
|
63
|
+
function resolveCheckpointId(configurable) {
|
|
64
|
+
if (!isAbsentId(configurable.checkpoint_id))
|
|
65
|
+
return parseCheckpointId(configurable.checkpoint_id);
|
|
66
|
+
if (!isAbsentId(configurable.thread_ts)) {
|
|
67
|
+
return parseCheckpointId(configurable.thread_ts, 'thread_ts');
|
|
68
|
+
}
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
function parseConfig(config) {
|
|
72
|
+
const configurable = configurableOf(config);
|
|
73
|
+
const threadId = configurable.thread_id === undefined ? undefined : parseThreadId(configurable.thread_id);
|
|
74
|
+
return {
|
|
75
|
+
threadId,
|
|
76
|
+
checkpointNs: namespaceOf(configurable),
|
|
77
|
+
checkpointId: resolveCheckpointId(configurable),
|
|
78
|
+
signal: config.signal,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
function parseThreadConfig(config) {
|
|
82
|
+
const configurable = configurableOf(config);
|
|
83
|
+
const threadId = parseThreadId(configurable.thread_id);
|
|
84
|
+
return {
|
|
85
|
+
address: {
|
|
86
|
+
threadId,
|
|
87
|
+
checkpointNs: namespaceOf(configurable) ?? exports.ROOT_NAMESPACE,
|
|
88
|
+
checkpointId: resolveCheckpointId(configurable),
|
|
89
|
+
},
|
|
90
|
+
signal: config.signal,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
function parsePutRequest(config, checkpoint, metadata) {
|
|
94
|
+
const { address, signal } = parseThreadConfig(config);
|
|
95
|
+
if (checkpoint === null || checkpoint === undefined) {
|
|
96
|
+
throw (0, errors_js_1.validationError)('checkpoint must be an object', 'checkpoint');
|
|
97
|
+
}
|
|
98
|
+
const checkpointId = parseCheckpointId(checkpoint.id);
|
|
99
|
+
return {
|
|
100
|
+
address: { threadId: address.threadId, checkpointNs: address.checkpointNs, checkpointId },
|
|
101
|
+
parentCheckpointId: address.checkpointId,
|
|
102
|
+
checkpoint,
|
|
103
|
+
metadata,
|
|
104
|
+
signal,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
function assertWriteEntries(writes) {
|
|
108
|
+
if (!Array.isArray(writes)) {
|
|
109
|
+
throw (0, errors_js_1.validationError)('writes must be an array', 'writes');
|
|
110
|
+
}
|
|
111
|
+
for (let index = 0; index < writes.length; index += 1) {
|
|
112
|
+
if (!Array.isArray(writes[index])) {
|
|
113
|
+
throw (0, errors_js_1.validationError)(`writes[${index}] must be a [channel, value] tuple`, 'writes');
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
function assertWriteKeyFits(address, taskId, channel) {
|
|
118
|
+
const bytes = (0, rows_js_1.writeSortKeyBytes)({
|
|
119
|
+
checkpointNs: address.checkpointNs,
|
|
120
|
+
checkpointId: address.checkpointId,
|
|
121
|
+
taskId,
|
|
122
|
+
channel,
|
|
123
|
+
});
|
|
124
|
+
if (bytes > table_schema_js_1.MAX_SORT_KEY_BYTES) {
|
|
125
|
+
throw (0, errors_js_1.validationError)(`checkpoint_ns, checkpoint_id, taskId and channel compose a ${bytes}-byte sort key; ` +
|
|
126
|
+
`DynamoDB caps sort keys at ${table_schema_js_1.MAX_SORT_KEY_BYTES} bytes`, 'sortKey');
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
function parsePutWritesRequest(config, writes, taskId, taskPath) {
|
|
130
|
+
const parsedTaskId = parseTaskId(taskId);
|
|
131
|
+
const parsedTaskPath = parseTaskPath(taskPath);
|
|
132
|
+
const { address, signal } = parseThreadConfig(config);
|
|
133
|
+
if (address.checkpointId === undefined) {
|
|
134
|
+
throw (0, errors_js_1.validationError)('checkpoint_id is required to store writes', 'checkpoint_id');
|
|
135
|
+
}
|
|
136
|
+
const target = {
|
|
137
|
+
threadId: address.threadId,
|
|
138
|
+
checkpointNs: address.checkpointNs,
|
|
139
|
+
checkpointId: address.checkpointId,
|
|
140
|
+
};
|
|
141
|
+
assertWriteEntries(writes);
|
|
142
|
+
const channels = writes.map(([channel]) => parseWriteChannel(channel));
|
|
143
|
+
for (const channel of channels)
|
|
144
|
+
assertWriteKeyFits(target, parsedTaskId, channel);
|
|
145
|
+
return {
|
|
146
|
+
address: target,
|
|
147
|
+
taskId: parsedTaskId,
|
|
148
|
+
taskPath: parsedTaskPath,
|
|
149
|
+
writes: writes.map(([, value], index) => [channels[index], value]),
|
|
150
|
+
signal,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
function beforeCheckpointId(before) {
|
|
154
|
+
if (before === undefined)
|
|
155
|
+
return undefined;
|
|
156
|
+
(0, option_shape_js_1.assertObjectShape)(before, 'before');
|
|
157
|
+
const checkpointId = before.configurable?.checkpoint_id;
|
|
158
|
+
if (isAbsentId(checkpointId))
|
|
159
|
+
return undefined;
|
|
160
|
+
return parseCheckpointId(checkpointId, 'before');
|
|
161
|
+
}
|
|
162
|
+
function parseListScope(config, options) {
|
|
163
|
+
const { threadId, checkpointNs, checkpointId, signal } = parseConfig(config);
|
|
164
|
+
if (options !== undefined) {
|
|
165
|
+
(0, option_shape_js_1.assertObjectShape)(options, 'options');
|
|
166
|
+
if (options.filter !== undefined)
|
|
167
|
+
(0, option_shape_js_1.assertObjectShape)(options.filter, 'filter');
|
|
168
|
+
}
|
|
169
|
+
const limit = options?.limit === undefined ? undefined : (0, primitives_js_1.parseLimit)(options.limit, 0);
|
|
170
|
+
return {
|
|
171
|
+
threadId,
|
|
172
|
+
checkpointNs,
|
|
173
|
+
checkpointId,
|
|
174
|
+
before: beforeCheckpointId(options?.before),
|
|
175
|
+
filter: options?.filter,
|
|
176
|
+
limit,
|
|
177
|
+
signal,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
function parseDeltaHistoryRequest(options) {
|
|
181
|
+
(0, option_shape_js_1.assertObjectShape)(options, 'options');
|
|
182
|
+
assertConfigShape(options.config);
|
|
183
|
+
return { config: options.config, channels: (0, primitives_js_1.parseStringArray)(options.channels, 'channels') };
|
|
184
|
+
}
|
|
@@ -10,11 +10,11 @@
|
|
|
10
10
|
* an upload is released only when a read, or the row a rejection returned,
|
|
11
11
|
* proves no live row names it — never on an outcome nothing confirmed.
|
|
12
12
|
*/
|
|
13
|
-
import { type PayloadDescriptor } from '../../shared/codec/codec';
|
|
14
|
-
import { type RowProbe } from '../../shared/dynamodb/idempotent-write';
|
|
15
|
-
import type { ThreadId } from './parse';
|
|
16
|
-
import { type CheckpointWriteRow } from './rows';
|
|
17
|
-
import type { CheckpointerContext } from './setup';
|
|
13
|
+
import { type PayloadDescriptor } from '../../shared/codec/codec.js';
|
|
14
|
+
import { type RowProbe } from '../../shared/dynamodb/idempotent-write.js';
|
|
15
|
+
import type { ThreadId } from './parse.js';
|
|
16
|
+
import { type CheckpointWriteRow } from './rows.js';
|
|
17
|
+
import type { CheckpointerContext } from './setup.js';
|
|
18
18
|
/** One call's rows, ready to commit. */
|
|
19
19
|
export interface PendingWriteBatch {
|
|
20
20
|
/** The caller's thread, which scopes every superseded object this commit may release. */
|
|
@@ -97,11 +97,15 @@ export interface SpecialWriteOutcome {
|
|
|
97
97
|
/** What a post-failure verification read established about the attempt. */
|
|
98
98
|
export interface VerifiedFailure {
|
|
99
99
|
outcome: SpecialWriteOutcome;
|
|
100
|
-
/**
|
|
100
|
+
/**
|
|
101
|
+
* Present only when the attempt is confirmed not to have landed: the row's
|
|
102
|
+
* state, for a compare-and-swap to re-pin to.
|
|
103
|
+
*/
|
|
101
104
|
observed?: SpecialRowState;
|
|
102
105
|
}
|
|
103
106
|
/**
|
|
104
|
-
* The probe that recognises
|
|
107
|
+
* The probe that recognises a write row's own write on its row — a special
|
|
108
|
+
* channel's row or a regular one, both of which carry a `writeGroup`.
|
|
105
109
|
*
|
|
106
110
|
* Accepts: `item` — the row this call tried to write, carrying its own
|
|
107
111
|
* `writeGroup`.
|
|
@@ -112,7 +116,7 @@ export interface VerifiedFailure {
|
|
|
112
116
|
*
|
|
113
117
|
* Throws: nothing.
|
|
114
118
|
*/
|
|
115
|
-
export declare function
|
|
119
|
+
export declare function writeRowProbe(item: CheckpointWriteRow): RowProbe;
|
|
116
120
|
/**
|
|
117
121
|
* Read a special row's current descriptor and the writeGroup guarding it.
|
|
118
122
|
*
|
|
@@ -134,13 +138,30 @@ export declare function readSpecialRow(context: CheckpointerContext, item: Check
|
|
|
134
138
|
* `rejectedRow`), so the strongly-consistent read is spent only for a failure
|
|
135
139
|
* that does not: a lost response, or a rejection whose row vanished since.
|
|
136
140
|
*
|
|
137
|
-
*
|
|
141
|
+
* Five answers are possible:
|
|
138
142
|
* - the row holds this item's own `writeGroup`: the write landed, and the
|
|
139
143
|
* descriptor this attempt pinned is the dead one.
|
|
140
|
-
* - the row
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
-
*
|
|
144
|
+
* - the row no longer satisfies this attempt's condition — it holds some other
|
|
145
|
+
* group than the one the attempt was pinned to, or it is absent while the
|
|
146
|
+
* attempt was pinned to a revision (`#rev = :rev`): the write is confirmed
|
|
147
|
+
* not to be what is live and can no longer apply, so this item's own upload
|
|
148
|
+
* is dead — its key ends in this call's own group, which no row names.
|
|
149
|
+
* `observed` is returned so a rejected compare-and-swap can re-pin and try
|
|
150
|
+
* again.
|
|
151
|
+
* - the row does not hold this item's group but still satisfies this attempt's
|
|
152
|
+
* condition — it holds exactly the state the attempt was pinned to; or the
|
|
153
|
+
* attempt was pinned to "no revision" and the row is absent, which that
|
|
154
|
+
* `attribute_not_exists` guard admits too; or this attempt was never pinned
|
|
155
|
+
* at all (the unconditional overwrite, which fits any row, a third writer's
|
|
156
|
+
* included) — and the failure may
|
|
157
|
+
* still land: any attempt of its budget got no answer (a cancel, a timeout,
|
|
158
|
+
* a dropped connection), or DynamoDB answered that an earlier attempt under
|
|
159
|
+
* this same token is still being processed, or with a server error (5xx).
|
|
160
|
+
* Nothing is confirmed either way, so this is `'unverified'` rather than
|
|
161
|
+
* `'not-landed'`, and the outcome reports a commit and keeps the upload.
|
|
162
|
+
* - the row still fits this attempt, but the failure was an answer that leaves
|
|
163
|
+
* nothing in flight (a refusal, a throttle, a spent budget of such answers):
|
|
164
|
+
* the write did not land, so this is `'not-landed'` and the upload is dead.
|
|
144
165
|
* - the read itself fails: nothing is confirmed, so the outcome still reports a
|
|
145
166
|
* commit and keeps the originating error. That leaks one S3 object at worst
|
|
146
167
|
* (reclaimed by `ensureS3LifecycleRule`) where the alternative strands a live
|
|
@@ -148,9 +169,12 @@ export declare function readSpecialRow(context: CheckpointerContext, item: Check
|
|
|
148
169
|
*
|
|
149
170
|
* Accepts: `attempted` — the state this attempt pinned, whose descriptor is the
|
|
150
171
|
* one superseded if the write did land. `error` — the failure being explained.
|
|
172
|
+
* `pinned` — false for the unconditional overwrite, whose attempt can land
|
|
173
|
+
* over any row.
|
|
151
174
|
*
|
|
152
|
-
* Returns: the outcome, and the row's observed state
|
|
153
|
-
*
|
|
175
|
+
* Returns: the outcome, and the row's observed state whenever the attempt is
|
|
176
|
+
* confirmed not to have landed, so a rejected compare-and-swap can re-pin and
|
|
177
|
+
* try again.
|
|
154
178
|
*
|
|
155
179
|
* Throws: nothing. It exists to turn a failure into a decision.
|
|
156
180
|
*
|
|
@@ -158,7 +182,7 @@ export declare function readSpecialRow(context: CheckpointerContext, item: Check
|
|
|
158
182
|
* the strongly-consistent read is spent only for a failure that does not — a
|
|
159
183
|
* lost response, or a rejection whose row vanished since.
|
|
160
184
|
*/
|
|
161
|
-
export declare function verifyAfterFailure(context: CheckpointerContext, item: CheckpointWriteRow, attempted: SpecialRowState, error: Error): Promise<VerifiedFailure>;
|
|
185
|
+
export declare function verifyAfterFailure(context: CheckpointerContext, item: CheckpointWriteRow, attempted: SpecialRowState, error: Error, pinned?: boolean): Promise<VerifiedFailure>;
|
|
162
186
|
/**
|
|
163
187
|
* Write special (negative-index) rows, then clean up the correct side of each.
|
|
164
188
|
*
|
|
@@ -190,15 +214,18 @@ export declare function verifyAfterFailure(context: CheckpointerContext, item: C
|
|
|
190
214
|
*
|
|
191
215
|
* Guarantees: a superseded payload is released only once the item that
|
|
192
216
|
* superseded it committed, and an item's own upload only once a read, or the
|
|
193
|
-
* row returned with its rejected write, shows the
|
|
194
|
-
*
|
|
217
|
+
* row returned with its rejected write, shows that the item's write is not what
|
|
218
|
+
* the row holds and can no longer land there: the row no longer satisfies the
|
|
219
|
+
* attempt's condition, or the failure left no attempt in flight (see
|
|
220
|
+
* {@link verifyAfterFailure}).
|
|
195
221
|
*/
|
|
196
222
|
export declare function writeSpecialRowsWithCleanup(context: CheckpointerContext, threadId: ThreadId, items: CheckpointWriteRow[], signal?: AbortSignal): Promise<Error | undefined>;
|
|
197
223
|
/**
|
|
198
224
|
* Outcome of {@link writeRegularRows}: never rejects. `deadUploads` holds
|
|
199
225
|
* exactly the items whose own S3 upload is confirmed unreferenced by this
|
|
200
|
-
* call's row — a verified non-commit,
|
|
201
|
-
* provably belongs to another call
|
|
226
|
+
* call's row — a verified non-commit, a guard rejection whose returned row
|
|
227
|
+
* provably belongs to another call, or a write the caller's signal came
|
|
228
|
+
* before, which was never sent at all. Everything else either committed, was
|
|
202
229
|
* turned away by a row this call may have written itself, or could not be
|
|
203
230
|
* verified; none of those may be cleaned up.
|
|
204
231
|
*
|
|
@@ -210,10 +237,21 @@ export interface RegularWriteOutcome {
|
|
|
210
237
|
error?: Error;
|
|
211
238
|
}
|
|
212
239
|
/**
|
|
213
|
-
*
|
|
214
|
-
*
|
|
215
|
-
*
|
|
216
|
-
*
|
|
240
|
+
* Regular pending writes one `putWrites` call keeps in flight. A `Send`
|
|
241
|
+
* fan-out can name a thousand of them, and the SDK's HTTP agent holds 50
|
|
242
|
+
* sockets by default: past that, a request waits for a socket, and the
|
|
243
|
+
* request timeout counts the wait, so a wide enough fan-out, larger values,
|
|
244
|
+
* or an injected client with a shorter request timeout can time out healthy
|
|
245
|
+
* writes that the retry layer then re-sends. Thirty-two in flight stays
|
|
246
|
+
* under the socket pool and still overlaps the round trips.
|
|
247
|
+
*/
|
|
248
|
+
export declare const REGULAR_WRITE_CONCURRENCY = 32;
|
|
249
|
+
/**
|
|
250
|
+
* Write regular rows with a first-write-wins guard. Every write fully settles,
|
|
251
|
+
* at most {@link REGULAR_WRITE_CONCURRENCY} at a time, before this resolves,
|
|
252
|
+
* and it never rejects; a genuine failure is reported via `error`, not thrown.
|
|
253
|
+
* The fan-out is one call per item whichever shape {@link commitWriteRow}
|
|
254
|
+
* gives that item's write.
|
|
217
255
|
*
|
|
218
256
|
* A failure is not proof of a non-commit: `withDynamoDBRetry` re-issues a put
|
|
219
257
|
* whose response was lost, and the re-issues can time out at the transport, so
|
|
@@ -227,7 +265,8 @@ export interface RegularWriteOutcome {
|
|
|
227
265
|
* `signal` — aborts the puts.
|
|
228
266
|
*
|
|
229
267
|
* Returns: which items are known not to have committed — whose own uploads are
|
|
230
|
-
* therefore dead — and the first genuine failure, if any
|
|
268
|
+
* therefore dead — and the first genuine failure, if any; a write the caller's
|
|
269
|
+
* signal came before is not sent, and its upload is dead.
|
|
231
270
|
*
|
|
232
271
|
* Throws: nothing. Every put settles before this resolves, because the caller
|
|
233
272
|
* runs it beside the special writes under `Promise.all` and its cleanup depends
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.REGULAR_WRITE_CONCURRENCY = void 0;
|
|
4
|
+
exports.commitPendingWrites = commitPendingWrites;
|
|
5
|
+
exports.writeSpecialRow = writeSpecialRow;
|
|
6
|
+
exports.writeRowProbe = writeRowProbe;
|
|
7
|
+
exports.readSpecialRow = readSpecialRow;
|
|
8
|
+
exports.verifyAfterFailure = verifyAfterFailure;
|
|
9
|
+
exports.writeSpecialRowsWithCleanup = writeSpecialRowsWithCleanup;
|
|
10
|
+
exports.writeRegularRows = writeRegularRows;
|
|
11
|
+
exports.reportGuardRejection = reportGuardRejection;
|
|
12
|
+
exports.rejectionProvesForeignRow = rejectionProvesForeignRow;
|
|
13
|
+
const codec_js_1 = require("../../shared/codec/codec.js");
|
|
14
|
+
const offloader_js_1 = require("../../shared/codec/s3/offloader.js");
|
|
15
|
+
const concurrency_js_1 = require("../../shared/concurrency.js");
|
|
16
|
+
const abort_js_1 = require("../../shared/dynamodb/abort.js");
|
|
17
|
+
const idempotent_write_js_1 = require("../../shared/dynamodb/idempotent-write.js");
|
|
18
|
+
const retry_js_1 = require("../../shared/dynamodb/retry.js");
|
|
19
|
+
const table_schema_js_1 = require("../../shared/dynamodb/table-schema.js");
|
|
20
|
+
const truncate_js_1 = require("../../shared/logging/truncate.js");
|
|
21
|
+
const rows_js_1 = require("./rows.js");
|
|
22
|
+
async function commitPendingWrites(context, batch) {
|
|
23
|
+
const special = batch.items.filter((item) => item.index < 0);
|
|
24
|
+
const regular = batch.items.filter((item) => item.index >= 0);
|
|
25
|
+
const [specialError, regularOutcome] = await Promise.all([
|
|
26
|
+
writeSpecialRowsWithCleanup(context, batch.threadId, special, batch.signal),
|
|
27
|
+
writeRegularRows(context, regular, batch.signal),
|
|
28
|
+
]);
|
|
29
|
+
await releaseDeadUploads(context, regularOutcome.deadUploads);
|
|
30
|
+
const firstError = specialError ?? regularOutcome.error;
|
|
31
|
+
if (firstError)
|
|
32
|
+
throw firstError;
|
|
33
|
+
}
|
|
34
|
+
async function releaseDeadUploads(context, dead) {
|
|
35
|
+
if (!context.offloader)
|
|
36
|
+
return;
|
|
37
|
+
await (0, offloader_js_1.cleanUpS3Orphans)(context.offloader, {
|
|
38
|
+
keys: (0, codec_js_1.collectS3Keys)(dead.map((item) => item.value)),
|
|
39
|
+
operation: 'putWrites',
|
|
40
|
+
logger: context.logger,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
async function commitSpecialRow(context, item, guard, signal) {
|
|
44
|
+
await (0, idempotent_write_js_1.commitRow)(context, item, item.value, { guard, signal });
|
|
45
|
+
}
|
|
46
|
+
async function attemptCasWrites(context, item, initial, signal) {
|
|
47
|
+
let observed = initial;
|
|
48
|
+
for (let attempt = 1; attempt <= idempotent_write_js_1.OVERWRITE_CAS_MAX_ATTEMPTS; attempt++) {
|
|
49
|
+
if (signal?.aborted) {
|
|
50
|
+
return { done: true, outcome: { committed: false, error: (0, abort_js_1.abortErrorFrom)(signal) } };
|
|
51
|
+
}
|
|
52
|
+
const attempted = observed;
|
|
53
|
+
try {
|
|
54
|
+
await commitSpecialRow(context, item, (0, idempotent_write_js_1.revisionGuard)(rows_js_1.WRITE_GROUP_ATTRIBUTE, attempted), signal);
|
|
55
|
+
return { done: true, outcome: { committed: true, superseded: attempted.value } };
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
const verified = await verifyAfterFailure(context, item, attempted, error);
|
|
59
|
+
if (!verified.observed || !(0, idempotent_write_js_1.isConditionalCheckFailed)(error)) {
|
|
60
|
+
return { done: true, outcome: verified.outcome };
|
|
61
|
+
}
|
|
62
|
+
observed = verified.observed;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return { done: false, observed };
|
|
66
|
+
}
|
|
67
|
+
async function overwriteUnconditionally(context, item, observed, signal) {
|
|
68
|
+
if (signal?.aborted)
|
|
69
|
+
return { committed: false, error: (0, abort_js_1.abortErrorFrom)(signal) };
|
|
70
|
+
try {
|
|
71
|
+
await commitSpecialRow(context, item, undefined, signal);
|
|
72
|
+
return { committed: true, superseded: observed.value };
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
return (await verifyAfterFailure(context, item, observed, error, false)).outcome;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
async function writeWithoutOffloader(context, item, signal) {
|
|
79
|
+
try {
|
|
80
|
+
await (0, retry_js_1.withDynamoDBRetry)((request) => context.client.put({ TableName: context.tableName, Item: item }, request), (0, retry_js_1.retryFor)(context, signal));
|
|
81
|
+
return { committed: true };
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
return { committed: false, error: error };
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
async function writeSpecialRow(context, item, signal) {
|
|
88
|
+
if (!context.offloader)
|
|
89
|
+
return writeWithoutOffloader(context, item, signal);
|
|
90
|
+
try {
|
|
91
|
+
const initial = await readSpecialRow(context, item);
|
|
92
|
+
const attempt = await attemptCasWrites(context, item, initial, signal);
|
|
93
|
+
if (attempt.done)
|
|
94
|
+
return attempt.outcome;
|
|
95
|
+
context.logger.warn('putWrites: special-write compare-and-swap exhausted; overwriting unconditionally, which ' +
|
|
96
|
+
'can orphan one S3 object under a concurrent call (reclaimed by ensureS3LifecycleRule)', { sortKey: item.SK, channel: item.channel, attempts: idempotent_write_js_1.OVERWRITE_CAS_MAX_ATTEMPTS });
|
|
97
|
+
return await overwriteUnconditionally(context, item, attempt.observed, signal);
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
return { committed: true, error: error };
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
function writeRowProbe(item) {
|
|
104
|
+
return {
|
|
105
|
+
key: (0, table_schema_js_1.rowKeyOf)(item),
|
|
106
|
+
kind: 'attribute',
|
|
107
|
+
attribute: rows_js_1.WRITE_GROUP_ATTRIBUTE,
|
|
108
|
+
expected: item.writeGroup,
|
|
109
|
+
also: ['value'],
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
function stateOf(row) {
|
|
113
|
+
if (!row)
|
|
114
|
+
return { exists: false };
|
|
115
|
+
return {
|
|
116
|
+
exists: true,
|
|
117
|
+
value: row.value,
|
|
118
|
+
revision: row[rows_js_1.WRITE_GROUP_ATTRIBUTE],
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
async function readSpecialRow(context, item) {
|
|
122
|
+
return stateOf(await (0, idempotent_write_js_1.readRow)(context, writeRowProbe(item)));
|
|
123
|
+
}
|
|
124
|
+
async function verifyAfterFailure(context, item, attempted, error, pinned = true) {
|
|
125
|
+
const probe = writeRowProbe(item);
|
|
126
|
+
const rejected = (0, idempotent_write_js_1.isConditionalCheckFailed)(error) ? (0, idempotent_write_js_1.rejectedRow)(error) : undefined;
|
|
127
|
+
const read = rejected
|
|
128
|
+
? { verdict: (0, idempotent_write_js_1.verdictFor)(probe, rejected), row: rejected }
|
|
129
|
+
: await (0, idempotent_write_js_1.verifyRow)(context, probe);
|
|
130
|
+
const verdict = rejected === undefined && (!pinned || stillPinned(attempted, read.row))
|
|
131
|
+
? (0, idempotent_write_js_1.settledVerdict)(read.verdict, error)
|
|
132
|
+
: read.verdict;
|
|
133
|
+
if (verdict === 'landed')
|
|
134
|
+
return { outcome: { committed: true, superseded: attempted.value } };
|
|
135
|
+
if (verdict === 'unverified')
|
|
136
|
+
return { outcome: { committed: true, error } };
|
|
137
|
+
return { outcome: { committed: false, error }, observed: stateOf(read.row) };
|
|
138
|
+
}
|
|
139
|
+
function stillPinned(attempted, row) {
|
|
140
|
+
const current = stateOf(row);
|
|
141
|
+
if (current.revision !== attempted.revision)
|
|
142
|
+
return false;
|
|
143
|
+
if (current.exists === attempted.exists)
|
|
144
|
+
return true;
|
|
145
|
+
return !current.exists && attempted.revision === undefined;
|
|
146
|
+
}
|
|
147
|
+
async function deleteDescriptors(context, descriptors, label, scope) {
|
|
148
|
+
if (!context.offloader)
|
|
149
|
+
return;
|
|
150
|
+
await (0, offloader_js_1.cleanUpS3Orphans)(context.offloader, {
|
|
151
|
+
keys: (0, codec_js_1.collectS3Keys)(descriptors.filter((ref) => Boolean(ref))),
|
|
152
|
+
operation: label,
|
|
153
|
+
logger: context.logger,
|
|
154
|
+
...(scope === undefined ? {} : { scope }),
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
async function writeSpecialRowsWithCleanup(context, threadId, items, signal) {
|
|
158
|
+
if (items.length === 0)
|
|
159
|
+
return undefined;
|
|
160
|
+
const outcomes = await Promise.all(items.map(async (item) => [
|
|
161
|
+
item,
|
|
162
|
+
await writeSpecialRow(context, item, signal),
|
|
163
|
+
]));
|
|
164
|
+
await deleteDescriptors(context, outcomes.filter(([, o]) => o.committed).map(([, o]) => o.superseded), 'putWrites.special.previous', [threadId]);
|
|
165
|
+
await deleteDescriptors(context, outcomes.filter(([, o]) => !o.committed).map(([item]) => item.value), 'putWrites.special.newUpload');
|
|
166
|
+
return outcomes.find(([, o]) => o.error)?.[1].error;
|
|
167
|
+
}
|
|
168
|
+
const FIRST_WRITE_WINS = {
|
|
169
|
+
ConditionExpression: `attribute_not_exists(${table_schema_js_1.PARTITION_KEY_ATTRIBUTE})`,
|
|
170
|
+
ReturnValuesOnConditionCheckFailure: 'ALL_OLD',
|
|
171
|
+
};
|
|
172
|
+
async function commitWriteRow(context, item, signal) {
|
|
173
|
+
await (0, idempotent_write_js_1.commitRow)(context, item, item.value, { guard: FIRST_WRITE_WINS, signal });
|
|
174
|
+
}
|
|
175
|
+
async function verifyFailure(context, item) {
|
|
176
|
+
if (!context.offloader)
|
|
177
|
+
return { verdict: 'not-landed' };
|
|
178
|
+
return (0, idempotent_write_js_1.verifyRow)(context, writeRowProbe(item));
|
|
179
|
+
}
|
|
180
|
+
exports.REGULAR_WRITE_CONCURRENCY = 32;
|
|
181
|
+
async function writeRegularRows(context, items, signal) {
|
|
182
|
+
const settled = await (0, concurrency_js_1.mapWithConcurrency)(items, exports.REGULAR_WRITE_CONCURRENCY, async (item) => {
|
|
183
|
+
if (signal?.aborted)
|
|
184
|
+
return { ok: false, reason: (0, abort_js_1.abortErrorFrom)(signal), sent: false };
|
|
185
|
+
try {
|
|
186
|
+
await commitWriteRow(context, item, signal);
|
|
187
|
+
return { ok: true };
|
|
188
|
+
}
|
|
189
|
+
catch (error) {
|
|
190
|
+
return { ok: false, reason: error, sent: true };
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
const outcome = { deadUploads: [] };
|
|
194
|
+
for (const [index, result] of settled.entries()) {
|
|
195
|
+
if (result.ok)
|
|
196
|
+
continue;
|
|
197
|
+
const item = items[index];
|
|
198
|
+
const { reason } = result;
|
|
199
|
+
if (!result.sent) {
|
|
200
|
+
outcome.deadUploads.push(item);
|
|
201
|
+
outcome.error = outcome.error ?? reason;
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
if ((0, idempotent_write_js_1.isConditionalCheckFailed)(reason)) {
|
|
205
|
+
reportGuardRejection(context, item, reason);
|
|
206
|
+
if (rejectionProvesForeignRow(item, reason))
|
|
207
|
+
outcome.deadUploads.push(item);
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
const { verdict, row } = await verifyFailure(context, item);
|
|
211
|
+
const settledNow = row === undefined ? (0, idempotent_write_js_1.settledVerdict)(verdict, reason) : verdict;
|
|
212
|
+
if (settledNow === 'landed')
|
|
213
|
+
continue;
|
|
214
|
+
if (settledNow === 'not-landed')
|
|
215
|
+
outcome.deadUploads.push(item);
|
|
216
|
+
outcome.error = outcome.error ?? reason;
|
|
217
|
+
}
|
|
218
|
+
return outcome;
|
|
219
|
+
}
|
|
220
|
+
function rejectedChannel(error) {
|
|
221
|
+
return (0, idempotent_write_js_1.rejectedRow)(error)?.channel;
|
|
222
|
+
}
|
|
223
|
+
function reportGuardRejection(context, item, error) {
|
|
224
|
+
const found = rejectedChannel(error);
|
|
225
|
+
if (found !== undefined && found !== item.channel) {
|
|
226
|
+
context.logger.warn('putWrites: write row held by an unexpected channel; write not persisted', {
|
|
227
|
+
sortKey: item.SK,
|
|
228
|
+
expected: item.channel,
|
|
229
|
+
found: (0, truncate_js_1.truncateForLog)(found),
|
|
230
|
+
});
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
context.logger.debug('putWrites: skipped a write already committed for this task and channel', {
|
|
234
|
+
sortKey: item.SK,
|
|
235
|
+
channel: item.channel,
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
function rejectionProvesForeignRow(item, error) {
|
|
239
|
+
const group = (0, idempotent_write_js_1.rejectedRow)(error)?.writeGroup;
|
|
240
|
+
return group !== undefined && group !== item.writeGroup;
|
|
241
|
+
}
|
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
* reads that takes, and in what order, is decided here.
|
|
10
10
|
*/
|
|
11
11
|
import { type Checkpoint, type CheckpointMetadata, type CheckpointPendingWrite, type CheckpointTuple } from '@langchain/langgraph-checkpoint';
|
|
12
|
-
import type { ThreadAddress } from './parse';
|
|
13
|
-
import { type CheckpointLocation, type CheckpointMetaRow, type CheckpointPayloadRow } from './rows';
|
|
14
|
-
import type { CheckpointerContext } from './setup';
|
|
12
|
+
import type { ThreadAddress } from './parse.js';
|
|
13
|
+
import { type CheckpointLocation, type CheckpointMetaRow, type CheckpointPayloadRow, type MetaReader } from './rows.js';
|
|
14
|
+
import type { CheckpointerContext } from './setup.js';
|
|
15
15
|
/** The thread and namespace a read was asked for. */
|
|
16
16
|
export interface ThreadLocation {
|
|
17
17
|
readonly threadId: string;
|
|
@@ -33,6 +33,8 @@ export interface ReadOptions {
|
|
|
33
33
|
*
|
|
34
34
|
* Accepts: `address` — parsed; its `checkpointId` names the row, and its
|
|
35
35
|
* absence asks for the newest in the namespace. `signal` — aborts the read.
|
|
36
|
+
* `reader` — the public method this read serves, named when a foreign row is
|
|
37
|
+
* reported; `getTuple` unless the caller says otherwise.
|
|
36
38
|
*
|
|
37
39
|
* Returns: the row, or undefined when there is none — including when every row
|
|
38
40
|
* in the namespace has expired, or when the only rows there belong to another
|
|
@@ -45,9 +47,10 @@ export interface ReadOptions {
|
|
|
45
47
|
* for, so a checkpoint past its ttl is absent to every reader however long
|
|
46
48
|
* DynamoDB's sweep lags. The newest-first read returns the first live row of
|
|
47
49
|
* ours and stops there, stepping over expired and foreign rows
|
|
48
|
-
* {@link LATEST_META_PAGE_SIZE} at a time
|
|
50
|
+
* {@link LATEST_META_PAGE_SIZE} at a time when the adapter has a `ttl`, and
|
|
51
|
+
* reading one row per page when it has none.
|
|
49
52
|
*/
|
|
50
|
-
export declare function fetchTargetMeta(context: CheckpointerContext, address: ThreadAddress, signal?: AbortSignal): Promise<CheckpointMetaRow | undefined>;
|
|
53
|
+
export declare function fetchTargetMeta(context: CheckpointerContext, address: ThreadAddress, signal?: AbortSignal, reader?: MetaReader): Promise<CheckpointMetaRow | undefined>;
|
|
51
54
|
/**
|
|
52
55
|
* The PAYLOAD row of one checkpoint.
|
|
53
56
|
*
|
|
@@ -55,8 +58,10 @@ export declare function fetchTargetMeta(context: CheckpointerContext, address: T
|
|
|
55
58
|
* true; `list` passes false and accepts replica lag, since a listing tolerates
|
|
56
59
|
* what a read-your-writes `getTuple` does not.
|
|
57
60
|
*
|
|
58
|
-
* Returns: the row, or undefined when it is not there — the
|
|
59
|
-
*
|
|
61
|
+
* Returns: the row, or undefined when it is not there — the two rows land in
|
|
62
|
+
* one transaction, so that is a thread being deleted row by row, or DynamoDB's
|
|
63
|
+
* expiry sweep reaching the PAYLOAD row before the META row — which the caller
|
|
64
|
+
* answers as "no checkpoint".
|
|
60
65
|
*
|
|
61
66
|
* Throws: `FORMAT_UNSUPPORTED` for a row a newer release wrote; whatever the
|
|
62
67
|
* read throws.
|
|
@@ -101,9 +106,9 @@ export interface AssembleOptions {
|
|
|
101
106
|
* `options.consistent` — true for `getTuple`, false for `list`.
|
|
102
107
|
*
|
|
103
108
|
* Returns: the tuple, with `parentConfig` set only when the row names a parent;
|
|
104
|
-
* `undefined` when the PAYLOAD row is absent —
|
|
105
|
-
* PAYLOAD
|
|
106
|
-
* checkpoint that does not exist.
|
|
109
|
+
* `undefined` when the PAYLOAD row is absent — a thread mid-delete, or an
|
|
110
|
+
* expiry sweep that reached the PAYLOAD row first — the same answer a caller
|
|
111
|
+
* gets for a checkpoint that does not exist.
|
|
107
112
|
*
|
|
108
113
|
* Throws: whatever the reads and decodes throw.
|
|
109
114
|
*/
|