@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.
Files changed (512) hide show
  1. package/README.md +1720 -154
  2. package/dist/backfill/backfill.d.ts +168 -0
  3. package/dist/backfill/backfill.js +393 -0
  4. package/dist/checkpointer/actions/delete-thread.d.ts +47 -6
  5. package/dist/checkpointer/actions/delete-thread.js +58 -21
  6. package/dist/checkpointer/actions/get-tuple.d.ts +29 -4
  7. package/dist/checkpointer/actions/get-tuple.js +44 -10
  8. package/dist/checkpointer/actions/list.d.ts +46 -4
  9. package/dist/checkpointer/actions/list.js +121 -66
  10. package/dist/checkpointer/actions/put-writes.d.ts +41 -9
  11. package/dist/checkpointer/actions/put-writes.js +62 -77
  12. package/dist/checkpointer/actions/put.d.ts +83 -4
  13. package/dist/checkpointer/actions/put.js +177 -25
  14. package/dist/checkpointer/internal/delta-history.d.ts +112 -0
  15. package/dist/checkpointer/internal/delta-history.js +252 -0
  16. package/dist/checkpointer/internal/listing.d.ts +149 -0
  17. package/dist/checkpointer/internal/listing.js +245 -0
  18. package/dist/checkpointer/internal/parse.d.ts +262 -0
  19. package/dist/checkpointer/internal/parse.js +372 -0
  20. package/dist/checkpointer/internal/pending-writes.d.ts +275 -0
  21. package/dist/checkpointer/internal/pending-writes.js +588 -0
  22. package/dist/checkpointer/internal/read.d.ts +130 -0
  23. package/dist/checkpointer/internal/read.js +264 -0
  24. package/dist/checkpointer/internal/rows.d.ts +571 -0
  25. package/dist/checkpointer/internal/rows.js +834 -0
  26. package/dist/checkpointer/internal/setup.d.ts +42 -19
  27. package/dist/checkpointer/internal/setup.js +65 -29
  28. package/dist/checkpointer/saver.d.ts +256 -16
  29. package/dist/checkpointer/saver.js +275 -29
  30. package/dist/checkpointer/types.d.ts +39 -39
  31. package/dist/checkpointer/types.js +10 -1
  32. package/dist/factory/factory.d.ts +134 -28
  33. package/dist/factory/factory.js +240 -21
  34. package/dist/factory/types.d.ts +76 -0
  35. package/dist/factory/types.js +10 -0
  36. package/dist/history/actions/add-messages.d.ts +31 -4
  37. package/dist/history/actions/add-messages.js +38 -58
  38. package/dist/history/actions/clear.d.ts +49 -6
  39. package/dist/history/actions/clear.js +66 -14
  40. package/dist/history/actions/get-messages.d.ts +54 -6
  41. package/dist/history/actions/get-messages.js +126 -43
  42. package/dist/history/actions/list-sessions.d.ts +52 -10
  43. package/dist/history/actions/list-sessions.js +139 -40
  44. package/dist/history/actions/reconcile-count.d.ts +42 -10
  45. package/dist/history/actions/reconcile-count.js +45 -45
  46. package/dist/history/chat-message-history.d.ts +220 -33
  47. package/dist/history/chat-message-history.js +240 -43
  48. package/dist/history/internal/append.d.ts +212 -0
  49. package/dist/history/internal/append.js +500 -0
  50. package/dist/history/internal/message-read.d.ts +84 -0
  51. package/dist/history/internal/message-read.js +204 -0
  52. package/dist/history/internal/parse.d.ts +153 -0
  53. package/dist/history/internal/parse.js +252 -0
  54. package/dist/history/internal/rows.d.ts +195 -0
  55. package/dist/history/internal/rows.js +250 -0
  56. package/dist/history/internal/session.d.ts +331 -0
  57. package/dist/history/internal/session.js +628 -0
  58. package/dist/history/internal/setup.d.ts +52 -17
  59. package/dist/history/internal/setup.js +92 -21
  60. package/dist/history/session-adapter.d.ts +102 -7
  61. package/dist/history/session-adapter.js +103 -9
  62. package/dist/history/types.d.ts +80 -29
  63. package/dist/history/types.js +10 -1
  64. package/dist/index.d.ts +42 -11
  65. package/dist/index.js +33 -12
  66. package/dist/shared/adapter.d.ts +135 -0
  67. package/dist/shared/adapter.js +143 -0
  68. package/dist/shared/clock.d.ts +51 -2
  69. package/dist/shared/clock.js +57 -2
  70. package/dist/shared/codec/codec.d.ts +288 -13
  71. package/dist/shared/codec/codec.js +416 -19
  72. package/dist/shared/codec/compression.d.ts +43 -7
  73. package/dist/shared/codec/compression.js +53 -13
  74. package/dist/shared/codec/json-serde.d.ts +76 -4
  75. package/dist/shared/codec/json-serde.js +181 -8
  76. package/dist/shared/codec/s3/client-types.d.ts +53 -0
  77. package/dist/shared/codec/s3/client-types.js +26 -0
  78. package/dist/shared/codec/s3/client.d.ts +43 -10
  79. package/dist/shared/codec/s3/client.js +82 -9
  80. package/dist/shared/codec/s3/config.d.ts +242 -11
  81. package/dist/shared/codec/s3/config.js +293 -11
  82. package/dist/shared/codec/s3/lifecycle.d.ts +164 -6
  83. package/dist/shared/codec/s3/lifecycle.js +335 -27
  84. package/dist/shared/codec/s3/offloader.d.ts +393 -18
  85. package/dist/shared/codec/s3/offloader.js +595 -37
  86. package/dist/shared/concurrency.d.ts +43 -0
  87. package/dist/shared/concurrency.js +78 -0
  88. package/dist/shared/dynamodb/abort.d.ts +47 -0
  89. package/dist/shared/dynamodb/abort.js +59 -0
  90. package/dist/shared/dynamodb/batch-write.d.ts +77 -14
  91. package/dist/shared/dynamodb/batch-write.js +146 -27
  92. package/dist/shared/dynamodb/cancellation.d.ts +121 -4
  93. package/dist/shared/dynamodb/cancellation.js +147 -3
  94. package/dist/shared/dynamodb/client.d.ts +162 -8
  95. package/dist/shared/dynamodb/client.js +153 -5
  96. package/dist/shared/dynamodb/idempotent-write.d.ts +551 -0
  97. package/dist/shared/dynamodb/idempotent-write.js +593 -0
  98. package/dist/shared/dynamodb/paginate.d.ts +105 -9
  99. package/dist/shared/dynamodb/paginate.js +175 -7
  100. package/dist/shared/dynamodb/partition-delete.d.ts +185 -14
  101. package/dist/shared/dynamodb/partition-delete.js +314 -44
  102. package/dist/shared/dynamodb/recency-index.d.ts +231 -0
  103. package/dist/shared/dynamodb/recency-index.js +377 -0
  104. package/dist/shared/dynamodb/retry.d.ts +276 -8
  105. package/dist/shared/dynamodb/retry.js +433 -23
  106. package/dist/shared/dynamodb/table-schema.d.ts +190 -0
  107. package/dist/shared/dynamodb/table-schema.js +209 -0
  108. package/dist/shared/errors/base-error.d.ts +184 -10
  109. package/dist/shared/errors/base-error.js +160 -14
  110. package/dist/shared/errors/boundary.d.ts +71 -0
  111. package/dist/shared/errors/boundary.js +143 -0
  112. package/dist/shared/errors/classify.d.ts +97 -0
  113. package/dist/shared/errors/classify.js +257 -0
  114. package/dist/shared/errors/error-code.d.ts +77 -2
  115. package/dist/shared/errors/error-code.js +83 -1
  116. package/dist/shared/errors/errors.d.ts +158 -59
  117. package/dist/shared/errors/errors.js +219 -92
  118. package/dist/shared/logging/logger.d.ts +69 -3
  119. package/dist/shared/logging/logger.js +97 -3
  120. package/dist/shared/logging/redaction.d.ts +92 -8
  121. package/dist/shared/logging/redaction.js +273 -17
  122. package/dist/shared/logging/secret-patterns.d.ts +149 -19
  123. package/dist/shared/logging/secret-patterns.js +188 -27
  124. package/dist/shared/logging/truncate.d.ts +197 -0
  125. package/dist/shared/logging/truncate.js +231 -0
  126. package/dist/shared/options.d.ts +59 -7
  127. package/dist/shared/options.js +9 -1
  128. package/dist/shared/ulid.d.ts +77 -7
  129. package/dist/shared/ulid.js +103 -8
  130. package/dist/shared/validation/collaborators.d.ts +141 -0
  131. package/dist/shared/validation/collaborators.js +188 -0
  132. package/dist/shared/validation/option-shape.d.ts +89 -0
  133. package/dist/shared/validation/option-shape.js +113 -0
  134. package/dist/shared/validation/options.d.ts +145 -0
  135. package/dist/shared/validation/options.js +328 -0
  136. package/dist/shared/validation/primitives.d.ts +288 -21
  137. package/dist/shared/validation/primitives.js +353 -50
  138. package/dist/shared/validation/ttl.d.ts +66 -10
  139. package/dist/shared/validation/ttl.js +113 -15
  140. package/dist/store/actions/list-namespaces.d.ts +76 -6
  141. package/dist/store/actions/list-namespaces.js +166 -24
  142. package/dist/store/actions/put.d.ts +33 -8
  143. package/dist/store/actions/put.js +53 -60
  144. package/dist/store/actions/reconcile-vector-index.d.ts +31 -10
  145. package/dist/store/actions/reconcile-vector-index.js +34 -15
  146. package/dist/store/actions/search.d.ts +34 -6
  147. package/dist/store/actions/search.js +56 -51
  148. package/dist/store/internal/batch-plan.d.ts +26 -0
  149. package/dist/store/internal/batch-plan.js +109 -0
  150. package/dist/store/internal/filter.d.ts +36 -3
  151. package/dist/store/internal/filter.js +66 -15
  152. package/dist/store/internal/get-item.d.ts +45 -0
  153. package/dist/store/internal/get-item.js +115 -0
  154. package/dist/store/internal/item-write.d.ts +230 -0
  155. package/dist/store/internal/item-write.js +463 -0
  156. package/dist/store/internal/parse.d.ts +225 -0
  157. package/dist/store/internal/parse.js +350 -0
  158. package/dist/store/internal/rows.d.ts +355 -0
  159. package/dist/store/internal/rows.js +447 -0
  160. package/dist/store/internal/semantic-search.d.ts +161 -6
  161. package/dist/store/internal/semantic-search.js +360 -18
  162. package/dist/store/internal/setup.d.ts +77 -20
  163. package/dist/store/internal/setup.js +178 -47
  164. package/dist/store/internal/table-search.d.ts +100 -0
  165. package/dist/store/internal/table-search.js +213 -0
  166. package/dist/store/internal/vector-index.d.ts +247 -0
  167. package/dist/store/internal/vector-index.js +546 -0
  168. package/dist/store/store.d.ts +270 -17
  169. package/dist/store/store.js +329 -38
  170. package/dist/store/types.d.ts +76 -26
  171. package/dist/store/types.js +13 -1
  172. package/dist/store/vector-backend.d.ts +64 -4
  173. package/dist/store/vector-backend.js +15 -1
  174. package/package.json +58 -36
  175. package/dist/checkpointer/actions/delete-thread.d.ts.map +0 -1
  176. package/dist/checkpointer/actions/delete-thread.js.map +0 -1
  177. package/dist/checkpointer/actions/get-tuple.d.ts.map +0 -1
  178. package/dist/checkpointer/actions/get-tuple.js.map +0 -1
  179. package/dist/checkpointer/actions/list.d.ts.map +0 -1
  180. package/dist/checkpointer/actions/list.js.map +0 -1
  181. package/dist/checkpointer/actions/put-writes.d.ts.map +0 -1
  182. package/dist/checkpointer/actions/put-writes.js.map +0 -1
  183. package/dist/checkpointer/actions/put.d.ts.map +0 -1
  184. package/dist/checkpointer/actions/put.js.map +0 -1
  185. package/dist/checkpointer/internal/assemble.d.ts +0 -10
  186. package/dist/checkpointer/internal/assemble.d.ts.map +0 -1
  187. package/dist/checkpointer/internal/assemble.js +0 -37
  188. package/dist/checkpointer/internal/assemble.js.map +0 -1
  189. package/dist/checkpointer/internal/configurable.d.ts +0 -13
  190. package/dist/checkpointer/internal/configurable.d.ts.map +0 -1
  191. package/dist/checkpointer/internal/configurable.js +0 -23
  192. package/dist/checkpointer/internal/configurable.js.map +0 -1
  193. package/dist/checkpointer/internal/fetch.d.ts +0 -10
  194. package/dist/checkpointer/internal/fetch.d.ts.map +0 -1
  195. package/dist/checkpointer/internal/fetch.js +0 -46
  196. package/dist/checkpointer/internal/fetch.js.map +0 -1
  197. package/dist/checkpointer/internal/filter-match.d.ts +0 -12
  198. package/dist/checkpointer/internal/filter-match.d.ts.map +0 -1
  199. package/dist/checkpointer/internal/filter-match.js +0 -14
  200. package/dist/checkpointer/internal/filter-match.js.map +0 -1
  201. package/dist/checkpointer/internal/item-reader.d.ts +0 -55
  202. package/dist/checkpointer/internal/item-reader.d.ts.map +0 -1
  203. package/dist/checkpointer/internal/item-reader.js +0 -88
  204. package/dist/checkpointer/internal/item-reader.js.map +0 -1
  205. package/dist/checkpointer/internal/item-writer.d.ts +0 -26
  206. package/dist/checkpointer/internal/item-writer.d.ts.map +0 -1
  207. package/dist/checkpointer/internal/item-writer.js +0 -92
  208. package/dist/checkpointer/internal/item-writer.js.map +0 -1
  209. package/dist/checkpointer/internal/keys.d.ts +0 -31
  210. package/dist/checkpointer/internal/keys.d.ts.map +0 -1
  211. package/dist/checkpointer/internal/keys.js +0 -87
  212. package/dist/checkpointer/internal/keys.js.map +0 -1
  213. package/dist/checkpointer/internal/query.d.ts +0 -20
  214. package/dist/checkpointer/internal/query.d.ts.map +0 -1
  215. package/dist/checkpointer/internal/query.js +0 -36
  216. package/dist/checkpointer/internal/query.js.map +0 -1
  217. package/dist/checkpointer/internal/setup.d.ts.map +0 -1
  218. package/dist/checkpointer/internal/setup.js.map +0 -1
  219. package/dist/checkpointer/internal/special-write-cas.d.ts +0 -30
  220. package/dist/checkpointer/internal/special-write-cas.d.ts.map +0 -1
  221. package/dist/checkpointer/internal/special-write-cas.js +0 -104
  222. package/dist/checkpointer/internal/special-write-cas.js.map +0 -1
  223. package/dist/checkpointer/internal/special-write-cleanup.d.ts +0 -24
  224. package/dist/checkpointer/internal/special-write-cleanup.d.ts.map +0 -1
  225. package/dist/checkpointer/internal/special-write-cleanup.js +0 -47
  226. package/dist/checkpointer/internal/special-write-cleanup.js.map +0 -1
  227. package/dist/checkpointer/internal/special-write-verify.d.ts +0 -54
  228. package/dist/checkpointer/internal/special-write-verify.d.ts.map +0 -1
  229. package/dist/checkpointer/internal/special-write-verify.js +0 -65
  230. package/dist/checkpointer/internal/special-write-verify.js.map +0 -1
  231. package/dist/checkpointer/internal/validation.d.ts +0 -13
  232. package/dist/checkpointer/internal/validation.d.ts.map +0 -1
  233. package/dist/checkpointer/internal/validation.js +0 -30
  234. package/dist/checkpointer/internal/validation.js.map +0 -1
  235. package/dist/checkpointer/internal/write-guard.d.ts +0 -13
  236. package/dist/checkpointer/internal/write-guard.d.ts.map +0 -1
  237. package/dist/checkpointer/internal/write-guard.js +0 -39
  238. package/dist/checkpointer/internal/write-guard.js.map +0 -1
  239. package/dist/checkpointer/internal/write-index.d.ts +0 -37
  240. package/dist/checkpointer/internal/write-index.d.ts.map +0 -1
  241. package/dist/checkpointer/internal/write-index.js +0 -42
  242. package/dist/checkpointer/internal/write-index.js.map +0 -1
  243. package/dist/checkpointer/saver.d.ts.map +0 -1
  244. package/dist/checkpointer/saver.js.map +0 -1
  245. package/dist/checkpointer/types.d.ts.map +0 -1
  246. package/dist/checkpointer/types.js.map +0 -1
  247. package/dist/factory/factory.d.ts.map +0 -1
  248. package/dist/factory/factory.js.map +0 -1
  249. package/dist/history/actions/add-messages.d.ts.map +0 -1
  250. package/dist/history/actions/add-messages.js.map +0 -1
  251. package/dist/history/actions/clear.d.ts.map +0 -1
  252. package/dist/history/actions/clear.js.map +0 -1
  253. package/dist/history/actions/get-messages.d.ts.map +0 -1
  254. package/dist/history/actions/get-messages.js.map +0 -1
  255. package/dist/history/actions/list-sessions.d.ts.map +0 -1
  256. package/dist/history/actions/list-sessions.js.map +0 -1
  257. package/dist/history/actions/reconcile-count.d.ts.map +0 -1
  258. package/dist/history/actions/reconcile-count.js.map +0 -1
  259. package/dist/history/chat-message-history.d.ts.map +0 -1
  260. package/dist/history/chat-message-history.js.map +0 -1
  261. package/dist/history/internal/append-saga.d.ts +0 -20
  262. package/dist/history/internal/append-saga.d.ts.map +0 -1
  263. package/dist/history/internal/append-saga.js +0 -35
  264. package/dist/history/internal/append-saga.js.map +0 -1
  265. package/dist/history/internal/compensation.d.ts +0 -21
  266. package/dist/history/internal/compensation.d.ts.map +0 -1
  267. package/dist/history/internal/compensation.js +0 -84
  268. package/dist/history/internal/compensation.js.map +0 -1
  269. package/dist/history/internal/item-mapper.d.ts +0 -12
  270. package/dist/history/internal/item-mapper.d.ts.map +0 -1
  271. package/dist/history/internal/item-mapper.js +0 -33
  272. package/dist/history/internal/item-mapper.js.map +0 -1
  273. package/dist/history/internal/keys.d.ts +0 -17
  274. package/dist/history/internal/keys.d.ts.map +0 -1
  275. package/dist/history/internal/keys.js +0 -49
  276. package/dist/history/internal/keys.js.map +0 -1
  277. package/dist/history/internal/message-chunker.d.ts +0 -14
  278. package/dist/history/internal/message-chunker.d.ts.map +0 -1
  279. package/dist/history/internal/message-chunker.js +0 -68
  280. package/dist/history/internal/message-chunker.js.map +0 -1
  281. package/dist/history/internal/message-transaction.d.ts +0 -26
  282. package/dist/history/internal/message-transaction.d.ts.map +0 -1
  283. package/dist/history/internal/message-transaction.js +0 -60
  284. package/dist/history/internal/message-transaction.js.map +0 -1
  285. package/dist/history/internal/query.d.ts +0 -10
  286. package/dist/history/internal/query.d.ts.map +0 -1
  287. package/dist/history/internal/query.js +0 -31
  288. package/dist/history/internal/query.js.map +0 -1
  289. package/dist/history/internal/session-count.d.ts +0 -41
  290. package/dist/history/internal/session-count.d.ts.map +0 -1
  291. package/dist/history/internal/session-count.js +0 -109
  292. package/dist/history/internal/session-count.js.map +0 -1
  293. package/dist/history/internal/session-title.d.ts +0 -20
  294. package/dist/history/internal/session-title.d.ts.map +0 -1
  295. package/dist/history/internal/session-title.js +0 -44
  296. package/dist/history/internal/session-title.js.map +0 -1
  297. package/dist/history/internal/session-update.d.ts +0 -28
  298. package/dist/history/internal/session-update.d.ts.map +0 -1
  299. package/dist/history/internal/session-update.js +0 -70
  300. package/dist/history/internal/session-update.js.map +0 -1
  301. package/dist/history/internal/setup.d.ts.map +0 -1
  302. package/dist/history/internal/setup.js.map +0 -1
  303. package/dist/history/internal/title-generator.d.ts +0 -13
  304. package/dist/history/internal/title-generator.d.ts.map +0 -1
  305. package/dist/history/internal/title-generator.js +0 -25
  306. package/dist/history/internal/title-generator.js.map +0 -1
  307. package/dist/history/internal/ttl-anchor.d.ts +0 -25
  308. package/dist/history/internal/ttl-anchor.d.ts.map +0 -1
  309. package/dist/history/internal/ttl-anchor.js +0 -38
  310. package/dist/history/internal/ttl-anchor.js.map +0 -1
  311. package/dist/history/internal/validation.d.ts +0 -9
  312. package/dist/history/internal/validation.d.ts.map +0 -1
  313. package/dist/history/internal/validation.js +0 -16
  314. package/dist/history/internal/validation.js.map +0 -1
  315. package/dist/history/session-adapter.d.ts.map +0 -1
  316. package/dist/history/session-adapter.js.map +0 -1
  317. package/dist/history/types.d.ts.map +0 -1
  318. package/dist/history/types.js.map +0 -1
  319. package/dist/index.d.ts.map +0 -1
  320. package/dist/index.js.map +0 -1
  321. package/dist/shared/clock.d.ts.map +0 -1
  322. package/dist/shared/clock.js.map +0 -1
  323. package/dist/shared/codec/codec.d.ts.map +0 -1
  324. package/dist/shared/codec/codec.js.map +0 -1
  325. package/dist/shared/codec/compression.d.ts.map +0 -1
  326. package/dist/shared/codec/compression.js.map +0 -1
  327. package/dist/shared/codec/descriptor-keys.d.ts +0 -4
  328. package/dist/shared/codec/descriptor-keys.d.ts.map +0 -1
  329. package/dist/shared/codec/descriptor-keys.js +0 -14
  330. package/dist/shared/codec/descriptor-keys.js.map +0 -1
  331. package/dist/shared/codec/json-serde.d.ts.map +0 -1
  332. package/dist/shared/codec/json-serde.js.map +0 -1
  333. package/dist/shared/codec/s3/client.d.ts.map +0 -1
  334. package/dist/shared/codec/s3/client.js.map +0 -1
  335. package/dist/shared/codec/s3/config.d.ts.map +0 -1
  336. package/dist/shared/codec/s3/config.js.map +0 -1
  337. package/dist/shared/codec/s3/delete.d.ts +0 -8
  338. package/dist/shared/codec/s3/delete.d.ts.map +0 -1
  339. package/dist/shared/codec/s3/delete.js +0 -29
  340. package/dist/shared/codec/s3/delete.js.map +0 -1
  341. package/dist/shared/codec/s3/lifecycle.d.ts.map +0 -1
  342. package/dist/shared/codec/s3/lifecycle.js.map +0 -1
  343. package/dist/shared/codec/s3/offloader.d.ts.map +0 -1
  344. package/dist/shared/codec/s3/offloader.js.map +0 -1
  345. package/dist/shared/codec/s3/orphans.d.ts +0 -18
  346. package/dist/shared/codec/s3/orphans.d.ts.map +0 -1
  347. package/dist/shared/codec/s3/orphans.js +0 -58
  348. package/dist/shared/codec/s3/orphans.js.map +0 -1
  349. package/dist/shared/codec/s3/read-write.d.ts +0 -14
  350. package/dist/shared/codec/s3/read-write.d.ts.map +0 -1
  351. package/dist/shared/codec/s3/read-write.js +0 -43
  352. package/dist/shared/codec/s3/read-write.js.map +0 -1
  353. package/dist/shared/codec/s3/retry.d.ts +0 -5
  354. package/dist/shared/codec/s3/retry.d.ts.map +0 -1
  355. package/dist/shared/codec/s3/retry.js +0 -25
  356. package/dist/shared/codec/s3/retry.js.map +0 -1
  357. package/dist/shared/constants.d.ts +0 -64
  358. package/dist/shared/constants.d.ts.map +0 -1
  359. package/dist/shared/constants.js +0 -67
  360. package/dist/shared/constants.js.map +0 -1
  361. package/dist/shared/dynamodb/backoff.d.ts +0 -15
  362. package/dist/shared/dynamodb/backoff.d.ts.map +0 -1
  363. package/dist/shared/dynamodb/backoff.js +0 -48
  364. package/dist/shared/dynamodb/backoff.js.map +0 -1
  365. package/dist/shared/dynamodb/batch-write.d.ts.map +0 -1
  366. package/dist/shared/dynamodb/batch-write.js.map +0 -1
  367. package/dist/shared/dynamodb/cancellation.d.ts.map +0 -1
  368. package/dist/shared/dynamodb/cancellation.js.map +0 -1
  369. package/dist/shared/dynamodb/client.d.ts.map +0 -1
  370. package/dist/shared/dynamodb/client.js.map +0 -1
  371. package/dist/shared/dynamodb/conditional-put.d.ts +0 -51
  372. package/dist/shared/dynamodb/conditional-put.d.ts.map +0 -1
  373. package/dist/shared/dynamodb/conditional-put.js +0 -59
  374. package/dist/shared/dynamodb/conditional-put.js.map +0 -1
  375. package/dist/shared/dynamodb/drain-unprocessed.d.ts +0 -19
  376. package/dist/shared/dynamodb/drain-unprocessed.d.ts.map +0 -1
  377. package/dist/shared/dynamodb/drain-unprocessed.js +0 -44
  378. package/dist/shared/dynamodb/drain-unprocessed.js.map +0 -1
  379. package/dist/shared/dynamodb/paginate-core.d.ts +0 -22
  380. package/dist/shared/dynamodb/paginate-core.d.ts.map +0 -1
  381. package/dist/shared/dynamodb/paginate-core.js +0 -52
  382. package/dist/shared/dynamodb/paginate-core.js.map +0 -1
  383. package/dist/shared/dynamodb/paginate.d.ts.map +0 -1
  384. package/dist/shared/dynamodb/paginate.js.map +0 -1
  385. package/dist/shared/dynamodb/partition-delete.d.ts.map +0 -1
  386. package/dist/shared/dynamodb/partition-delete.js.map +0 -1
  387. package/dist/shared/dynamodb/retry-classifier.d.ts +0 -9
  388. package/dist/shared/dynamodb/retry-classifier.d.ts.map +0 -1
  389. package/dist/shared/dynamodb/retry-classifier.js +0 -87
  390. package/dist/shared/dynamodb/retry-classifier.js.map +0 -1
  391. package/dist/shared/dynamodb/retry.d.ts.map +0 -1
  392. package/dist/shared/dynamodb/retry.js.map +0 -1
  393. package/dist/shared/dynamodb/scan.d.ts +0 -15
  394. package/dist/shared/dynamodb/scan.d.ts.map +0 -1
  395. package/dist/shared/dynamodb/scan.js +0 -20
  396. package/dist/shared/dynamodb/scan.js.map +0 -1
  397. package/dist/shared/dynamodb/types.d.ts +0 -24
  398. package/dist/shared/dynamodb/types.d.ts.map +0 -1
  399. package/dist/shared/dynamodb/types.js +0 -3
  400. package/dist/shared/dynamodb/types.js.map +0 -1
  401. package/dist/shared/errors/base-error.d.ts.map +0 -1
  402. package/dist/shared/errors/base-error.js.map +0 -1
  403. package/dist/shared/errors/error-code.d.ts.map +0 -1
  404. package/dist/shared/errors/error-code.js.map +0 -1
  405. package/dist/shared/errors/errors.d.ts.map +0 -1
  406. package/dist/shared/errors/errors.js.map +0 -1
  407. package/dist/shared/errors/wrap-error.d.ts +0 -16
  408. package/dist/shared/errors/wrap-error.d.ts.map +0 -1
  409. package/dist/shared/errors/wrap-error.js +0 -30
  410. package/dist/shared/errors/wrap-error.js.map +0 -1
  411. package/dist/shared/logging/logger.d.ts.map +0 -1
  412. package/dist/shared/logging/logger.js.map +0 -1
  413. package/dist/shared/logging/redaction-walk.d.ts +0 -23
  414. package/dist/shared/logging/redaction-walk.d.ts.map +0 -1
  415. package/dist/shared/logging/redaction-walk.js +0 -92
  416. package/dist/shared/logging/redaction-walk.js.map +0 -1
  417. package/dist/shared/logging/redaction.d.ts.map +0 -1
  418. package/dist/shared/logging/redaction.js.map +0 -1
  419. package/dist/shared/logging/secret-patterns.d.ts.map +0 -1
  420. package/dist/shared/logging/secret-patterns.js.map +0 -1
  421. package/dist/shared/options.d.ts.map +0 -1
  422. package/dist/shared/options.js.map +0 -1
  423. package/dist/shared/ulid.d.ts.map +0 -1
  424. package/dist/shared/ulid.js.map +0 -1
  425. package/dist/shared/validation/primitives.d.ts.map +0 -1
  426. package/dist/shared/validation/primitives.js.map +0 -1
  427. package/dist/shared/validation/ttl.d.ts.map +0 -1
  428. package/dist/shared/validation/ttl.js.map +0 -1
  429. package/dist/store/actions/get.d.ts +0 -5
  430. package/dist/store/actions/get.d.ts.map +0 -1
  431. package/dist/store/actions/get.js +0 -35
  432. package/dist/store/actions/get.js.map +0 -1
  433. package/dist/store/actions/list-namespaces.d.ts.map +0 -1
  434. package/dist/store/actions/list-namespaces.js.map +0 -1
  435. package/dist/store/actions/put.d.ts.map +0 -1
  436. package/dist/store/actions/put.js.map +0 -1
  437. package/dist/store/actions/reconcile-vector-index.d.ts.map +0 -1
  438. package/dist/store/actions/reconcile-vector-index.js.map +0 -1
  439. package/dist/store/actions/search.d.ts.map +0 -1
  440. package/dist/store/actions/search.js.map +0 -1
  441. package/dist/store/internal/backend-search.d.ts +0 -5
  442. package/dist/store/internal/backend-search.d.ts.map +0 -1
  443. package/dist/store/internal/backend-search.js +0 -68
  444. package/dist/store/internal/backend-search.js.map +0 -1
  445. package/dist/store/internal/filter.d.ts.map +0 -1
  446. package/dist/store/internal/filter.js.map +0 -1
  447. package/dist/store/internal/index-reconcile.d.ts +0 -22
  448. package/dist/store/internal/index-reconcile.d.ts.map +0 -1
  449. package/dist/store/internal/index-reconcile.js +0 -105
  450. package/dist/store/internal/index-reconcile.js.map +0 -1
  451. package/dist/store/internal/index-sync.d.ts +0 -11
  452. package/dist/store/internal/index-sync.d.ts.map +0 -1
  453. package/dist/store/internal/index-sync.js +0 -26
  454. package/dist/store/internal/index-sync.js.map +0 -1
  455. package/dist/store/internal/item-mapper.d.ts +0 -25
  456. package/dist/store/internal/item-mapper.d.ts.map +0 -1
  457. package/dist/store/internal/item-mapper.js +0 -53
  458. package/dist/store/internal/item-mapper.js.map +0 -1
  459. package/dist/store/internal/keys.d.ts +0 -18
  460. package/dist/store/internal/keys.d.ts.map +0 -1
  461. package/dist/store/internal/keys.js +0 -42
  462. package/dist/store/internal/keys.js.map +0 -1
  463. package/dist/store/internal/namespace-match.d.ts +0 -12
  464. package/dist/store/internal/namespace-match.d.ts.map +0 -1
  465. package/dist/store/internal/namespace-match.js +0 -41
  466. package/dist/store/internal/namespace-match.js.map +0 -1
  467. package/dist/store/internal/overwrite-swap.d.ts +0 -33
  468. package/dist/store/internal/overwrite-swap.d.ts.map +0 -1
  469. package/dist/store/internal/overwrite-swap.js +0 -62
  470. package/dist/store/internal/overwrite-swap.js.map +0 -1
  471. package/dist/store/internal/persist.d.ts +0 -27
  472. package/dist/store/internal/persist.d.ts.map +0 -1
  473. package/dist/store/internal/persist.js +0 -59
  474. package/dist/store/internal/persist.js.map +0 -1
  475. package/dist/store/internal/query.d.ts +0 -6
  476. package/dist/store/internal/query.d.ts.map +0 -1
  477. package/dist/store/internal/query.js +0 -32
  478. package/dist/store/internal/query.js.map +0 -1
  479. package/dist/store/internal/ranker.d.ts +0 -13
  480. package/dist/store/internal/ranker.d.ts.map +0 -1
  481. package/dist/store/internal/ranker.js +0 -31
  482. package/dist/store/internal/ranker.js.map +0 -1
  483. package/dist/store/internal/read-existing.d.ts +0 -19
  484. package/dist/store/internal/read-existing.d.ts.map +0 -1
  485. package/dist/store/internal/read-existing.js +0 -29
  486. package/dist/store/internal/read-existing.js.map +0 -1
  487. package/dist/store/internal/score-direction.d.ts +0 -32
  488. package/dist/store/internal/score-direction.d.ts.map +0 -1
  489. package/dist/store/internal/score-direction.js +0 -39
  490. package/dist/store/internal/score-direction.js.map +0 -1
  491. package/dist/store/internal/search-filter.d.ts +0 -4
  492. package/dist/store/internal/search-filter.d.ts.map +0 -1
  493. package/dist/store/internal/search-filter.js +0 -11
  494. package/dist/store/internal/search-filter.js.map +0 -1
  495. package/dist/store/internal/semantic-search.d.ts.map +0 -1
  496. package/dist/store/internal/semantic-search.js.map +0 -1
  497. package/dist/store/internal/setup.d.ts.map +0 -1
  498. package/dist/store/internal/setup.js.map +0 -1
  499. package/dist/store/internal/validation.d.ts +0 -13
  500. package/dist/store/internal/validation.d.ts.map +0 -1
  501. package/dist/store/internal/validation.js +0 -35
  502. package/dist/store/internal/validation.js.map +0 -1
  503. package/dist/store/internal/write-verify.d.ts +0 -37
  504. package/dist/store/internal/write-verify.d.ts.map +0 -1
  505. package/dist/store/internal/write-verify.js +0 -68
  506. package/dist/store/internal/write-verify.js.map +0 -1
  507. package/dist/store/store.d.ts.map +0 -1
  508. package/dist/store/store.js.map +0 -1
  509. package/dist/store/types.d.ts.map +0 -1
  510. package/dist/store/types.js.map +0 -1
  511. package/dist/store/vector-backend.d.ts.map +0 -1
  512. package/dist/store/vector-backend.js.map +0 -1
@@ -1,70 +1,340 @@
1
1
  "use strict";
2
+ /**
3
+ * Hides deleting exactly the rows of a partition that a read observed.
4
+ *
5
+ * A partition on a shared table can hold another adapter's rows, and a row can
6
+ * be rewritten between the read and the delete. A foreign row is left in place,
7
+ * each delete is pinned to the write id the read saw so a rewritten row
8
+ * survives, the rows of a unit are skipped once one of them is refused, and an
9
+ * object is released only once the row naming it is confirmed gone.
10
+ */
2
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.DELETE_CONCURRENCY = void 0;
13
+ exports.namedDescriptor = namedDescriptor;
3
14
  exports.deletePartitionRows = deletePartitionRows;
4
- const descriptor_keys_1 = require("../codec/descriptor-keys");
5
- const orphans_1 = require("../codec/s3/orphans");
6
- const constants_1 = require("../constants");
15
+ exports.flushPendingDeletes = flushPendingDeletes;
16
+ const codec_1 = require("../codec/codec");
17
+ const offloader_1 = require("../codec/s3/offloader");
18
+ const concurrency_1 = require("../concurrency");
7
19
  const errors_1 = require("../errors/errors");
20
+ const truncate_1 = require("../logging/truncate");
21
+ const abort_1 = require("./abort");
8
22
  const batch_write_1 = require("./batch-write");
23
+ const idempotent_write_1 = require("./idempotent-write");
9
24
  const paginate_1 = require("./paginate");
10
- /** Delete the buffered keys, best-effort clean their S3 objects, then clear it. */
11
- async function flushBuffer(options, buffer, progress) {
12
- if (buffer.keys.length === 0)
13
- return;
14
- const chunks = Math.ceil(buffer.keys.length / constants_1.BATCH_WRITE_MAX);
15
- try {
16
- await (0, batch_write_1.batchWriteAll)(options.client, options.tableName, buffer.keys.map((Key) => ({ DeleteRequest: { Key } })));
17
- }
18
- catch (error) {
19
- /** batchWriteAll's only throw is a BatchWriteAllIncompleteError (see batch-write.ts). */
20
- const failure = error;
21
- throw new errors_1.BatchWriteAllIncompleteError(progress.succeededChunks + failure.succeededChunks, progress.totalChunks + failure.totalChunks, failure.failedChunks, progress.writes + failure.succeededCount);
25
+ const retry_1 = require("./retry");
26
+ const table_schema_1 = require("./table-schema");
27
+ /**
28
+ * Conditional row deletes a partition-wide delete keeps in flight. Pinning a
29
+ * row on the write that produced it costs one request per row where a batch
30
+ * carried twenty-five, so issuing them one at a time would have paid a round
31
+ * trip per row; eight at once gives most of that back while keeping a
32
+ * partition of any size from opening a socket per row. A fixed value rather
33
+ * than a caller option: this is a maintenance path, and it has no other knob.
34
+ *
35
+ * Its own literal at the same value as `DEFAULT_READ_CONCURRENCY`
36
+ * (`src/shared/concurrency.ts`), not an alias of it — aliasing two limits
37
+ * would move one whenever the other is retuned (see
38
+ * `LIST_SCAN_WARN_THRESHOLD` (`src/shared/dynamodb/paginate.ts`)).
39
+ */
40
+ exports.DELETE_CONCURRENCY = 8;
41
+ /**
42
+ * One row attribute read as a named descriptor, which is the only way this
43
+ * library fills a {@link NamedDescriptor}.
44
+ *
45
+ * Accepts: `row` — a row the partition read returned, whose attributes this
46
+ * library did not necessarily write. `attribute` — the name the payload would
47
+ * be held under.
48
+ *
49
+ * Returns: the named descriptor, or nothing when the row carries no usable one
50
+ * there. An absent attribute and one holding `null` are the same answer,
51
+ * because neither names a payload: the row contributes no id to pin on and no
52
+ * object to release. Narrowing here rather than at each caller is what keeps
53
+ * `descriptor` the non-null thing the type claims — a `null` cast into the
54
+ * array by a caller reached `pinFor`, which reads a write id off it.
55
+ *
56
+ * Throws: nothing.
57
+ */
58
+ function namedDescriptor(row, attribute) {
59
+ const descriptor = row[attribute];
60
+ if (descriptor === null || descriptor === undefined)
61
+ return undefined;
62
+ return { attribute, descriptor };
63
+ }
64
+ /**
65
+ * The condition the read's own observation supports: the top-level id when the
66
+ * row carries one, else the id on the first descriptor that has one. A row
67
+ * observed with neither gets none and is deleted unconditionally — every row
68
+ * written before the id existed is such a row, and refusing those would leave a
69
+ * table upgraded in place impossible to empty.
70
+ */
71
+ function pinFor(idAttribute, row, named) {
72
+ if (idAttribute !== undefined) {
73
+ const observed = row[idAttribute];
74
+ if (typeof observed === 'string')
75
+ return (0, idempotent_write_1.writeIdGuard)(idAttribute, observed);
22
76
  }
23
- progress.writes += buffer.keys.length;
24
- progress.succeededChunks += chunks;
25
- progress.totalChunks += chunks;
26
- if (options.offloader) {
27
- await (0, orphans_1.cleanUpS3Orphans)(options.offloader, (0, descriptor_keys_1.collectS3Keys)(buffer.descriptors), options.operation, options.logger);
77
+ for (const entry of named) {
78
+ const { writeId } = entry.descriptor;
79
+ if (writeId !== undefined)
80
+ return (0, idempotent_write_1.writeIdGuard)(entry.attribute, writeId, idempotent_write_1.WRITE_ID_ATTRIBUTE);
28
81
  }
29
- buffer.keys = [];
30
- buffer.descriptors = [];
82
+ return undefined;
83
+ }
84
+ /** The row as a buffered delete: its key, its pin, its objects and its unit. */
85
+ function pendingDelete(options, row) {
86
+ const named = options.descriptorsOf(row);
87
+ return {
88
+ key: (0, table_schema_1.rowKeyOf)(row),
89
+ guard: pinFor(options.idAttribute, row, named),
90
+ descriptors: named.map((entry) => entry.descriptor),
91
+ unit: options.unitOf?.(row),
92
+ };
93
+ }
94
+ /** Whether an earlier kind's refusal already settled this row's unit. */
95
+ function unitRefused(options, row, state) {
96
+ const unit = options.unitOf?.(row);
97
+ return unit !== undefined && state.units.has(unit);
31
98
  }
32
99
  /**
33
- * Delete every row in a partition that belongs to the calling adapter,
34
- * best-effort deleting any offloaded S3 objects. Streams the partition with
35
- * unbounded pagination and flushes in batches, so a partition of any size is
36
- * deleted to completion with bounded memory — never silently truncated at the
37
- * in-memory page caps, and never discarding already-flushed progress if a
38
- * later batch fails. Returns the number of rows deleted.
100
+ * The cancel among a flush's failures, when the caller's signal fired. A row
101
+ * whose delete was cancelled is neither deleted nor failed, so reporting the
102
+ * pass as an incomplete delete told a caller branching on `ABORTED` that its
103
+ * own stop was a fault.
104
+ */
105
+ function cancelAmong(failures) {
106
+ return failures.find(abort_1.isAbortError);
107
+ }
108
+ /** Delete the buffered rows, fold what they settled into the pass, and empty the buffer. */
109
+ async function flushBuffer(options, state) {
110
+ if (state.buffer.length === 0)
111
+ return;
112
+ const tally = await flushPendingDeletes(options, state.buffer.splice(0));
113
+ state.deleted += tally.deleted;
114
+ state.skipped += tally.refused;
115
+ // Refusals are deliberately out of this total. They are not rows the pass
116
+ // failed to delete; they are rows it was never entitled to delete, already
117
+ // counted as `skipped` and reported on their own line. Counting them here
118
+ // would make the error read `1/3 row(s) succeeded, 1 row(s) failed` and leave
119
+ // the reader to guess at the third.
120
+ state.attempted += tally.deleted + tally.failures.length;
121
+ for (const unit of tally.refusedUnits)
122
+ state.units.add(unit);
123
+ if (tally.failures.length === 0)
124
+ return;
125
+ const cancelled = cancelAmong(tally.failures);
126
+ if (cancelled !== undefined)
127
+ throw cancelled;
128
+ const { deleted, attempted } = state;
129
+ throw (0, errors_1.batchWriteAllIncompleteError)({
130
+ succeeded: deleted,
131
+ total: attempted,
132
+ failures: tally.failures,
133
+ succeededCount: deleted,
134
+ unit: 'row',
135
+ });
136
+ }
137
+ /**
138
+ * Delete exactly the rows of one partition that this adapter's read observed.
139
+ *
140
+ * Accepts: `params` — the partition query, which carries no sort-key
141
+ * condition. `ownsSortKey` — decides per row; a row it rejects is left in
142
+ * place and reported at `warn`, which is what keeps a shared table's other
143
+ * adapters intact. `descriptorsOf` — the offloaded payloads a row references,
144
+ * each named by the attribute holding it. `idAttribute`, `unitOf` and `kindOf`
145
+ * — the per-write id, the unit and the kind boundary, for an adapter whose
146
+ * rows have them. `scope` — the partition's own leading S3 key parts; an object
147
+ * outside their path is never deleted. `signal` — stops the read between pages.
148
+ *
149
+ * Returns: how many rows were deleted, not counting the ones left in place.
150
+ *
151
+ * Throws: `ABORTED` when the signal fires, whether between pages or during
152
+ * a row's delete, unwrapped and with no further row issued — a cancel is not a
153
+ * delete that half-landed. Otherwise `BATCH_WRITE_INCOMPLETE` when
154
+ * a row's delete fails, carrying what did succeed across every earlier flush.
155
+ * S3 cleanup never throws, whatever it finds.
156
+ *
157
+ * Guarantees: every delete is pinned on the per-write id the read observed, so
158
+ * a row rewritten after that read is left in place and reported rather than
159
+ * erased with the object it names. A row observed carrying no id is deleted
160
+ * unconditionally, as it was before the pin existed. The read is deliberately
161
+ * uncapped (`maxItems` and `maxIterations` are `Infinity`), so a partition of
162
+ * any size is deleted to completion rather than truncated at the in-memory page
163
+ * caps — memory stays bounded because rows are flushed in batches of
164
+ * {@link BATCH_WRITE_MAX} and never accumulated. The carry-forward depends on
165
+ * the scan being **ascending**, which is the default the partition queries rely
166
+ * on: a kind's rows are settled before the next kind's are issued, so a refusal
167
+ * suppresses the rest of its unit. A failure part-way keeps the rows already
168
+ * deleted; this is a single pass over a quiescent partition, not a transaction.
39
169
  */
40
170
  async function deletePartitionRows(options) {
41
- const buffer = { keys: [], descriptors: [] };
42
- const progress = { writes: 0, succeededChunks: 0, totalChunks: 0 };
43
- let skipped = 0;
171
+ const state = { buffer: [], deleted: 0, attempted: 0, skipped: 0, units: new Set() };
172
+ let kind;
44
173
  const pages = (0, paginate_1.paginateQuery)({
45
174
  client: options.client,
46
175
  params: options.params,
176
+ retry: options.retry,
177
+ signal: options.signal,
47
178
  maxItems: Number.POSITIVE_INFINITY,
48
179
  maxIterations: Number.POSITIVE_INFINITY,
49
180
  });
50
181
  for await (const row of pages) {
51
- if (!options.ownsSortKey(row.SK)) {
52
- skipped += 1;
182
+ const sortKey = row.SK;
183
+ if (!options.ownsSortKey(sortKey)) {
184
+ state.skipped += 1;
53
185
  options.logger.warn(`${options.operation}: left a foreign row in place`, {
54
- sortKey: row.SK,
186
+ sortKey: (0, truncate_1.truncateForLog)(sortKey),
55
187
  });
56
188
  continue;
57
189
  }
58
- buffer.keys.push({ PK: row.PK, SK: row.SK });
59
- for (const descriptor of options.descriptorsOf(row)) {
60
- if (descriptor)
61
- buffer.descriptors.push(descriptor);
190
+ const rowKind = options.kindOf?.(row);
191
+ if (rowKind !== kind) {
192
+ await flushBuffer(options, state);
193
+ kind = rowKind;
194
+ }
195
+ if (unitRefused(options, row, state)) {
196
+ state.skipped += 1;
197
+ options.logger.warn(`${options.operation}: skipped a row whose unit was refused`, {
198
+ sortKey: (0, truncate_1.truncateForLog)(sortKey),
199
+ });
200
+ continue;
62
201
  }
63
- if (buffer.keys.length >= constants_1.BATCH_WRITE_MAX)
64
- await flushBuffer(options, buffer, progress);
202
+ state.buffer.push(pendingDelete(options, row));
203
+ if (state.buffer.length >= batch_write_1.BATCH_WRITE_MAX)
204
+ await flushBuffer(options, state);
205
+ }
206
+ await flushBuffer(options, state);
207
+ const { deleted, skipped } = state;
208
+ options.logger.info(`${options.operation}: deleted rows`, { deleted, skipped });
209
+ return deleted;
210
+ }
211
+ /**
212
+ * Record a row the pin turned away: left in place, nothing released, reported.
213
+ *
214
+ * Reported *before* it is counted, deliberately. The report calls the caller's
215
+ * own `Logger`, and a `Logger` that throws makes this row's handling
216
+ * incomplete; {@link deleteRow} then files it as a failure. Counting it first
217
+ * would leave the same row counted as a refusal the pass also reports as a
218
+ * failure. One row, one outcome.
219
+ */
220
+ function recordRefusal(deps, row, tally) {
221
+ deps.logger.warn(`${deps.operation}: left a row rewritten since the read`, {
222
+ sortKey: (0, truncate_1.truncateForLog)(row.key.SK),
223
+ });
224
+ tally.refused += 1;
225
+ if (row.unit !== undefined)
226
+ tally.refusedUnits.push(row.unit);
227
+ }
228
+ /**
229
+ * Settle one row, turning a lost pin into an outcome rather than a rejection.
230
+ *
231
+ * A rejection carrying the row means it was rewritten after the read: the row
232
+ * stays, its objects stay, and the pass reports it. A rejection carrying no row
233
+ * means it is already gone — a racing delete, or this pass's own earlier
234
+ * attempt whose acknowledgement was lost — which is the outcome the caller
235
+ * asked for, so it counts as deleted and its objects are released. Anything
236
+ * else is a genuine failure and is rethrown, so the pass ends rather than
237
+ * reporting a delete it did not make.
238
+ */
239
+ async function settleRow(deps, row, tally) {
240
+ try {
241
+ await (0, retry_1.withDynamoDBRetry)((request) => deps.client.delete({
242
+ TableName: deps.tableName,
243
+ Key: row.key,
244
+ ...row.guard,
245
+ }, request), deps.retry);
246
+ }
247
+ catch (error) {
248
+ const rejection = error;
249
+ if (!(0, idempotent_write_1.isConditionalCheckFailed)(rejection))
250
+ throw rejection;
251
+ if ((0, idempotent_write_1.rejectedRow)(rejection) !== undefined) {
252
+ recordRefusal(deps, row, tally);
253
+ return;
254
+ }
255
+ }
256
+ tally.deleted += 1;
257
+ tally.released.push(...row.descriptors);
258
+ }
259
+ /**
260
+ * Delete one row, recording whatever stops it before letting the flush end.
261
+ *
262
+ * The recording wraps the whole of {@link settleRow} rather than sitting in the
263
+ * one branch that first needed it, because the delete's own rejection is not
264
+ * the only thing in there that can throw. Reading the row a rejection carries
265
+ * is a decode, and it fails on an `Item` that arrives already unmarshalled —
266
+ * which the stock document client does not produce, but a client wrapped
267
+ * through the documented injection seam can. Reporting a refusal is a call into
268
+ * the caller's own `Logger`, which is consumer code. Recorded only in that one
269
+ * branch, neither would reach `tally.failures`, and an empty `failures` is
270
+ * exactly what the pass reads as "nothing went wrong": one such throw would
271
+ * abandon the rest of the buffer and the pass would still resolve, reporting a
272
+ * thread deleted that was mostly still there.
273
+ */
274
+ async function deleteRow(deps, row, tally) {
275
+ try {
276
+ await settleRow(deps, row, tally);
277
+ }
278
+ catch (error) {
279
+ tally.failures.push(error);
280
+ throw error;
281
+ }
282
+ }
283
+ /**
284
+ * Delete a buffer of rows, each pinned on what the read observed of it, then
285
+ * release the objects of the rows that are confirmed gone.
286
+ *
287
+ * Accepts: `deps` — the client, the table, and the logging, retry and offload
288
+ * collaborators of the pass this flush belongs to. `rows` — the buffer,
289
+ * each row carrying its key, its pin and the objects it names.
290
+ *
291
+ * Returns: the tally — rows deleted, rows refused and the units they belonged
292
+ * to, the failures, and the descriptors released.
293
+ *
294
+ * Throws: nothing. Every failure stops the flush from starting further rows and
295
+ * is handed back in `failures` for the caller to end the pass with — the
296
+ * delete's own rejection, and equally a throw from decoding a rejection's
297
+ * attached row or from the caller's logger, neither of which is this pass's to
298
+ * absorb. A refusal never stops anything. S3 cleanup never throws either
299
+ * ({@link cleanUpS3Orphans}).
300
+ *
301
+ * Guarantees: an empty `failures` means every row of the buffer was settled.
302
+ * The flush cannot both lose a failure and hand back a clean tally, which is
303
+ * what let a pass log a deleted thread over a partition it had mostly left
304
+ * alone. At most {@link DELETE_CONCURRENCY} requests are in flight. There
305
+ * is one request per row - that is the price of a condition, which a batch
306
+ * write silently ignores - but they cost a bounded number of sequential rounds
307
+ * rather than one per row, and a partition of any size cannot open a socket
308
+ * per row. A row the pin
309
+ * turned away is left exactly as the racing writer left it, and nothing it
310
+ * names is released — a live row still names those objects.
311
+ */
312
+ async function flushPendingDeletes(deps, rows) {
313
+ const tally = {
314
+ deleted: 0,
315
+ refused: 0,
316
+ refusedUnits: [],
317
+ failures: [],
318
+ released: [],
319
+ };
320
+ try {
321
+ await (0, concurrency_1.mapWithConcurrency)(rows, exports.DELETE_CONCURRENCY, (row) => deleteRow(deps, row, tally));
322
+ }
323
+ catch {
324
+ // The only thing that reaches here is {@link deleteRow}'s own rethrow, and
325
+ // it records every failure it rethrows — the delete's rejection, the decode
326
+ // of a rejection's attached row, and the caller's logger alike. So what is
327
+ // dropped here is a second reference to something already in
328
+ // `tally.failures`, never the only record of it, and the throw's remaining
329
+ // job was to stop further rows from being started.
330
+ }
331
+ if (deps.offloader) {
332
+ await (0, offloader_1.cleanUpS3Orphans)(deps.offloader, {
333
+ keys: (0, codec_1.collectS3Keys)(tally.released),
334
+ operation: deps.operation,
335
+ logger: deps.logger,
336
+ scope: deps.scope,
337
+ });
65
338
  }
66
- await flushBuffer(options, buffer, progress);
67
- options.logger.info(`${options.operation}: deleted rows`, { deleted: progress.writes, skipped });
68
- return progress.writes;
339
+ return tally;
69
340
  }
70
- //# sourceMappingURL=partition-delete.js.map
@@ -0,0 +1,231 @@
1
+ /**
2
+ * Hides the recency index (record 8).
3
+ *
4
+ * A row that a cross-partition listing reaches carries two index keys: a
5
+ * partition that hashes its identity onto one of a fixed number of shards, and
6
+ * a sort key that orders it by time. A listing reads every shard at once,
7
+ * merges them newest first, and hands out an opaque cursor that resumes the
8
+ * merge. The shard function, the key format and the merge are decided here.
9
+ */
10
+ import { type PageLimit } from '../validation/primitives';
11
+ import type { AttributeMap, DynamoDBDocumentLike } from './client';
12
+ import { type RetryOptions } from './retry';
13
+ /** One page of a recency listing, and where the next one resumes. */
14
+ export interface IndexPage {
15
+ items: AttributeMap[];
16
+ /** Absent when the page is the last one. */
17
+ nextCursor?: string;
18
+ }
19
+ /**
20
+ * Read one page of a recency listing from the index, newest first.
21
+ *
22
+ * Each shard is read one DynamoDB page at a time and the pages are merged row
23
+ * by row: the newest buffered row goes onto the page, and a shard whose buffer
24
+ * runs dry reads its next page before another row is chosen. That is correct
25
+ * because each shard is already sorted and no row is chosen while a shard that
26
+ * may hold a newer one is unread. It is also what bounds memory: a listing
27
+ * holds the page it is building, up to `limit` rows, plus at most one DynamoDB
28
+ * page per shard, and a shard none of whose buffered rows the page takes is
29
+ * never followed. The price is that a dry shard is read again whenever the page
30
+ * still needs a row, even when every row still to come is another shard's,
31
+ * which can cost a query per shard per page whose rows the page never takes.
32
+ * The alternative — one query over an unsharded index — would make every
33
+ * listing hit one partition, which is what the sharding exists to avoid.
34
+ *
35
+ * This replaces a full-table `Scan` with a `FilterExpression`, which consumed
36
+ * read capacity for every row *evaluated*, collected the whole table in memory
37
+ * and sorted it there.
38
+ *
39
+ * Accepts: `limit` — a `PageLimit`, already checked against the package-wide
40
+ * page rule by the caller's parser. `0` returns an empty page with no cursor
41
+ * and issues no query — and is answered here rather than left to the merge,
42
+ * where an empty page with shards still unread would have read
43
+ * `items[items.length - 1]` off an empty array to build the cursor. `cursor`
44
+ * — from a previous page, or none to start at the newest. `shards` — must
45
+ * match what the writers used. `concurrency` — how many shards are queried at
46
+ * once.
47
+ *
48
+ * Returns: the page, newest first, and a `nextCursor` exactly while rows may
49
+ * remain: a shard still buffers a row the page did not take, or has not
50
+ * reported its end. A cursor is never withheld while rows remain, and none is
51
+ * issued once every shard has reported its end, even for a page filled
52
+ * exactly. DynamoDB can still report a `LastEvaluatedKey` on a page that ends
53
+ * at a shard's last row, so the page after such a cursor may come back empty.
54
+ *
55
+ * Throws: `VALIDATION` naming `cursor`; `RESULT_TRUNCATED`
56
+ * for a shard whose pages do not end within `MAX_LOOP_ITERATIONS`; whatever
57
+ * the queries throw, including an `ABORTED` error.
58
+ *
59
+ * Guarantees: at most `concurrency` shards are queried at once; each shard is
60
+ * followed across DynamoDB's 1 MB page boundary, but its next page is read only
61
+ * when its buffer is empty and the page still needs a row, so besides the page
62
+ * being built, up to `limit` rows, no more than one DynamoDB page per shard is
63
+ * held at a time.
64
+ */
65
+ export declare function queryRecencyIndex(options: IndexQueryOptions): Promise<IndexPage>;
66
+ /**
67
+ * Every row of one adapter's recency index, newest first, page by page.
68
+ *
69
+ * The streaming counterpart of {@link queryRecencyIndex}, for a caller that
70
+ * consumes rows until it has what it needs and then stops. It replaces a
71
+ * full-table `Scan` whose cost scaled with the table rather than with the
72
+ * answer.
73
+ *
74
+ * Accepts: as {@link queryRecencyIndex}, without `limit` and `cursor` — this
75
+ * walks the whole index, paging internally.
76
+ *
77
+ * Returns: an async generator over every row, newest first. An early `break`
78
+ * fetches no further page, so a caller that needs ten rows of a large index
79
+ * pays for one page.
80
+ *
81
+ * Throws: as {@link queryRecencyIndex}.
82
+ */
83
+ export declare function iterateRecencyIndex(options: Omit<IndexQueryOptions, 'limit' | 'cursor'>): AsyncGenerator<AttributeMap>;
84
+ /** The adapter tags that scope GSI1, matching the partition-key tags. */
85
+ export type IndexTag = 'CHKPT' | 'STORE' | 'SESS';
86
+ /** How a row appears in the recency index: its adapter's tag, its identity, and its time. */
87
+ export interface IndexTarget {
88
+ tag: IndexTag;
89
+ id: string;
90
+ at: string;
91
+ }
92
+ /** The time a row that recorded none is indexed at, older than anything indexed since. */
93
+ export declare const BACKFILLED_AT = "1970-01-01T00:00:00.000Z";
94
+ /**
95
+ * The time a backfilled row is indexed at.
96
+ *
97
+ * Accepts: `recorded` — the row's own time attribute, whatever it holds.
98
+ *
99
+ * Returns: that time when it is a string, else {@link BACKFILLED_AT}.
100
+ *
101
+ * Throws: nothing.
102
+ */
103
+ export declare function backfilledAt(recorded: AttributeMap[string]): string;
104
+ /** The two attributes a row carries to appear in GSI1. */
105
+ export interface IndexKeys {
106
+ gsi1pk: string;
107
+ gsi1sk: string;
108
+ }
109
+ /** Default number of index partitions per adapter. */
110
+ export declare const DEFAULT_INDEX_SHARDS = 8;
111
+ /**
112
+ * The most shards a recency index may have. The indexed read builds every
113
+ * shard's partition key and issues at least one query per shard, so an
114
+ * unbounded value turns a config typo into an unbounded stream of requests and
115
+ * an out-of-memory crash. How many of those queries run at once is
116
+ * `readConcurrency`.
117
+ */
118
+ export declare const MAX_INDEX_SHARDS = 1024;
119
+ /**
120
+ * The GSI1 keys for a row that takes part in cross-partition listing.
121
+ *
122
+ * The partition key is the adapter tag plus a shard, because an index keyed by
123
+ * the tag alone is one partition per adapter — a single hot partition, which is
124
+ * worse than the table scan it replaces. AWS names the sharding requirement
125
+ * directly: mapping one identifier onto one partition key "will quickly create
126
+ * partition hot spots", and the answer is a secondary sharding model
127
+ * (https://docs.aws.amazon.com/whitepapers/latest/multi-tenant-saas-storage-strategies/multitenancy-on-dynamodb.html).
128
+ *
129
+ * The sort key leads with an ISO-8601 timestamp, used unparsed: its byte order
130
+ * already is its chronological order, so a recency listing is a key condition
131
+ * rather than an in-memory sort. The row's own id follows it, which makes the
132
+ * key total — two rows written in the same millisecond still order, so a cursor
133
+ * can never loop.
134
+ *
135
+ * Accepts: `tag` — the adapter's. `id` — the row's own identifier, which
136
+ * decides its shard and breaks ties in the sort key. `at` — an ISO-8601
137
+ * instant. `shards` — index partitions per adapter, at least 1; fixed at table
138
+ * creation, since changing it changes every row's shard and requires a
139
+ * backfill.
140
+ *
141
+ * Returns: the two index attributes.
142
+ *
143
+ * Throws: `VALIDATION` naming `indexShards` for a count below 1 — the read
144
+ * side built an empty partition list from such a value and reported an empty
145
+ * table full of rows.
146
+ *
147
+ * Guarantees: the same row always lands on the same shard, so a listing that
148
+ * queries every shard sees every row exactly once.
149
+ */
150
+ export declare function indexKeys(tag: IndexTag, id: string, at: string, shards: number): IndexKeys;
151
+ /**
152
+ * Every index partition of one adapter.
153
+ *
154
+ * Accepts: `shards` — the same count the rows were written with; validated
155
+ * here as it is in {@link indexKeys}, because a listing that silently queried
156
+ * an empty partition list would return nothing for a table full of rows.
157
+ *
158
+ * Returns: one partition key per shard, which a recency listing queries in
159
+ * parallel and merges.
160
+ *
161
+ * Throws: `VALIDATION` naming `indexShards`.
162
+ */
163
+ export declare function indexPartitions(tag: IndexTag, shards: number): string[];
164
+ /** What a recency listing needs to read one page. */
165
+ export interface IndexQueryOptions {
166
+ client: DynamoDBDocumentLike;
167
+ tableName: string;
168
+ indexName: string;
169
+ tag: IndexTag;
170
+ shards: number;
171
+ /** Shards queried at once: the adapter's `readConcurrency`. */
172
+ concurrency: number;
173
+ /** Rows per page, checked by the caller's parser, so the query does not check it again. */
174
+ limit: PageLimit;
175
+ /** Opaque, from a previous page. */
176
+ cursor?: string;
177
+ retry?: RetryOptions;
178
+ signal?: AbortSignal;
179
+ }
180
+ /** Where one shard stands while a listing builds a page. */
181
+ export interface ShardReader {
182
+ partition: string;
183
+ /**
184
+ * The rows of the shard's last DynamoDB page that are not on the listing's
185
+ * page yet, oldest first, so the newest is the last element and leaves with
186
+ * `pop()`. Never more than one page.
187
+ */
188
+ buffer: AttributeMap[];
189
+ /** Where the shard's next page starts; absent before its first page. */
190
+ startKey: AttributeMap | undefined;
191
+ /** True once DynamoDB reported no data past the last page read. */
192
+ exhausted: boolean;
193
+ /** DynamoDB pages read from this shard so far. */
194
+ pages: number;
195
+ }
196
+ /**
197
+ * A reader placed before a shard's first page.
198
+ *
199
+ * Accepts: `partition` — the shard's index partition key.
200
+ *
201
+ * Returns: a reader with an empty buffer that is not exhausted, so a listing
202
+ * reads its first page before choosing any row.
203
+ *
204
+ * Throws: nothing.
205
+ */
206
+ export declare function shardReader(partition: string): ShardReader;
207
+ /**
208
+ * Read a shard's next DynamoDB page into its buffer.
209
+ *
210
+ * `Limit` bounds the items a `Query` *evaluates*, and a page also stops at
211
+ * 1 MB, so a shard of large rows answers with fewer than `limit` items and a
212
+ * `LastEvaluatedKey`. Taking that short page as the whole shard would drop
213
+ * rows and report the listing complete. The key is kept here
214
+ * instead, and the listing reads the next page once the shard's buffer is empty
215
+ * and its page still needs a row. One page at a time is what bounds a listing's
216
+ * memory to at most one DynamoDB page per shard, besides the page it is
217
+ * building.
218
+ *
219
+ * Accepts: `reader` — its buffer empty and the shard not exhausted. `before` —
220
+ * the sort key to read below, or none for the newest. `limit` — the rows the
221
+ * listing's page still needs, at least 1; the shard cannot contribute more.
222
+ *
223
+ * Returns: nothing. The reader's buffer holds the page's rows, and its key,
224
+ * `exhausted` and page count describe what is left.
225
+ *
226
+ * Throws: `RESULT_TRUNCATED` naming `maxIterations`, without issuing
227
+ * a query, when the shard has already read {@link MAX_LOOP_ITERATIONS} pages —
228
+ * a listing fails rather than hand back a partial shard; whatever the query
229
+ * throws, including an `ABORTED` error.
230
+ */
231
+ export declare function readShardPage(options: IndexQueryOptions, reader: ShardReader, before: string | undefined, limit: number): Promise<void>;