@storyshelf/core 0.7.0 → 0.9.0-next-d2cc082

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 (537) hide show
  1. package/dist/adapter/capture-queue.d.mts +0 -2
  2. package/dist/adapter/capture-runner.d.mts +10 -4
  3. package/dist/adapter/capture-runner.mjs +7 -2
  4. package/dist/adapter/database.d.mts +63 -3
  5. package/dist/adapter/database.mjs +4 -3
  6. package/dist/adapter/database.mjs.map +1 -1
  7. package/dist/adapter/design.d.mts +0 -2
  8. package/dist/adapter/design.mjs +1 -2
  9. package/dist/adapter/email-sender.d.mts +0 -2
  10. package/dist/adapter/metadata.d.mts +0 -2
  11. package/dist/adapter/oauth.d.mts +0 -2
  12. package/dist/adapter/setup.d.mts +0 -2
  13. package/dist/adapter/setup.mjs +1 -2
  14. package/dist/adapter/storage.d.mts +1 -3
  15. package/dist/adapter/webhook-events.d.mts +0 -2
  16. package/dist/adapter/webhook-events.mjs +12 -13
  17. package/dist/adapter/webhook-events.mjs.map +1 -1
  18. package/dist/adapters/capture-target-offers.d.mts +0 -2
  19. package/dist/adapters/capture-target-offers.mjs +1 -2
  20. package/dist/adapters/capture-target.d.mts +0 -2
  21. package/dist/adapters/capture-target.mjs +1 -2
  22. package/dist/adapters/notifier/build-comment.d.mts +0 -2
  23. package/dist/adapters/notifier/build-comment.mjs +1 -2
  24. package/dist/adapters/notifier/build-state.d.mts +0 -2
  25. package/dist/adapters/notifier/build-state.mjs +1 -2
  26. package/dist/adapters/notifier/events.d.mts +0 -2
  27. package/dist/adapters/notifier/events.mjs +1 -2
  28. package/dist/adapters/notifier/format.d.mts +0 -2
  29. package/dist/adapters/notifier/format.mjs +1 -2
  30. package/dist/adapters/notifier/provider.d.mts +0 -2
  31. package/dist/adapters/notifier/provider.mjs +1 -2
  32. package/dist/adapters/notifier/state.d.mts +0 -2
  33. package/dist/adapters/notifier/state.mjs +1 -2
  34. package/dist/adapters/notifier/types.d.mts +0 -2
  35. package/dist/adapters/remote-browser.d.mts +120 -31
  36. package/dist/adapters/remote-browser.mjs +134 -34
  37. package/dist/adapters/remote-browser.mjs.map +1 -1
  38. package/dist/adapters/remote-lease-attempt.mjs +39 -0
  39. package/dist/adapters/remote-lease-attempt.mjs.map +1 -0
  40. package/dist/adapters/remote-lease-error.d.mts +25 -0
  41. package/dist/adapters/remote-lease-error.mjs +54 -0
  42. package/dist/adapters/remote-lease-error.mjs.map +1 -0
  43. package/dist/adapters/remote-lease-held.d.mts +15 -0
  44. package/dist/adapters/remote-lease-held.mjs +86 -0
  45. package/dist/adapters/remote-lease-held.mjs.map +1 -0
  46. package/dist/adapters/remote-lease-shutdown.d.mts +12 -0
  47. package/dist/adapters/remote-lease-shutdown.mjs +32 -0
  48. package/dist/adapters/remote-lease-shutdown.mjs.map +1 -0
  49. package/dist/adapters/remote-lease.d.mts +39 -0
  50. package/dist/adapters/remote-lease.mjs +175 -0
  51. package/dist/adapters/remote-lease.mjs.map +1 -0
  52. package/dist/adapters/remote-limiter.mjs +121 -0
  53. package/dist/adapters/remote-limiter.mjs.map +1 -0
  54. package/dist/adapters/remote-pool.d.mts +56 -0
  55. package/dist/adapters/remote-pool.mjs +195 -0
  56. package/dist/adapters/remote-pool.mjs.map +1 -0
  57. package/dist/adapters/remote-sizing.d.mts +44 -0
  58. package/dist/adapters/remote-sizing.mjs +53 -0
  59. package/dist/adapters/remote-sizing.mjs.map +1 -0
  60. package/dist/adapters/render-runs.d.mts +0 -2
  61. package/dist/adapters/render-runs.mjs +1 -2
  62. package/dist/adapters/setup-runner.d.mts +0 -2
  63. package/dist/adapters/setup-runner.mjs +1 -2
  64. package/dist/adapters/sources.d.mts +0 -2
  65. package/dist/adapters/sources.mjs +1 -2
  66. package/dist/adapters/validate.d.mts +0 -2
  67. package/dist/adapters/validate.mjs +2 -2
  68. package/dist/adapters/validate.mjs.map +1 -1
  69. package/dist/ai.d.mts +0 -2
  70. package/dist/ai.mjs +1 -2
  71. package/dist/auth.d.mts +0 -2
  72. package/dist/auth.mjs +1 -2
  73. package/dist/brand-packs.d.mts +0 -2
  74. package/dist/brand-packs.mjs +0 -1
  75. package/dist/capture/a11y/axe-source.d.mts +0 -2
  76. package/dist/capture/a11y/axe-source.mjs +1 -2
  77. package/dist/capture/a11y/in-page.d.mts +1 -3
  78. package/dist/capture/a11y/in-page.mjs +3 -4
  79. package/dist/capture/a11y/in-page.mjs.map +1 -1
  80. package/dist/capture/a11y/map.d.mts +0 -2
  81. package/dist/capture/a11y/map.mjs +1 -2
  82. package/dist/capture/a11y/options.d.mts +0 -2
  83. package/dist/capture/a11y/options.mjs +1 -2
  84. package/dist/capture/adapter.d.mts +5 -2
  85. package/dist/capture/adapter.mjs +1 -2
  86. package/dist/capture/adapter.mjs.map +1 -1
  87. package/dist/capture/affected.d.mts +0 -2
  88. package/dist/capture/affected.mjs +1 -2
  89. package/dist/capture/attempt-logger.mjs +1 -2
  90. package/dist/capture/browsers.d.mts +0 -2
  91. package/dist/capture/browsers.mjs +1 -2
  92. package/dist/capture/build-state/deliver.d.mts +0 -2
  93. package/dist/capture/build-state/deliver.mjs +1 -2
  94. package/dist/capture/build-state/notify-job.d.mts +0 -2
  95. package/dist/capture/build-state/notify-job.mjs +1 -2
  96. package/dist/capture/build-state/publisher.d.mts +0 -2
  97. package/dist/capture/build-state/publisher.mjs +1 -2
  98. package/dist/capture/build-state/resume.d.mts +0 -2
  99. package/dist/capture/build-state/resume.mjs +1 -2
  100. package/dist/capture/build-state/types.d.mts +1 -3
  101. package/dist/capture/catalog/catalogue.d.mts +0 -2
  102. package/dist/capture/catalog/catalogue.mjs +1 -2
  103. package/dist/capture/catalog/components.d.mts +0 -2
  104. package/dist/capture/catalog/components.mjs +1 -2
  105. package/dist/capture/catalog/history.d.mts +0 -2
  106. package/dist/capture/catalog/history.mjs +1 -2
  107. package/dist/capture/catalog/hook.d.mts +0 -2
  108. package/dist/capture/catalog/hook.mjs +1 -2
  109. package/dist/capture/catalog/index.d.mts +2 -2
  110. package/dist/capture/catalog/load.d.mts +0 -2
  111. package/dist/capture/catalog/load.mjs +1 -2
  112. package/dist/capture/catalog/parse.d.mts +0 -2
  113. package/dist/capture/catalog/parse.mjs +1 -2
  114. package/dist/capture/catalog/read.d.mts +6 -3
  115. package/dist/capture/catalog/read.mjs +14 -8
  116. package/dist/capture/catalog/read.mjs.map +1 -1
  117. package/dist/capture/catalog/types.d.mts +0 -2
  118. package/dist/capture/comparison-reference.d.mts +27 -0
  119. package/dist/capture/comparison-reference.mjs +75 -0
  120. package/dist/capture/comparison-reference.mjs.map +1 -0
  121. package/dist/capture/consumer/capture-handler.d.mts +1 -3
  122. package/dist/capture/consumer/capture-handler.mjs +1 -2
  123. package/dist/capture/consumer/idle.d.mts +0 -2
  124. package/dist/capture/consumer/idle.mjs +1 -2
  125. package/dist/capture/consumer/index.d.mts +0 -2
  126. package/dist/capture/consumer/index.mjs +1 -2
  127. package/dist/capture/consumer/loop.mjs +1 -2
  128. package/dist/capture/consumer/metrics.d.mts +0 -2
  129. package/dist/capture/consumer/metrics.mjs +1 -2
  130. package/dist/capture/consumer/retry.d.mts +0 -2
  131. package/dist/capture/consumer/retry.mjs +1 -2
  132. package/dist/capture/consumer/run-job.mjs +1 -2
  133. package/dist/capture/consumer/startup.mjs +1 -2
  134. package/dist/capture/consumer/types.d.mts +0 -2
  135. package/dist/capture/crash-failure.d.mts +0 -2
  136. package/dist/capture/crash-failure.mjs +1 -2
  137. package/dist/capture/db-queue/cadence.d.mts +0 -2
  138. package/dist/capture/db-queue/cadence.mjs +1 -2
  139. package/dist/capture/db-queue/claim.d.mts +0 -2
  140. package/dist/capture/db-queue/claim.mjs +20 -4
  141. package/dist/capture/db-queue/claim.mjs.map +1 -1
  142. package/dist/capture/db-queue/clock.mjs +1 -2
  143. package/dist/capture/db-queue/codec.mjs +1 -2
  144. package/dist/capture/db-queue/index.d.mts +0 -2
  145. package/dist/capture/db-queue/index.mjs +3 -3
  146. package/dist/capture/db-queue/index.mjs.map +1 -1
  147. package/dist/capture/db-queue/keeper.d.mts +0 -2
  148. package/dist/capture/db-queue/keeper.mjs +1 -2
  149. package/dist/capture/db-queue/lease.mjs +1 -2
  150. package/dist/capture/db-queue/lifecycle.mjs +1 -2
  151. package/dist/capture/db-queue/operations.mjs +1 -2
  152. package/dist/capture/db-queue/poll-loop.d.mts +0 -2
  153. package/dist/capture/db-queue/poll-loop.mjs +1 -2
  154. package/dist/capture/db-queue/poll.d.mts +0 -2
  155. package/dist/capture/db-queue/poll.mjs +1 -2
  156. package/dist/capture/db-queue/timers.d.mts +0 -2
  157. package/dist/capture/db-queue/timers.mjs +1 -2
  158. package/dist/capture/db-queue/types.d.mts +0 -2
  159. package/dist/capture/db-queue/types.mjs +1 -2
  160. package/dist/capture/db-queue/types.mjs.map +1 -1
  161. package/dist/capture/db-queue/wake.mjs +1 -2
  162. package/dist/capture/design.mjs +1 -2
  163. package/dist/capture/diff-record.mjs +1 -2
  164. package/dist/capture/dispatch.d.mts +1 -3
  165. package/dist/capture/dispatch.mjs +17 -5
  166. package/dist/capture/dispatch.mjs.map +1 -1
  167. package/dist/capture/enrich.mjs +1 -2
  168. package/dist/capture/failure-sets.mjs +1 -2
  169. package/dist/capture/fingerprint.d.mts +19 -8
  170. package/dist/capture/fingerprint.mjs +43 -14
  171. package/dist/capture/fingerprint.mjs.map +1 -1
  172. package/dist/capture/forked/channel.d.mts +0 -2
  173. package/dist/capture/forked/child.d.mts +0 -2
  174. package/dist/capture/forked/child.mjs +1 -2
  175. package/dist/capture/forked/crash-tracker.mjs +1 -2
  176. package/dist/capture/forked/decision.d.mts +0 -2
  177. package/dist/capture/forked/decision.mjs +1 -2
  178. package/dist/capture/forked/exit.mjs +1 -2
  179. package/dist/capture/forked/fork.d.mts +0 -2
  180. package/dist/capture/forked/fork.mjs +1 -2
  181. package/dist/capture/forked/forked-capture.d.mts +0 -2
  182. package/dist/capture/forked/forked-capture.mjs +1 -2
  183. package/dist/capture/forked/lease-book.mjs +1 -2
  184. package/dist/capture/forked/protocol.d.mts +0 -2
  185. package/dist/capture/forked/protocol.mjs +1 -2
  186. package/dist/capture/forked/runs.mjs +1 -2
  187. package/dist/capture/guards.mjs +1 -2
  188. package/dist/capture/ignore-regions.d.mts +36 -0
  189. package/dist/capture/ignore-regions.mjs +65 -0
  190. package/dist/capture/ignore-regions.mjs.map +1 -0
  191. package/dist/capture/isolate.mjs +1 -2
  192. package/dist/capture/job-lease.d.mts +0 -2
  193. package/dist/capture/job-lease.mjs +1 -2
  194. package/dist/capture/matrix.mjs +4 -4
  195. package/dist/capture/matrix.mjs.map +1 -1
  196. package/dist/capture/modes.d.mts +0 -2
  197. package/dist/capture/modes.mjs +2 -3
  198. package/dist/capture/modes.mjs.map +1 -1
  199. package/dist/capture/orchestrator.d.mts +0 -2
  200. package/dist/capture/orchestrator.mjs +2 -3
  201. package/dist/capture/pipeline.d.mts +0 -2
  202. package/dist/capture/pipeline.mjs +44 -10
  203. package/dist/capture/pipeline.mjs.map +1 -1
  204. package/dist/capture/progress.d.mts +0 -2
  205. package/dist/capture/progress.mjs +1 -2
  206. package/dist/capture/publish/accept.d.mts +0 -2
  207. package/dist/capture/publish/accept.mjs +1 -2
  208. package/dist/capture/publish/complete.d.mts +1 -3
  209. package/dist/capture/publish/complete.mjs +1 -2
  210. package/dist/capture/publish/extract.d.mts +0 -2
  211. package/dist/capture/publish/extract.mjs +6 -5
  212. package/dist/capture/publish/extract.mjs.map +1 -1
  213. package/dist/capture/publish/handler.d.mts +1 -3
  214. package/dist/capture/publish/handler.mjs +1 -2
  215. package/dist/capture/publish/index.d.mts +2 -1
  216. package/dist/capture/publish/invalid-zip.d.mts +8 -0
  217. package/dist/capture/publish/invalid-zip.mjs +11 -0
  218. package/dist/capture/publish/invalid-zip.mjs.map +1 -0
  219. package/dist/capture/publish/limits.d.mts +0 -2
  220. package/dist/capture/publish/limits.mjs +1 -2
  221. package/dist/capture/publish/published.d.mts +0 -2
  222. package/dist/capture/publish/published.mjs +1 -2
  223. package/dist/capture/publish/run.d.mts +1 -3
  224. package/dist/capture/publish/run.mjs +1 -2
  225. package/dist/capture/rediff.d.mts +1 -3
  226. package/dist/capture/rediff.mjs +19 -6
  227. package/dist/capture/rediff.mjs.map +1 -1
  228. package/dist/capture/render.mjs +1 -2
  229. package/dist/capture/render.mjs.map +1 -1
  230. package/dist/capture/scratch.d.mts +0 -2
  231. package/dist/capture/scratch.mjs +2 -4
  232. package/dist/capture/scratch.mjs.map +1 -1
  233. package/dist/capture/shard-plan.mjs +1 -2
  234. package/dist/capture/shards/context.mjs +3 -3
  235. package/dist/capture/shards/context.mjs.map +1 -1
  236. package/dist/capture/shards/execute.mjs +4 -3
  237. package/dist/capture/shards/execute.mjs.map +1 -1
  238. package/dist/capture/shards/fan-out.mjs +1 -2
  239. package/dist/capture/shards/history.mjs +1 -2
  240. package/dist/capture/shards/reduce.mjs +1 -2
  241. package/dist/capture/sizing.d.mts +0 -2
  242. package/dist/capture/sizing.mjs +1 -2
  243. package/dist/capture/skip-checks.mjs +1 -2
  244. package/dist/capture/statics.d.mts +0 -2
  245. package/dist/capture/statics.mjs +2 -4
  246. package/dist/capture/statics.mjs.map +1 -1
  247. package/dist/capture/storybook-urls.d.mts +0 -2
  248. package/dist/capture/storybook-urls.mjs +3 -3
  249. package/dist/capture/storybook-urls.mjs.map +1 -1
  250. package/dist/capture/storybook.d.mts +0 -2
  251. package/dist/capture/storybook.mjs +8 -4
  252. package/dist/capture/storybook.mjs.map +1 -1
  253. package/dist/capture/target.mjs +1 -2
  254. package/dist/capture/targets.d.mts +0 -2
  255. package/dist/capture/targets.mjs +1 -2
  256. package/dist/capture/tests.d.mts +0 -2
  257. package/dist/capture/tests.mjs +13 -3
  258. package/dist/capture/tests.mjs.map +1 -1
  259. package/dist/capture/token-chunks.mjs +24 -7
  260. package/dist/capture/token-chunks.mjs.map +1 -1
  261. package/dist/capture.d.mts +5 -2
  262. package/dist/capture.mjs +5 -2
  263. package/dist/config.d.mts +16 -3
  264. package/dist/config.mjs +6 -3
  265. package/dist/config.mjs.map +1 -1
  266. package/dist/diff.d.mts +0 -2
  267. package/dist/diff.mjs +1 -2
  268. package/dist/index.d.mts +2 -2
  269. package/dist/index.mjs +2 -2
  270. package/dist/insights/budget.d.mts +0 -2
  271. package/dist/insights/budget.mjs +1 -2
  272. package/dist/insights/envelope.d.mts +0 -2
  273. package/dist/insights/envelope.mjs +1 -2
  274. package/dist/insights/evidence-health.d.mts +0 -2
  275. package/dist/insights/evidence-health.mjs +1 -2
  276. package/dist/insights/evidence.d.mts +0 -2
  277. package/dist/insights/evidence.mjs +1 -2
  278. package/dist/insights/hash.d.mts +0 -2
  279. package/dist/insights/hash.mjs +1 -2
  280. package/dist/insights/limits.d.mts +0 -2
  281. package/dist/insights/limits.mjs +1 -2
  282. package/dist/insights/prompts/v1.d.mts +0 -2
  283. package/dist/insights/prompts/v1.mjs +1 -2
  284. package/dist/insights/redact.d.mts +0 -2
  285. package/dist/insights/redact.mjs +1 -2
  286. package/dist/insights/text.mjs +1 -2
  287. package/dist/logger.d.mts +0 -2
  288. package/dist/logger.mjs +1 -2
  289. package/dist/models/ai-budget-alert.d.mts +0 -2
  290. package/dist/models/ai-budget-alert.mjs +1 -2
  291. package/dist/models/ai-usage.d.mts +0 -2
  292. package/dist/models/ai-usage.mjs +1 -2
  293. package/dist/models/baseline-approval.d.mts +18 -0
  294. package/dist/models/baseline-approval.mjs +41 -0
  295. package/dist/models/baseline-approval.mjs.map +1 -0
  296. package/dist/models/baseline-archive.d.mts +0 -2
  297. package/dist/models/baseline-archive.mjs +1 -2
  298. package/dist/models/baseline-atomic.mjs +66 -0
  299. package/dist/models/baseline-atomic.mjs.map +1 -0
  300. package/dist/models/baseline-conflict.d.mts +6 -0
  301. package/dist/models/baseline-conflict.mjs +9 -0
  302. package/dist/models/baseline-conflict.mjs.map +1 -0
  303. package/dist/models/baseline-export.d.mts +0 -2
  304. package/dist/models/baseline-export.mjs +1 -2
  305. package/dist/models/baseline-import.mjs +1 -2
  306. package/dist/models/baseline-origin.d.mts +16 -0
  307. package/dist/models/baseline-origin.mjs +35 -0
  308. package/dist/models/baseline-origin.mjs.map +1 -0
  309. package/dist/models/baseline-status.d.mts +0 -2
  310. package/dist/models/baseline-status.mjs +1 -2
  311. package/dist/models/baseline-transfer.d.mts +1 -2
  312. package/dist/models/baseline-transfer.mjs +30 -2
  313. package/dist/models/baseline-transfer.mjs.map +1 -1
  314. package/dist/models/baseline.d.mts +5 -2
  315. package/dist/models/baseline.mjs +91 -12
  316. package/dist/models/baseline.mjs.map +1 -1
  317. package/dist/models/build-component.d.mts +0 -2
  318. package/dist/models/build-component.mjs +1 -2
  319. package/dist/models/build-review-status.d.mts +0 -2
  320. package/dist/models/build-review-status.mjs +1 -2
  321. package/dist/models/build-review.d.mts +0 -2
  322. package/dist/models/build-review.mjs +1 -2
  323. package/dist/models/build.d.mts +1 -3
  324. package/dist/models/build.mjs +14 -15
  325. package/dist/models/build.mjs.map +1 -1
  326. package/dist/models/capture-attempt.d.mts +0 -2
  327. package/dist/models/capture-attempt.mjs +1 -2
  328. package/dist/models/capture-job.d.mts +0 -2
  329. package/dist/models/capture-job.mjs +1 -2
  330. package/dist/models/capture-log.d.mts +0 -2
  331. package/dist/models/capture-log.mjs +1 -2
  332. package/dist/models/capture-shard.d.mts +0 -2
  333. package/dist/models/capture-shard.mjs +1 -2
  334. package/dist/models/changeset.d.mts +0 -2
  335. package/dist/models/changeset.mjs +1 -2
  336. package/dist/models/columns.mjs +1 -2
  337. package/dist/models/comment.d.mts +0 -2
  338. package/dist/models/comment.mjs +1 -2
  339. package/dist/models/component.d.mts +0 -2
  340. package/dist/models/component.mjs +1 -2
  341. package/dist/models/connections.d.mts +0 -2
  342. package/dist/models/connections.mjs +1 -2
  343. package/dist/models/content-ref.d.mts +0 -2
  344. package/dist/models/content-ref.mjs +1 -2
  345. package/dist/models/credentials.d.mts +0 -2
  346. package/dist/models/credentials.mjs +1 -2
  347. package/dist/models/design-credentials.d.mts +0 -2
  348. package/dist/models/design-credentials.mjs +1 -2
  349. package/dist/models/design-health.d.mts +16 -3
  350. package/dist/models/design-health.mjs +21 -3
  351. package/dist/models/design-health.mjs.map +1 -1
  352. package/dist/models/design-nodes.d.mts +11 -4
  353. package/dist/models/design-nodes.mjs +18 -3
  354. package/dist/models/design-nodes.mjs.map +1 -1
  355. package/dist/models/design-renders.mjs +1 -2
  356. package/dist/models/design-resolve.d.mts +0 -2
  357. package/dist/models/design-resolve.mjs +1 -2
  358. package/dist/models/design.d.mts +0 -2
  359. package/dist/models/design.mjs +1 -2
  360. package/dist/models/inherited-ratio.d.mts +0 -2
  361. package/dist/models/inherited-ratio.mjs +1 -2
  362. package/dist/models/insight.d.mts +0 -2
  363. package/dist/models/insight.mjs +1 -2
  364. package/dist/models/label.d.mts +0 -2
  365. package/dist/models/label.mjs +1 -2
  366. package/dist/models/member.d.mts +0 -2
  367. package/dist/models/member.mjs +1 -2
  368. package/dist/models/notification-channel.d.mts +0 -2
  369. package/dist/models/notification-channel.mjs +1 -2
  370. package/dist/models/notification-subscription.d.mts +0 -2
  371. package/dist/models/notification-subscription.mjs +1 -2
  372. package/dist/models/project-group-mapping.d.mts +0 -2
  373. package/dist/models/project-group-mapping.mjs +1 -2
  374. package/dist/models/project.d.mts +0 -2
  375. package/dist/models/project.mjs +1 -2
  376. package/dist/models/public-origin.d.mts +0 -2
  377. package/dist/models/public-origin.mjs +1 -2
  378. package/dist/models/review-switch-off.d.mts +0 -2
  379. package/dist/models/review-switch-off.mjs +1 -2
  380. package/dist/models/site-settings.d.mts +0 -2
  381. package/dist/models/site-settings.mjs +1 -2
  382. package/dist/models/snapshot.d.mts +3 -2
  383. package/dist/models/snapshot.mjs +4 -2
  384. package/dist/models/snapshot.mjs.map +1 -1
  385. package/dist/models/token.d.mts +0 -2
  386. package/dist/models/token.mjs +1 -2
  387. package/dist/models/usage.d.mts +0 -2
  388. package/dist/models/usage.mjs +1 -2
  389. package/dist/models/user.d.mts +0 -2
  390. package/dist/models/user.mjs +1 -2
  391. package/dist/models/webhook.d.mts +0 -2
  392. package/dist/models/webhook.mjs +1 -2
  393. package/dist/models.d.mts +6 -3
  394. package/dist/models.mjs +6 -3
  395. package/dist/options.d.mts +0 -2
  396. package/dist/options.mjs +2 -4
  397. package/dist/options.mjs.map +1 -1
  398. package/dist/paths.d.mts +3 -3
  399. package/dist/paths.mjs +7 -3
  400. package/dist/paths.mjs.map +1 -1
  401. package/dist/retention/ai.d.mts +1 -3
  402. package/dist/retention/ai.mjs +0 -1
  403. package/dist/retention/pending.mjs +1 -2
  404. package/dist/retention/published-gzip-sweep.mjs +28 -0
  405. package/dist/retention/published-gzip-sweep.mjs.map +1 -0
  406. package/dist/retention/screenshot-sweep.d.mts +0 -2
  407. package/dist/retention/screenshot-sweep.mjs +1 -2
  408. package/dist/retention.d.mts +0 -2
  409. package/dist/retention.mjs +5 -2
  410. package/dist/retention.mjs.map +1 -1
  411. package/dist/schema/baseline.d.mts +2 -2
  412. package/dist/schema/build-component.d.mts +0 -2
  413. package/dist/schema/build-review.d.mts +0 -2
  414. package/dist/schema/build.d.mts +0 -2
  415. package/dist/schema/capture-attempt.d.mts +0 -2
  416. package/dist/schema/capture-job.d.mts +0 -2
  417. package/dist/schema/capture-shard.d.mts +0 -2
  418. package/dist/schema/comment.d.mts +0 -2
  419. package/dist/schema/connection.d.mts +0 -2
  420. package/dist/schema/content-ref.d.mts +0 -2
  421. package/dist/schema/design.d.mts +2 -2
  422. package/dist/schema/insight.d.mts +0 -2
  423. package/dist/schema/label.d.mts +0 -2
  424. package/dist/schema/member.d.mts +0 -2
  425. package/dist/schema/notification.d.mts +0 -2
  426. package/dist/schema/project-group-mapping.d.mts +0 -2
  427. package/dist/schema/project.d.mts +0 -2
  428. package/dist/schema/site-setting.d.mts +0 -2
  429. package/dist/schema/snapshot.d.mts +5 -2
  430. package/dist/schema/token.d.mts +0 -2
  431. package/dist/schema/usage.d.mts +0 -2
  432. package/dist/schema/user.d.mts +0 -2
  433. package/dist/schema/webhook.d.mts +0 -2
  434. package/dist/schema.d.mts +4 -6
  435. package/dist/serverless.d.mts +0 -2
  436. package/dist/serverless.mjs +1 -2
  437. package/dist/test-helpers/build-reference-contract.d.mts +14 -0
  438. package/dist/test-helpers/build-reference-contract.mjs +66 -0
  439. package/dist/test-helpers/build-reference-contract.mjs.map +1 -0
  440. package/dist/test-helpers/create-project.d.mts +0 -2
  441. package/dist/test-helpers/create-project.mjs +1 -2
  442. package/dist/test-helpers/database-contract.d.mts +0 -2
  443. package/dist/test-helpers/database-contract.mjs +37 -2
  444. package/dist/test-helpers/database-contract.mjs.map +1 -1
  445. package/dist/test-helpers/deferred.d.mts +0 -2
  446. package/dist/test-helpers/deferred.mjs +1 -2
  447. package/dist/test-helpers/design-contract.d.mts +0 -2
  448. package/dist/test-helpers/design-contract.mjs +1 -2
  449. package/dist/test-helpers/fake-adapters.d.mts +0 -2
  450. package/dist/test-helpers/fake-adapters.mjs +1 -2
  451. package/dist/test-helpers/fake-database.d.mts +0 -2
  452. package/dist/test-helpers/fake-database.mjs +7 -2
  453. package/dist/test-helpers/fake-database.mjs.map +1 -1
  454. package/dist/test-helpers/fake-design.d.mts +0 -2
  455. package/dist/test-helpers/fake-design.mjs +1 -2
  456. package/dist/test-helpers/fake-notifier.d.mts +0 -2
  457. package/dist/test-helpers/fake-notifier.mjs +1 -2
  458. package/dist/test-helpers/fake-storage.d.mts +0 -2
  459. package/dist/test-helpers/fake-storage.mjs +1 -2
  460. package/dist/test-helpers/fake-tables.mjs +6 -2
  461. package/dist/test-helpers/fake-tables.mjs.map +1 -1
  462. package/dist/test-helpers/manual-clock.d.mts +0 -2
  463. package/dist/test-helpers/manual-clock.mjs +1 -2
  464. package/dist/test-helpers/notifier-contract.d.mts +0 -2
  465. package/dist/test-helpers/notifier-contract.mjs +1 -2
  466. package/dist/test-helpers/queue-contract.d.mts +0 -2
  467. package/dist/test-helpers/queue-contract.mjs +1 -2
  468. package/dist/test-helpers/queue-multi-instance.d.mts +0 -2
  469. package/dist/test-helpers/queue-multi-instance.mjs +1 -2
  470. package/dist/test-helpers/runner-contract.d.mts +0 -2
  471. package/dist/test-helpers/runner-contract.mjs +1 -2
  472. package/dist/test-helpers/sql-chunks.mjs +2 -2
  473. package/dist/test-helpers/sql-chunks.mjs.map +1 -1
  474. package/dist/test-helpers/storage-contract.d.mts +0 -2
  475. package/dist/test-helpers/storage-contract.mjs +1 -2
  476. package/dist/test-helpers.d.mts +2 -1
  477. package/dist/test-helpers.mjs +2 -1
  478. package/dist/tracing.mjs +36 -6
  479. package/dist/tracing.mjs.map +1 -1
  480. package/dist/types.d.mts +0 -2
  481. package/dist/types.mjs +1 -2
  482. package/dist/urls.d.mts +0 -2
  483. package/dist/urls.mjs +1 -2
  484. package/dist/utils/adaptive-concurrency.d.mts +0 -2
  485. package/dist/utils/adaptive-concurrency.mjs +1 -2
  486. package/dist/utils/connect-retry.d.mts +2 -2
  487. package/dist/utils/connect-retry.mjs +2 -3
  488. package/dist/utils/connect-retry.mjs.map +1 -1
  489. package/dist/utils/encrypt.d.mts +0 -2
  490. package/dist/utils/encrypt.mjs +1 -2
  491. package/dist/utils/environment.d.mts +0 -2
  492. package/dist/utils/environment.mjs +1 -2
  493. package/dist/utils/hash.d.mts +0 -2
  494. package/dist/utils/hash.mjs +1 -2
  495. package/dist/utils/http.d.mts +13 -3
  496. package/dist/utils/http.mjs +79 -17
  497. package/dist/utils/http.mjs.map +1 -1
  498. package/dist/utils/map-adaptive.d.mts +0 -2
  499. package/dist/utils/map-adaptive.mjs +1 -2
  500. package/dist/utils/map-limit.d.mts +0 -2
  501. package/dist/utils/map-limit.mjs +1 -2
  502. package/dist/utils/mime.d.mts +0 -2
  503. package/dist/utils/mime.mjs +1 -2
  504. package/dist/utils/page-limiter.d.mts +0 -2
  505. package/dist/utils/page-limiter.mjs +1 -2
  506. package/dist/utils/path-security.d.mts +0 -2
  507. package/dist/utils/path-security.mjs +2 -4
  508. package/dist/utils/path-security.mjs.map +1 -1
  509. package/dist/utils/public-origin.d.mts +0 -2
  510. package/dist/utils/public-origin.mjs +1 -2
  511. package/dist/utils/redact.d.mts +0 -2
  512. package/dist/utils/redact.mjs +1 -2
  513. package/dist/utils/remote-environment.d.mts +40 -3
  514. package/dist/utils/remote-environment.mjs +52 -3
  515. package/dist/utils/remote-environment.mjs.map +1 -1
  516. package/dist/utils/resources.d.mts +0 -2
  517. package/dist/utils/resources.mjs +1 -2
  518. package/dist/utils/screenshot-store.d.mts +0 -2
  519. package/dist/utils/screenshot-store.mjs +1 -2
  520. package/dist/utils/session-gate.d.mts +7 -6
  521. package/dist/utils/session-gate.mjs +28 -12
  522. package/dist/utils/session-gate.mjs.map +1 -1
  523. package/dist/utils/storybook-token.d.mts +11 -3
  524. package/dist/utils/storybook-token.mjs +10 -9
  525. package/dist/utils/storybook-token.mjs.map +1 -1
  526. package/dist/utils/storybook-url.d.mts +0 -2
  527. package/dist/utils/storybook-url.mjs +1 -2
  528. package/dist/utils/timing.d.mts +0 -2
  529. package/dist/utils/timing.mjs +1 -2
  530. package/dist/utils/ulid.d.mts +0 -2
  531. package/dist/utils/ulid.mjs +1 -2
  532. package/dist/utils/zip-read.mjs +1 -2
  533. package/dist/utils/zip-write.d.mts +0 -2
  534. package/dist/utils/zip-write.mjs +1 -2
  535. package/dist/utils.d.mts +5 -5
  536. package/dist/utils.mjs +5 -5
  537. package/package.json +6 -15
@@ -3,7 +3,7 @@ import "node:url";
3
3
  import.meta.url;
4
4
  import { REAL_TIMERS } from "../db-queue/timers.mjs";
5
5
  import { idleDelayMs, isFastEmptyPoll } from "./idle.mjs";
6
- //#region src/capture/consumer/loop.ts
6
+ // src/capture/consumer/loop.ts
7
7
  /** Pause after a failed poll. */
8
8
  const POLL_ERROR_DELAY_MS = 1e3;
9
9
  /** Start consuming `queue` with `slots` concurrent jobs. */
@@ -104,7 +104,6 @@ async function sleep(state, timers, ms) {
104
104
  await promise;
105
105
  if (handle !== null) clock.clearTimeout(handle);
106
106
  }
107
- //#endregion
108
107
  export { POLL_ERROR_DELAY_MS, startSlotLoop };
109
108
 
110
109
  //# sourceMappingURL=loop.mjs.map
@@ -3,7 +3,6 @@ import __tsdown_shims_url from 'node:url';
3
3
  import "../../logger.mjs";
4
4
  import { PollableCaptureQueue } from "../../adapter/capture-queue.mjs";
5
5
  import { CaptureJobKind } from "../../schema/capture-job.mjs";
6
- //#region src/capture/consumer/metrics.d.ts
7
6
  /** How a consumed job ended. */
8
7
  type JobOutcome = "completed" | "retried" | "failed" | "cancelled" | "lost" | "dropped" | "unhandled";
9
8
  /** A job the consumer finished with. */
@@ -36,6 +35,5 @@ interface ConsumerMetrics {
36
35
  declare const DEFAULT_SAMPLE_MS = 30000;
37
36
  /** Read the backlog of `queue` from its `active()` view. */
38
37
  declare function sampleQueue(queue: PollableCaptureQueue, now: number): Promise<QueueSample>;
39
- //#endregion
40
38
  export { ConsumerMetrics, DEFAULT_SAMPLE_MS, JobFinishedEvent, JobOutcome, QueueSample, sampleQueue };
41
39
  //# sourceMappingURL=metrics.d.mts.map
@@ -2,7 +2,7 @@ import "node:path";
2
2
  import "node:url";
3
3
  import.meta.url;
4
4
  import { repeatEvery } from "../db-queue/timers.mjs";
5
- //#region src/capture/consumer/metrics.ts
5
+ // src/capture/consumer/metrics.ts
6
6
  /** Default interval between queue samples. */
7
7
  const DEFAULT_SAMPLE_MS = 3e4;
8
8
  /** Read the backlog of `queue` from its `active()` view. */
@@ -32,7 +32,6 @@ function reportFinished(metrics, event) {
32
32
  metrics?.jobFinished?.(event);
33
33
  } catch {}
34
34
  }
35
- //#endregion
36
35
  export { DEFAULT_SAMPLE_MS, reportFinished, sampleQueue, startQueueSampling };
37
36
 
38
37
  //# sourceMappingURL=metrics.mjs.map
@@ -1,7 +1,6 @@
1
1
  import __tsdown_shims_path from 'node:path';
2
2
  import __tsdown_shims_url from 'node:url';
3
3
  import { PollableJob } from "../../adapter/capture-queue.mjs";
4
- //#region src/capture/consumer/retry.d.ts
5
4
  /** Retries after the first attempt before a job is failed for good (three attempts in total). */
6
5
  declare const DEFAULT_MAX_RETRIES = 2;
7
6
  /** Base of the exponential retry delay: the n-th retry waits `base * 2^n` ms. */
@@ -28,6 +27,5 @@ declare function isFinalAttempt(job: PollableJob & {
28
27
  attempt?: number;
29
28
  maxAttempts?: number;
30
29
  }, maxRetries?: number): boolean;
31
- //#endregion
32
30
  export { DEFAULT_BACKOFF_MS, DEFAULT_MAX_RETRIES, DEFAULT_WAIT_TIME_SECONDS, MAX_BACKOFF_MS, RetryConfig, backoffDelayMs, isFinalAttempt };
33
31
  //# sourceMappingURL=retry.d.mts.map
@@ -1,7 +1,7 @@
1
1
  import "node:path";
2
2
  import "node:url";
3
3
  import.meta.url;
4
- //#region src/capture/consumer/retry.ts
4
+ // src/capture/consumer/retry.ts
5
5
  /** Retries after the first attempt before a job is failed for good (three attempts in total). */
6
6
  const DEFAULT_MAX_RETRIES = 2;
7
7
  /** Base of the exponential retry delay: the n-th retry waits `base * 2^n` ms. */
@@ -28,7 +28,6 @@ function isFinalAttempt(job, maxRetries = 2) {
28
28
  function retriesOf(job, fallback = 2) {
29
29
  return typeof job.maxAttempts === "number" ? Math.max(0, job.maxAttempts - 1) : fallback;
30
30
  }
31
- //#endregion
32
31
  export { DEFAULT_BACKOFF_MS, DEFAULT_MAX_RETRIES, DEFAULT_WAIT_TIME_SECONDS, MAX_BACKOFF_MS, backoffDelayMs, isFinalAttempt, retriesOf };
33
32
 
34
33
  //# sourceMappingURL=retry.mjs.map
@@ -5,7 +5,7 @@ import { roundedTimings, runWithTimings } from "../../utils/timing.mjs";
5
5
  import { backoffDelayMs, isFinalAttempt } from "./retry.mjs";
6
6
  import { keepJobLease } from "../db-queue/keeper.mjs";
7
7
  import { reportFinished } from "./metrics.mjs";
8
- //#region src/capture/consumer/run-job.ts
8
+ // src/capture/consumer/run-job.ts
9
9
  /** Run `job` in the slot the caller holds; never rejects. */
10
10
  async function runJob(rt, job) {
11
11
  const kind = job.kind ?? "capture";
@@ -189,7 +189,6 @@ async function failJob(rt, job, message, logger) {
189
189
  await rt.queue.ack(job);
190
190
  }
191
191
  }
192
- //#endregion
193
192
  export { runJob };
194
193
 
195
194
  //# sourceMappingURL=run-job.mjs.map
@@ -3,7 +3,7 @@ import "node:url";
3
3
  import.meta.url;
4
4
  import { sweepOrphanedScratch } from "../scratch.mjs";
5
5
  import { configureImages, verifyImageEngine } from "../../diff.mjs";
6
- //#region src/capture/consumer/startup.ts
6
+ // src/capture/consumer/startup.ts
7
7
  /**
8
8
  * Only touch the process-wide image settings when asked, so a consumer created next to an app in
9
9
  * one process does not undo the app's own `images`/`compare` options.
@@ -32,7 +32,6 @@ async function sweepScratch(scratchDir, logger) {
32
32
  logger.warn({ err: error }, "scratch sweep failed");
33
33
  }
34
34
  }
35
- //#endregion
36
35
  export { applyImageSettings, ensureImageEngine, sweepScratch };
37
36
 
38
37
  //# sourceMappingURL=startup.mjs.map
@@ -9,7 +9,6 @@ import { QueueTimers } from "../db-queue/timers.mjs";
9
9
  import { CaptureHandlerOptions } from "./capture-handler.mjs";
10
10
  import { ConsumerMetrics } from "./metrics.mjs";
11
11
  import { RetryConfig } from "./retry.mjs";
12
- //#region src/capture/consumer/types.d.ts
13
12
  /** A polled job as the consumer sees it: database jobs carry the extra fields, others omit them. */
14
13
  type ConsumerJob = PollableJob & {
15
14
  /** Job kind; absent on queues that only carry capture jobs (remote, IPC). */
@@ -92,6 +91,5 @@ interface CaptureConsumer {
92
91
  stop(): Promise<void>;
93
92
  isRunning(): boolean;
94
93
  }
95
- //#endregion
96
94
  export { CaptureConsumer, CaptureConsumerOptions, ConsumerConfig, ConsumerJob, JobHandlers, JobRunContext, KindHandler };
97
95
  //# sourceMappingURL=types.d.mts.map
@@ -1,7 +1,6 @@
1
1
  import __tsdown_shims_path from 'node:path';
2
2
  import __tsdown_shims_url from 'node:url';
3
3
  import { DispatchDeps } from "./dispatch.mjs";
4
- //#region src/capture/crash-failure.d.ts
5
4
  /** What {@link failCrashedCapture} did. */
6
5
  type CrashFailureOutcome =
7
6
  /** The build was failed. */
@@ -20,6 +19,5 @@ declare function failCrashedCapture(deps: DispatchDeps, job: {
20
19
  buildId: string;
21
20
  shard?: string | undefined;
22
21
  }, error: string): Promise<CrashFailureOutcome>;
23
- //#endregion
24
22
  export { CrashFailureOutcome, failCrashedCapture };
25
23
  //# sourceMappingURL=crash-failure.d.mts.map
@@ -6,7 +6,7 @@ import { BuildModel } from "../models/build.mjs";
6
6
  import { CaptureShardModel } from "../models/capture-shard.mjs";
7
7
  import { ProjectModel } from "../models/project.mjs";
8
8
  import { reduceBuild } from "./shards/reduce.mjs";
9
- //#region src/capture/crash-failure.ts
9
+ // src/capture/crash-failure.ts
10
10
  /**
11
11
  * The terminal path for a capture job the forked parent gave up on because the child kept dying on
12
12
  * it (ADR 0005 phase 3). The child never got to record the failure, so the parent writes it: the
@@ -64,7 +64,6 @@ async function closeOpenAttempts(deps, buildId, error) {
64
64
  const open = (await attempts.listByBuild(buildId)).filter((attempt) => attempt.status === "queued" || attempt.status === "running");
65
65
  await Promise.all(open.map(async (attempt) => await attempts.markFinished(attempt.id, "failed", error)));
66
66
  }
67
- //#endregion
68
67
  export { failCrashedCapture };
69
68
 
70
69
  //# sourceMappingURL=crash-failure.mjs.map
@@ -1,6 +1,5 @@
1
1
  import __tsdown_shims_path from 'node:path';
2
2
  import __tsdown_shims_url from 'node:url';
3
- //#region src/capture/db-queue/cadence.d.ts
4
3
  /** Poll and cancel-check cadence of the database queue (ADR 0006, decision 11). */
5
4
  /** Poll interval of an idle instance. */
6
5
  declare const IDLE_POLL_MS = 15000;
@@ -27,6 +26,5 @@ declare const DEFAULT_CADENCE: PollCadence;
27
26
  * `[0, jitter)` of it, so instances started together drift apart instead of probing in lockstep.
28
27
  */
29
28
  declare function nextPollDelay(lastWorkAt: number | null, now: number, cadence?: PollCadence, random?: () => number): number;
30
- //#endregion
31
29
  export { ACTIVE_POLL_MS, ACTIVE_WINDOW_MS, CANCEL_CHECK_MS, DEFAULT_CADENCE, IDLE_POLL_MS, POLL_JITTER, PollCadence, nextPollDelay };
32
30
  //# sourceMappingURL=cadence.d.mts.map
@@ -1,7 +1,7 @@
1
1
  import "node:path";
2
2
  import "node:url";
3
3
  import.meta.url;
4
- //#region src/capture/db-queue/cadence.ts
4
+ // src/capture/db-queue/cadence.ts
5
5
  /** Poll and cancel-check cadence of the database queue (ADR 0006, decision 11). */
6
6
  /** Poll interval of an idle instance. */
7
7
  const IDLE_POLL_MS = 15e3;
@@ -32,7 +32,6 @@ function nextPollDelay(lastWorkAt, now, cadence = DEFAULT_CADENCE, random = Math
32
32
  function clampUnit(value) {
33
33
  return Math.min(Math.max(value, 0), .999999);
34
34
  }
35
- //#endregion
36
35
  export { ACTIVE_POLL_MS, ACTIVE_WINDOW_MS, CANCEL_CHECK_MS, DEFAULT_CADENCE, IDLE_POLL_MS, POLL_JITTER, nextPollDelay };
37
36
 
38
37
  //# sourceMappingURL=cadence.mjs.map
@@ -1,9 +1,7 @@
1
1
  import __tsdown_shims_path from 'node:path';
2
2
  import __tsdown_shims_url from 'node:url';
3
3
  import "./types.mjs";
4
- //#region src/capture/db-queue/claim.d.ts
5
4
  /** Error recorded on a job whose last allowed attempt lost its lease. */
6
5
  declare const LEASE_EXHAUSTED_ERROR = "lease expired on the final attempt";
7
- //#endregion
8
6
  export { LEASE_EXHAUSTED_ERROR };
9
7
  //# sourceMappingURL=claim.d.mts.map
@@ -4,7 +4,7 @@ import.meta.url;
4
4
  import { attemptRowId, isTerminalJob } from "../../models/capture-job.mjs";
5
5
  import { toDatabaseJob } from "./codec.mjs";
6
6
  import { isoAt } from "./clock.mjs";
7
- //#region src/capture/db-queue/claim.ts
7
+ // src/capture/db-queue/claim.ts
8
8
  /**
9
9
  * The claim algorithm of the database queue. A poll probes for the oldest candidate row (a queued
10
10
  * job whose `visibleAt` passed, or a running attempt whose lease ran out), then claims the job's
@@ -114,19 +114,35 @@ async function exhaust(rt, job, stale) {
114
114
  }, "job failed: lease exhausted");
115
115
  await reportExhausted(rt, job);
116
116
  }
117
+ /** Sleep for `ms`, using injected timers when available. */
118
+ async function sleep(rt, ms) {
119
+ if (rt.timers === void 0) {
120
+ await new Promise((resolve) => {
121
+ setTimeout(resolve, ms);
122
+ });
123
+ return;
124
+ }
125
+ await new Promise((resolve) => {
126
+ rt.timers?.setTimeout(resolve, ms);
127
+ });
128
+ }
117
129
  /** Tell the host a job ended without any holder to record it; its failure never blocks the poll. */
118
130
  async function reportExhausted(rt, job) {
119
131
  if (rt.onExhausted === void 0) return;
120
- try {
132
+ const attempts = 3;
133
+ for (let attempt = 1; attempt <= attempts; attempt += 1) try {
121
134
  await rt.onExhausted(toDatabaseJob(job, job.attempt, rt.leaseMs), LEASE_EXHAUSTED_ERROR);
135
+ return;
122
136
  } catch (error) {
123
137
  rt.logger?.error({
124
138
  err: error,
125
- jobId: job.jobId
139
+ jobId: job.jobId,
140
+ attempt,
141
+ attempts
126
142
  }, "exhausted-job hook failed");
143
+ if (attempt < attempts) await sleep(rt, 100 * attempt);
127
144
  }
128
145
  }
129
- //#endregion
130
146
  export { LEASE_EXHAUSTED_ERROR, claimCandidate, claimNext };
131
147
 
132
148
  //# sourceMappingURL=claim.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"claim.mjs","names":[],"sources":["../../../src/capture/db-queue/claim.ts"],"sourcesContent":["/**\n * The claim algorithm of the database queue. A poll probes for the oldest candidate row (a queued\n * job whose `visibleAt` passed, or a running attempt whose lease ran out), then claims the job's\n * next attempt by inserting its row: the unique key lets exactly one instance win. The winner\n * retires the expired attempt it replaced and marks the job row running.\n */\nimport { attemptRowId, isTerminalJob } from \"../../models/capture-job.ts\";\nimport type { CaptureJobRow } from \"../../schema/capture-job.ts\";\nimport { isoAt } from \"./clock.ts\";\nimport { toDatabaseJob } from \"./codec.ts\";\nimport type { DatabaseJob, QueueRuntime } from \"./types.ts\";\n\n/** Candidates tried per poll when other instances win the race for them. */\nconst MAX_CLAIM_TRIES = 3;\n\n/** Error recorded on a job whose last allowed attempt lost its lease. */\nexport const LEASE_EXHAUSTED_ERROR = \"lease expired on the final attempt\";\n\n/** Probe once and claim the job found; on a lost race, try the next candidate (a few times). */\nexport async function claimNext(rt: QueueRuntime): Promise<DatabaseJob | null> {\n for (let tries = 0; tries < MAX_CLAIM_TRIES; tries += 1) {\n // oxlint-disable-next-line no-await-in-loop -- one candidate at a time, in order\n const candidate = await rt.model.nextCandidate(rt.kinds, isoAt(rt));\n if (candidate === null) {\n return null;\n }\n // oxlint-disable-next-line no-await-in-loop -- see above\n const job = await claimCandidate(rt, candidate);\n if (job !== null) {\n return job;\n }\n }\n return null;\n}\n\n/** Claim the job behind a candidate row; null when it is gone, over, exhausted or lost to a race. */\nexport async function claimCandidate(\n rt: QueueRuntime,\n candidate: CaptureJobRow,\n): Promise<DatabaseJob | null> {\n if (candidate.entry === \"job\" && candidate.status !== \"queued\") {\n // A running job row put back in range by a late deferral (see `deferBehind`): not claimable.\n await rt.model.clearVisibility(candidate.id, isoAt(rt));\n return null;\n }\n const stale = candidate.entry === \"attempt\" ? candidate : null;\n const job = stale === null ? candidate : await rt.model.get(candidate.jobId);\n if (job === null || isTerminalJob(job) || (stale !== null && stale.attempt < job.attempt)) {\n // Nothing left to claim: the expired attempt is just cleaned out of the poll's range.\n await retire(rt, stale);\n return null;\n }\n return await claimNextAttempt(rt, job, stale);\n}\n\n/** Claim the attempt after the last one made, or fail the job when none is left. */\nasync function claimNextAttempt(\n rt: QueueRuntime,\n job: CaptureJobRow,\n stale: CaptureJobRow | null,\n): Promise<DatabaseJob | null> {\n // An attempt row ahead of its job row belongs to a claimer that died before marking the job.\n const made = Math.max(job.attempt, stale?.attempt ?? 0);\n if (made >= job.maxAttempts) {\n await exhaust(rt, job, stale);\n return null;\n }\n return await claimAttempt(rt, job, made + 1, stale);\n}\n\nasync function claimAttempt(\n rt: QueueRuntime,\n job: CaptureJobRow,\n attempt: number,\n stale: CaptureJobRow | null,\n): Promise<DatabaseJob | null> {\n const leaseUntil = isoAt(rt, rt.leaseMs);\n const won = await rt.model.claim({ job, attempt, owner: rt.owner, leaseUntil }, isoAt(rt));\n if (!won) {\n return stale === null ? await afterLostRace(rt, job, attempt) : null;\n }\n const fresh = await rt.model.get(job.jobId);\n if (fresh === null || isTerminalJob(fresh)) {\n // Cancelled (or finished by a late holder) between the probe and the insert.\n await rt.model.finishAttempt(attemptRowId(job.jobId, attempt), \"expired\", isoAt(rt));\n return null;\n }\n return await takeOver(rt, fresh, attempt, stale);\n}\n\n/**\n * Another instance holds attempt `attempt` of a job whose row still reads queued. Usually that\n * winner is about to mark the job running. If it died before doing so, its attempt's lease decides:\n * once expired, the attempt is claimed like any expired one; until then the job row is moved\n * behind that lease, so it does not sit at the head of the queue losing every claim. Only\n * `visibleAt` is written, never the status, so a winner that finished meanwhile keeps its outcome.\n */\nasync function afterLostRace(\n rt: QueueRuntime,\n job: CaptureJobRow,\n attempt: number,\n): Promise<DatabaseJob | null> {\n const id = attemptRowId(job.jobId, attempt);\n const expired = await rt.model.expiredAttempt(id, isoAt(rt));\n if (expired !== null) {\n return await claimCandidate(rt, expired);\n }\n await deferBehind(rt, job, await rt.model.get(id));\n return null;\n}\n\nasync function deferBehind(\n rt: QueueRuntime,\n job: CaptureJobRow,\n holder: CaptureJobRow | null,\n): Promise<void> {\n const current = await rt.model.get(job.jobId);\n if (holder?.visibleAt && current?.status === \"queued\" && current.attempt === job.attempt) {\n await rt.model.defer(job.jobId, holder.visibleAt, isoAt(rt));\n }\n}\n\n/** The claim won: retire the attempt it replaced and record the new one on the job row. */\nasync function takeOver(\n rt: QueueRuntime,\n job: CaptureJobRow,\n attempt: number,\n stale: CaptureJobRow | null,\n): Promise<DatabaseJob> {\n await retire(rt, stale);\n await rt.model.markRunning(job.jobId, attempt, isoAt(rt));\n rt.logger?.debug({ jobId: job.jobId, attempt }, \"job claimed\");\n return toDatabaseJob(job, attempt, rt.leaseMs);\n}\n\n/** Mark an expired attempt row `expired`: it leaves the poll's range, and its holder sees `lost`. */\nasync function retire(rt: QueueRuntime, stale: CaptureJobRow | null): Promise<void> {\n if (stale !== null) {\n await rt.model.finishAttempt(stale.id, \"expired\", isoAt(rt));\n }\n}\n\n/**\n * The final attempt lost its lease: the job fails (one limit covers failed attempts and lost\n * leases). Idempotent, so two instances finding the same row write the same outcome. If the late\n * holder finished after all, its `done` wins.\n */\nasync function exhaust(\n rt: QueueRuntime,\n job: CaptureJobRow,\n stale: CaptureJobRow | null,\n): Promise<void> {\n const now = isoAt(rt);\n if (stale !== null && (await rt.model.get(stale.id))?.status === \"done\") {\n await rt.model.finishJob(job.jobId, \"done\", now);\n return;\n }\n await retire(rt, stale);\n await rt.model.finishJob(job.jobId, \"failed\", now, LEASE_EXHAUSTED_ERROR);\n rt.logger?.warn({ jobId: job.jobId, attempts: job.attempt }, \"job failed: lease exhausted\");\n await reportExhausted(rt, job);\n}\n\n/** Tell the host a job ended without any holder to record it; its failure never blocks the poll. */\nasync function reportExhausted(rt: QueueRuntime, job: CaptureJobRow): Promise<void> {\n if (rt.onExhausted === undefined) {\n return;\n }\n try {\n await rt.onExhausted(toDatabaseJob(job, job.attempt, rt.leaseMs), LEASE_EXHAUSTED_ERROR);\n } catch (error) {\n rt.logger?.error({ err: error, jobId: job.jobId }, \"exhausted-job hook failed\");\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"claim.mjs","names":[],"sources":["../../../src/capture/db-queue/claim.ts"],"sourcesContent":["/**\n * The claim algorithm of the database queue. A poll probes for the oldest candidate row (a queued\n * job whose `visibleAt` passed, or a running attempt whose lease ran out), then claims the job's\n * next attempt by inserting its row: the unique key lets exactly one instance win. The winner\n * retires the expired attempt it replaced and marks the job row running.\n */\nimport { attemptRowId, isTerminalJob } from \"../../models/capture-job.ts\";\nimport type { CaptureJobRow } from \"../../schema/capture-job.ts\";\nimport { isoAt } from \"./clock.ts\";\nimport { toDatabaseJob } from \"./codec.ts\";\nimport type { DatabaseJob, QueueRuntime } from \"./types.ts\";\n\n/** Candidates tried per poll when other instances win the race for them. */\nconst MAX_CLAIM_TRIES = 3;\n\n/** Error recorded on a job whose last allowed attempt lost its lease. */\nexport const LEASE_EXHAUSTED_ERROR = \"lease expired on the final attempt\";\n\n/** Probe once and claim the job found; on a lost race, try the next candidate (a few times). */\nexport async function claimNext(rt: QueueRuntime): Promise<DatabaseJob | null> {\n for (let tries = 0; tries < MAX_CLAIM_TRIES; tries += 1) {\n // oxlint-disable-next-line no-await-in-loop -- one candidate at a time, in order\n const candidate = await rt.model.nextCandidate(rt.kinds, isoAt(rt));\n if (candidate === null) {\n return null;\n }\n // oxlint-disable-next-line no-await-in-loop -- see above\n const job = await claimCandidate(rt, candidate);\n if (job !== null) {\n return job;\n }\n }\n return null;\n}\n\n/** Claim the job behind a candidate row; null when it is gone, over, exhausted or lost to a race. */\nexport async function claimCandidate(\n rt: QueueRuntime,\n candidate: CaptureJobRow,\n): Promise<DatabaseJob | null> {\n if (candidate.entry === \"job\" && candidate.status !== \"queued\") {\n // A running job row put back in range by a late deferral (see `deferBehind`): not claimable.\n await rt.model.clearVisibility(candidate.id, isoAt(rt));\n return null;\n }\n const stale = candidate.entry === \"attempt\" ? candidate : null;\n const job = stale === null ? candidate : await rt.model.get(candidate.jobId);\n if (job === null || isTerminalJob(job) || (stale !== null && stale.attempt < job.attempt)) {\n // Nothing left to claim: the expired attempt is just cleaned out of the poll's range.\n await retire(rt, stale);\n return null;\n }\n return await claimNextAttempt(rt, job, stale);\n}\n\n/** Claim the attempt after the last one made, or fail the job when none is left. */\nasync function claimNextAttempt(\n rt: QueueRuntime,\n job: CaptureJobRow,\n stale: CaptureJobRow | null,\n): Promise<DatabaseJob | null> {\n // An attempt row ahead of its job row belongs to a claimer that died before marking the job.\n const made = Math.max(job.attempt, stale?.attempt ?? 0);\n if (made >= job.maxAttempts) {\n await exhaust(rt, job, stale);\n return null;\n }\n return await claimAttempt(rt, job, made + 1, stale);\n}\n\nasync function claimAttempt(\n rt: QueueRuntime,\n job: CaptureJobRow,\n attempt: number,\n stale: CaptureJobRow | null,\n): Promise<DatabaseJob | null> {\n const leaseUntil = isoAt(rt, rt.leaseMs);\n const won = await rt.model.claim({ job, attempt, owner: rt.owner, leaseUntil }, isoAt(rt));\n if (!won) {\n return stale === null ? await afterLostRace(rt, job, attempt) : null;\n }\n const fresh = await rt.model.get(job.jobId);\n if (fresh === null || isTerminalJob(fresh)) {\n // Cancelled (or finished by a late holder) between the probe and the insert.\n await rt.model.finishAttempt(attemptRowId(job.jobId, attempt), \"expired\", isoAt(rt));\n return null;\n }\n return await takeOver(rt, fresh, attempt, stale);\n}\n\n/**\n * Another instance holds attempt `attempt` of a job whose row still reads queued. Usually that\n * winner is about to mark the job running. If it died before doing so, its attempt's lease decides:\n * once expired, the attempt is claimed like any expired one; until then the job row is moved\n * behind that lease, so it does not sit at the head of the queue losing every claim. Only\n * `visibleAt` is written, never the status, so a winner that finished meanwhile keeps its outcome.\n */\nasync function afterLostRace(\n rt: QueueRuntime,\n job: CaptureJobRow,\n attempt: number,\n): Promise<DatabaseJob | null> {\n const id = attemptRowId(job.jobId, attempt);\n const expired = await rt.model.expiredAttempt(id, isoAt(rt));\n if (expired !== null) {\n return await claimCandidate(rt, expired);\n }\n await deferBehind(rt, job, await rt.model.get(id));\n return null;\n}\n\nasync function deferBehind(\n rt: QueueRuntime,\n job: CaptureJobRow,\n holder: CaptureJobRow | null,\n): Promise<void> {\n const current = await rt.model.get(job.jobId);\n if (holder?.visibleAt && current?.status === \"queued\" && current.attempt === job.attempt) {\n await rt.model.defer(job.jobId, holder.visibleAt, isoAt(rt));\n }\n}\n\n/** The claim won: retire the attempt it replaced and record the new one on the job row. */\nasync function takeOver(\n rt: QueueRuntime,\n job: CaptureJobRow,\n attempt: number,\n stale: CaptureJobRow | null,\n): Promise<DatabaseJob> {\n await retire(rt, stale);\n await rt.model.markRunning(job.jobId, attempt, isoAt(rt));\n rt.logger?.debug({ jobId: job.jobId, attempt }, \"job claimed\");\n return toDatabaseJob(job, attempt, rt.leaseMs);\n}\n\n/** Mark an expired attempt row `expired`: it leaves the poll's range, and its holder sees `lost`. */\nasync function retire(rt: QueueRuntime, stale: CaptureJobRow | null): Promise<void> {\n if (stale !== null) {\n await rt.model.finishAttempt(stale.id, \"expired\", isoAt(rt));\n }\n}\n\n/**\n * The final attempt lost its lease: the job fails (one limit covers failed attempts and lost\n * leases). Idempotent, so two instances finding the same row write the same outcome. If the late\n * holder finished after all, its `done` wins.\n */\nasync function exhaust(\n rt: QueueRuntime,\n job: CaptureJobRow,\n stale: CaptureJobRow | null,\n): Promise<void> {\n const now = isoAt(rt);\n if (stale !== null && (await rt.model.get(stale.id))?.status === \"done\") {\n await rt.model.finishJob(job.jobId, \"done\", now);\n return;\n }\n await retire(rt, stale);\n await rt.model.finishJob(job.jobId, \"failed\", now, LEASE_EXHAUSTED_ERROR);\n rt.logger?.warn({ jobId: job.jobId, attempts: job.attempt }, \"job failed: lease exhausted\");\n await reportExhausted(rt, job);\n}\n\n/** Sleep for `ms`, using injected timers when available. */\nasync function sleep(rt: QueueRuntime, ms: number): Promise<void> {\n if (rt.timers === undefined) {\n await new Promise<void>((resolve) => {\n setTimeout(resolve, ms);\n });\n return;\n }\n await new Promise<void>((resolve) => {\n rt.timers?.setTimeout(resolve, ms);\n });\n}\n\n/** Tell the host a job ended without any holder to record it; its failure never blocks the poll. */\nasync function reportExhausted(rt: QueueRuntime, job: CaptureJobRow): Promise<void> {\n if (rt.onExhausted === undefined) {\n return;\n }\n const attempts = 3;\n for (let attempt = 1; attempt <= attempts; attempt += 1) {\n try {\n // oxlint-disable-next-line eslint/no-await-in-loop -- sequential retries\n await rt.onExhausted(toDatabaseJob(job, job.attempt, rt.leaseMs), LEASE_EXHAUSTED_ERROR);\n return;\n } catch (error) {\n rt.logger?.error(\n { err: error, jobId: job.jobId, attempt, attempts },\n \"exhausted-job hook failed\",\n );\n if (attempt < attempts) {\n // oxlint-disable-next-line eslint/no-await-in-loop -- sequential retries\n await sleep(rt, 100 * attempt);\n }\n }\n }\n}\n"],"mappings":"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"}
@@ -1,12 +1,11 @@
1
1
  import "node:path";
2
2
  import "node:url";
3
3
  import.meta.url;
4
- //#region src/capture/db-queue/clock.ts
4
+ // src/capture/db-queue/clock.ts
5
5
  /** ISO-8601 time `plusMs` from now on the queue's clock. */
6
6
  function isoAt(rt, plusMs = 0) {
7
7
  return new Date(rt.now() + plusMs).toISOString();
8
8
  }
9
- //#endregion
10
9
  export { isoAt };
11
10
 
12
11
  //# sourceMappingURL=clock.mjs.map
@@ -2,7 +2,7 @@ import "node:path";
2
2
  import "node:url";
3
3
  import.meta.url;
4
4
  import { attemptRowId } from "../../models/capture-job.mjs";
5
- //#region src/capture/db-queue/codec.ts
5
+ // src/capture/db-queue/codec.ts
6
6
  /** Serialize the request id, trace context and kind-specific fields of a job; null when empty. */
7
7
  function encodePayload(job) {
8
8
  const stored = {};
@@ -70,7 +70,6 @@ function pickPayload(parsed) {
70
70
  function isRecord(value) {
71
71
  return typeof value === "object" && value !== null && !Array.isArray(value);
72
72
  }
73
- //#endregion
74
73
  export { decodePayload, encodePayload, toDatabaseJob, toQueueEntry };
75
74
 
76
75
  //# sourceMappingURL=codec.mjs.map
@@ -4,7 +4,6 @@ import { DatabaseAdapter } from "../../adapter/database.mjs";
4
4
  import { DEFAULT_LEASE_MS, DEFAULT_RETRIES, DatabaseCaptureQueue, DatabaseCaptureQueueOptions, DatabaseJob, QueueJobInput } from "./types.mjs";
5
5
  import { LEASE_EXHAUSTED_ERROR } from "./claim.mjs";
6
6
  import { MAX_NACK_DELAY_MS } from "./poll.mjs";
7
- //#region src/capture/db-queue/index.d.ts
8
7
  /** What the database queue reports about itself; hosts show it before the queue is built. */
9
8
  declare const DATABASE_QUEUE_METADATA: {
10
9
  readonly name: "Database Queue";
@@ -15,6 +14,5 @@ declare const DATABASE_QUEUE_METADATA: {
15
14
  };
16
15
  /** A `PollableCaptureQueue` over `db`'s `capture_jobs` table. */
17
16
  declare function createDatabaseCaptureQueue(db: DatabaseAdapter, options?: DatabaseCaptureQueueOptions): DatabaseCaptureQueue;
18
- //#endregion
19
17
  export { DATABASE_QUEUE_METADATA, DEFAULT_LEASE_MS, DEFAULT_RETRIES, type DatabaseCaptureQueue, type DatabaseCaptureQueueOptions, type DatabaseJob, LEASE_EXHAUSTED_ERROR, MAX_NACK_DELAY_MS, type QueueJobInput, createDatabaseCaptureQueue };
20
18
  //# sourceMappingURL=index.d.mts.map
@@ -11,7 +11,7 @@ import { activeEntries, cancelJobs, enqueueCapture, enqueueJob, recentEntries, s
11
11
  import { DEFAULT_LEASE_MS, DEFAULT_RETRIES } from "./types.mjs";
12
12
  import { createWakeSignal } from "./wake.mjs";
13
13
  import { hostname } from "node:os";
14
- //#region src/capture/db-queue/index.ts
14
+ // src/capture/db-queue/index.ts
15
15
  /**
16
16
  * Create the database capture queue (ADR 0006, decision 4): `capture_jobs` on the app's own
17
17
  * `DatabaseAdapter` is the queue, safe with any number of instances.
@@ -24,7 +24,7 @@ import { hostname } from "node:os";
24
24
  /** What the database queue reports about itself; hosts show it before the queue is built. */
25
25
  const DATABASE_QUEUE_METADATA = {
26
26
  name: "Database Queue",
27
- version: "0.7.0",
27
+ version: "0.9.0-next-d2cc082",
28
28
  description: "Capture queue on the app database (capture_jobs)",
29
29
  kind: "database",
30
30
  category: "capture-queue"
@@ -70,6 +70,7 @@ function resolveRuntime(db, options) {
70
70
  maxAttempts: retries + 1,
71
71
  owner: options.owner ?? `${hostname()}:${String(process.pid)}:${ulid().slice(-6)}`,
72
72
  now: options.now ?? Date.now,
73
+ timers: options.timers,
73
74
  wake: createWakeSignal(options.timers),
74
75
  pollVersion: 0
75
76
  }, options);
@@ -83,7 +84,6 @@ function withHooks(rt, options) {
83
84
  function positive(value, fallback) {
84
85
  return value !== void 0 && Number.isFinite(value) && value > 0 ? value : fallback;
85
86
  }
86
- //#endregion
87
87
  export { DATABASE_QUEUE_METADATA, DEFAULT_LEASE_MS, DEFAULT_RETRIES, LEASE_EXHAUSTED_ERROR, MAX_NACK_DELAY_MS, createDatabaseCaptureQueue };
88
88
 
89
89
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../../src/capture/db-queue/index.ts"],"sourcesContent":["/**\n * Create the database capture queue (ADR 0006, decision 4): `capture_jobs` on the app's own\n * `DatabaseAdapter` is the queue, safe with any number of instances.\n *\n * Composition root: wires the runtime, lifecycle, enqueue/cancel/views (`operations`), the claim\n * (`claim`, `poll`) and the lease (`lease`) into a `PollableCaptureQueue`. Every attempt has its own\n * row `<jobId>:<attempt>`, created by a unique-key insert, so claiming needs no compare-and-swap and\n * a holder only ever writes its own attempt row.\n */\nimport { hostname } from \"node:os\";\nimport type { DatabaseAdapter } from \"../../adapters/database.ts\";\nimport type { Logger } from \"../../logger.ts\";\nimport { CaptureJobModel } from \"../../models/capture-job.ts\";\nimport { ulid } from \"../../utils/ulid.ts\";\nimport { extendJob, inspectJob } from \"./lease.ts\";\nimport { buildQueueLifecycle } from \"./lifecycle.ts\";\nimport {\n activeEntries,\n cancelJobs,\n enqueueCapture,\n enqueueJob,\n recentEntries,\n statusOf,\n} from \"./operations.ts\";\nimport { ackJob, nackJob, pollJob } from \"./poll.ts\";\nimport {\n DEFAULT_LEASE_MS,\n DEFAULT_RETRIES,\n type DatabaseCaptureQueue,\n type DatabaseCaptureQueueOptions,\n type QueueRuntime,\n} from \"./types.ts\";\nimport { createWakeSignal } from \"./wake.ts\";\n\ndeclare const __PKG_VERSION__: string | undefined;\n\n/** What the database queue reports about itself; hosts show it before the queue is built. */\nexport const DATABASE_QUEUE_METADATA = {\n name: \"Database Queue\",\n version: typeof __PKG_VERSION__ === \"string\" ? __PKG_VERSION__ : \"0.0.0\",\n description: \"Capture queue on the app database (capture_jobs)\",\n kind: \"database\",\n category: \"capture-queue\",\n} as const;\n\n/** A `PollableCaptureQueue` over `db`'s `capture_jobs` table. */\nexport function createDatabaseCaptureQueue(\n db: DatabaseAdapter,\n options: DatabaseCaptureQueueOptions = {},\n): DatabaseCaptureQueue {\n const rt = resolveRuntime(db, options);\n return {\n metadata: DATABASE_QUEUE_METADATA,\n lifecycle: buildQueueLifecycle(rt),\n setLogger(bound: Logger): void {\n rt.logger ??= bound;\n },\n enqueue: async (job) => {\n await enqueueCapture(rt, job);\n },\n enqueueJob: async (job) => await enqueueJob(rt, job),\n status: async (buildId) => await statusOf(rt, buildId),\n active: async () => await activeEntries(rt),\n recent: async (limit) => await recentEntries(rt, limit),\n cancel: async (id) => await cancelJobs(rt, id),\n poll: async (pollOptions) => await pollJob(rt, pollOptions),\n ack: async (job) => {\n await ackJob(rt, job);\n },\n nack: async (job, nackOptions) => {\n await nackJob(rt, job, nackOptions);\n },\n extend: async (job) => await extendJob(rt, job),\n inspect: async (job) => await inspectJob(rt, job),\n waitForWork: async (ms) => await rt.wake.wait(ms, rt.pollVersion),\n };\n}\n\nfunction resolveRuntime(db: DatabaseAdapter, options: DatabaseCaptureQueueOptions): QueueRuntime {\n const kinds = options.kinds ?? [\"capture\"];\n const retries = options.retries ?? DEFAULT_RETRIES;\n if (kinds.length === 0) {\n throw new Error(\"createDatabaseCaptureQueue: `kinds` must name at least one job kind\");\n }\n if (!Number.isInteger(retries) || retries < 0) {\n throw new Error(\"createDatabaseCaptureQueue: `retries` must be a non-negative integer\");\n }\n const rt: QueueRuntime = {\n model: new CaptureJobModel(db),\n kinds,\n leaseMs: positive(options.leaseMs, DEFAULT_LEASE_MS),\n maxAttempts: retries + 1,\n owner: options.owner ?? `${hostname()}:${String(process.pid)}:${ulid().slice(-6)}`,\n now: options.now ?? Date.now,\n wake: createWakeSignal(options.timers),\n pollVersion: 0,\n };\n return withHooks(rt, options);\n}\n\n/** The optional logger and exhausted-job hook, when given. */\nfunction withHooks(rt: QueueRuntime, options: DatabaseCaptureQueueOptions): QueueRuntime {\n if (options.logger !== undefined) {\n rt.logger = options.logger;\n }\n if (options.onExhausted !== undefined) {\n rt.onExhausted = options.onExhausted;\n }\n return rt;\n}\n\nfunction positive(value: number | undefined, fallback: number): number {\n return value !== undefined && Number.isFinite(value) && value > 0 ? value : fallback;\n}\n\nexport {\n DEFAULT_LEASE_MS,\n DEFAULT_RETRIES,\n type DatabaseCaptureQueue,\n type DatabaseCaptureQueueOptions,\n type DatabaseJob,\n type QueueJobInput,\n} from \"./types.ts\";\nexport { LEASE_EXHAUSTED_ERROR } from \"./claim.ts\";\nexport { MAX_NACK_DELAY_MS } from \"./poll.ts\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAqCA,MAAa,0BAA0B;CACrC,MAAM;CACN,SAAA;CACA,aAAa;CACb,MAAM;CACN,UAAU;AACZ;;AAGA,SAAgB,2BACd,IACA,UAAuC,CAAC,GAClB;CACtB,MAAM,KAAK,eAAe,IAAI,OAAO;CACrC,OAAO;EACL,UAAU;EACV,WAAW,oBAAoB,EAAE;EACjC,UAAU,OAAqB;GAC7B,GAAG,WAAW;EAChB;EACA,SAAS,OAAO,QAAQ;GACtB,MAAM,eAAe,IAAI,GAAG;EAC9B;EACA,YAAY,OAAO,QAAQ,MAAM,WAAW,IAAI,GAAG;EACnD,QAAQ,OAAO,YAAY,MAAM,SAAS,IAAI,OAAO;EACrD,QAAQ,YAAY,MAAM,cAAc,EAAE;EAC1C,QAAQ,OAAO,UAAU,MAAM,cAAc,IAAI,KAAK;EACtD,QAAQ,OAAO,OAAO,MAAM,WAAW,IAAI,EAAE;EAC7C,MAAM,OAAO,gBAAgB,MAAM,QAAQ,IAAI,WAAW;EAC1D,KAAK,OAAO,QAAQ;GAClB,MAAM,OAAO,IAAI,GAAG;EACtB;EACA,MAAM,OAAO,KAAK,gBAAgB;GAChC,MAAM,QAAQ,IAAI,KAAK,WAAW;EACpC;EACA,QAAQ,OAAO,QAAQ,MAAM,UAAU,IAAI,GAAG;EAC9C,SAAS,OAAO,QAAQ,MAAM,WAAW,IAAI,GAAG;EAChD,aAAa,OAAO,OAAO,MAAM,GAAG,KAAK,KAAK,IAAI,GAAG,WAAW;CAClE;AACF;AAEA,SAAS,eAAe,IAAqB,SAAoD;CAC/F,MAAM,QAAQ,QAAQ,SAAS,CAAC,SAAS;CACzC,MAAM,UAAU,QAAQ,WAAA;CACxB,IAAI,MAAM,WAAW,GACnB,MAAM,IAAI,MAAM,qEAAqE;CAEvF,IAAI,CAAC,OAAO,UAAU,OAAO,KAAK,UAAU,GAC1C,MAAM,IAAI,MAAM,sEAAsE;CAYxF,OAAO,UAAU;EATf,OAAO,IAAI,gBAAgB,EAAE;EAC7B;EACA,SAAS,SAAS,QAAQ,SAAS,gBAAgB;EACnD,aAAa,UAAU;EACvB,OAAO,QAAQ,SAAS,GAAG,SAAS,EAAE,GAAG,OAAO,QAAQ,GAAG,EAAE,GAAG,KAAK,CAAC,CAAC,MAAM,EAAE;EAC/E,KAAK,QAAQ,OAAO,KAAK;EACzB,MAAM,iBAAiB,QAAQ,MAAM;EACrC,aAAa;CAEG,GAAG,OAAO;AAC9B;;AAGA,SAAS,UAAU,IAAkB,SAAoD;CACvF,IAAI,QAAQ,WAAW,KAAA,GACrB,GAAG,SAAS,QAAQ;CAEtB,IAAI,QAAQ,gBAAgB,KAAA,GAC1B,GAAG,cAAc,QAAQ;CAE3B,OAAO;AACT;AAEA,SAAS,SAAS,OAA2B,UAA0B;CACrE,OAAO,UAAU,KAAA,KAAa,OAAO,SAAS,KAAK,KAAK,QAAQ,IAAI,QAAQ;AAC9E"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../../src/capture/db-queue/index.ts"],"sourcesContent":["/**\n * Create the database capture queue (ADR 0006, decision 4): `capture_jobs` on the app's own\n * `DatabaseAdapter` is the queue, safe with any number of instances.\n *\n * Composition root: wires the runtime, lifecycle, enqueue/cancel/views (`operations`), the claim\n * (`claim`, `poll`) and the lease (`lease`) into a `PollableCaptureQueue`. Every attempt has its own\n * row `<jobId>:<attempt>`, created by a unique-key insert, so claiming needs no compare-and-swap and\n * a holder only ever writes its own attempt row.\n */\nimport { hostname } from \"node:os\";\nimport type { DatabaseAdapter } from \"../../adapters/database.ts\";\nimport type { Logger } from \"../../logger.ts\";\nimport { CaptureJobModel } from \"../../models/capture-job.ts\";\nimport { ulid } from \"../../utils/ulid.ts\";\nimport { extendJob, inspectJob } from \"./lease.ts\";\nimport { buildQueueLifecycle } from \"./lifecycle.ts\";\nimport {\n activeEntries,\n cancelJobs,\n enqueueCapture,\n enqueueJob,\n recentEntries,\n statusOf,\n} from \"./operations.ts\";\nimport { ackJob, nackJob, pollJob } from \"./poll.ts\";\nimport {\n DEFAULT_LEASE_MS,\n DEFAULT_RETRIES,\n type DatabaseCaptureQueue,\n type DatabaseCaptureQueueOptions,\n type QueueRuntime,\n} from \"./types.ts\";\nimport { createWakeSignal } from \"./wake.ts\";\n\ndeclare const __PKG_VERSION__: string | undefined;\n\n/** What the database queue reports about itself; hosts show it before the queue is built. */\nexport const DATABASE_QUEUE_METADATA = {\n name: \"Database Queue\",\n version: typeof __PKG_VERSION__ === \"string\" ? __PKG_VERSION__ : \"0.0.0\",\n description: \"Capture queue on the app database (capture_jobs)\",\n kind: \"database\",\n category: \"capture-queue\",\n} as const;\n\n/** A `PollableCaptureQueue` over `db`'s `capture_jobs` table. */\nexport function createDatabaseCaptureQueue(\n db: DatabaseAdapter,\n options: DatabaseCaptureQueueOptions = {},\n): DatabaseCaptureQueue {\n const rt = resolveRuntime(db, options);\n return {\n metadata: DATABASE_QUEUE_METADATA,\n lifecycle: buildQueueLifecycle(rt),\n setLogger(bound: Logger): void {\n rt.logger ??= bound;\n },\n enqueue: async (job) => {\n await enqueueCapture(rt, job);\n },\n enqueueJob: async (job) => await enqueueJob(rt, job),\n status: async (buildId) => await statusOf(rt, buildId),\n active: async () => await activeEntries(rt),\n recent: async (limit) => await recentEntries(rt, limit),\n cancel: async (id) => await cancelJobs(rt, id),\n poll: async (pollOptions) => await pollJob(rt, pollOptions),\n ack: async (job) => {\n await ackJob(rt, job);\n },\n nack: async (job, nackOptions) => {\n await nackJob(rt, job, nackOptions);\n },\n extend: async (job) => await extendJob(rt, job),\n inspect: async (job) => await inspectJob(rt, job),\n waitForWork: async (ms) => await rt.wake.wait(ms, rt.pollVersion),\n };\n}\n\nfunction resolveRuntime(db: DatabaseAdapter, options: DatabaseCaptureQueueOptions): QueueRuntime {\n const kinds = options.kinds ?? [\"capture\"];\n const retries = options.retries ?? DEFAULT_RETRIES;\n if (kinds.length === 0) {\n throw new Error(\"createDatabaseCaptureQueue: `kinds` must name at least one job kind\");\n }\n if (!Number.isInteger(retries) || retries < 0) {\n throw new Error(\"createDatabaseCaptureQueue: `retries` must be a non-negative integer\");\n }\n const rt: QueueRuntime = {\n model: new CaptureJobModel(db),\n kinds,\n leaseMs: positive(options.leaseMs, DEFAULT_LEASE_MS),\n maxAttempts: retries + 1,\n owner: options.owner ?? `${hostname()}:${String(process.pid)}:${ulid().slice(-6)}`,\n now: options.now ?? Date.now,\n timers: options.timers,\n wake: createWakeSignal(options.timers),\n pollVersion: 0,\n };\n return withHooks(rt, options);\n}\n\n/** The optional logger and exhausted-job hook, when given. */\nfunction withHooks(rt: QueueRuntime, options: DatabaseCaptureQueueOptions): QueueRuntime {\n if (options.logger !== undefined) {\n rt.logger = options.logger;\n }\n if (options.onExhausted !== undefined) {\n rt.onExhausted = options.onExhausted;\n }\n return rt;\n}\n\nfunction positive(value: number | undefined, fallback: number): number {\n return value !== undefined && Number.isFinite(value) && value > 0 ? value : fallback;\n}\n\nexport {\n DEFAULT_LEASE_MS,\n DEFAULT_RETRIES,\n type DatabaseCaptureQueue,\n type DatabaseCaptureQueueOptions,\n type DatabaseJob,\n type QueueJobInput,\n} from \"./types.ts\";\nexport { LEASE_EXHAUSTED_ERROR } from \"./claim.ts\";\nexport { MAX_NACK_DELAY_MS } from \"./poll.ts\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAqCA,MAAa,0BAA0B;CACrC,MAAM;CACN,SAAA;CACA,aAAa;CACb,MAAM;CACN,UAAU;AACZ;;AAGA,SAAgB,2BACd,IACA,UAAuC,CAAC,GAClB;CACtB,MAAM,KAAK,eAAe,IAAI,OAAO;CACrC,OAAO;EACL,UAAU;EACV,WAAW,oBAAoB,EAAE;EACjC,UAAU,OAAqB;GAC7B,GAAG,WAAW;EAChB;EACA,SAAS,OAAO,QAAQ;GACtB,MAAM,eAAe,IAAI,GAAG;EAC9B;EACA,YAAY,OAAO,QAAQ,MAAM,WAAW,IAAI,GAAG;EACnD,QAAQ,OAAO,YAAY,MAAM,SAAS,IAAI,OAAO;EACrD,QAAQ,YAAY,MAAM,cAAc,EAAE;EAC1C,QAAQ,OAAO,UAAU,MAAM,cAAc,IAAI,KAAK;EACtD,QAAQ,OAAO,OAAO,MAAM,WAAW,IAAI,EAAE;EAC7C,MAAM,OAAO,gBAAgB,MAAM,QAAQ,IAAI,WAAW;EAC1D,KAAK,OAAO,QAAQ;GAClB,MAAM,OAAO,IAAI,GAAG;EACtB;EACA,MAAM,OAAO,KAAK,gBAAgB;GAChC,MAAM,QAAQ,IAAI,KAAK,WAAW;EACpC;EACA,QAAQ,OAAO,QAAQ,MAAM,UAAU,IAAI,GAAG;EAC9C,SAAS,OAAO,QAAQ,MAAM,WAAW,IAAI,GAAG;EAChD,aAAa,OAAO,OAAO,MAAM,GAAG,KAAK,KAAK,IAAI,GAAG,WAAW;CAClE;AACF;AAEA,SAAS,eAAe,IAAqB,SAAoD;CAC/F,MAAM,QAAQ,QAAQ,SAAS,CAAC,SAAS;CACzC,MAAM,UAAU,QAAQ,WAAA;CACxB,IAAI,MAAM,WAAW,GACnB,MAAM,IAAI,MAAM,qEAAqE;CAEvF,IAAI,CAAC,OAAO,UAAU,OAAO,KAAK,UAAU,GAC1C,MAAM,IAAI,MAAM,sEAAsE;CAaxF,OAAO,UAAU;EAVf,OAAO,IAAI,gBAAgB,EAAE;EAC7B;EACA,SAAS,SAAS,QAAQ,SAAS,gBAAgB;EACnD,aAAa,UAAU;EACvB,OAAO,QAAQ,SAAS,GAAG,SAAS,EAAE,GAAG,OAAO,QAAQ,GAAG,EAAE,GAAG,KAAK,CAAC,CAAC,MAAM,EAAE;EAC/E,KAAK,QAAQ,OAAO,KAAK;EACzB,QAAQ,QAAQ;EAChB,MAAM,iBAAiB,QAAQ,MAAM;EACrC,aAAa;CAEG,GAAG,OAAO;AAC9B;;AAGA,SAAS,UAAU,IAAkB,SAAoD;CACvF,IAAI,QAAQ,WAAW,KAAA,GACrB,GAAG,SAAS,QAAQ;CAEtB,IAAI,QAAQ,gBAAgB,KAAA,GAC1B,GAAG,cAAc,QAAQ;CAE3B,OAAO;AACT;AAEA,SAAS,SAAS,OAA2B,UAA0B;CACrE,OAAO,UAAU,KAAA,KAAa,OAAO,SAAS,KAAK,KAAK,QAAQ,IAAI,QAAQ;AAC9E"}
@@ -3,7 +3,6 @@ import __tsdown_shims_url from 'node:url';
3
3
  import { Logger } from "../../logger.mjs";
4
4
  import { LeaseRenewal, PollableCaptureQueue, PollableJob } from "../../adapter/capture-queue.mjs";
5
5
  import { QueueTimers } from "./timers.mjs";
6
- //#region src/capture/db-queue/keeper.d.ts
7
6
  /** Longest gap between two renewals while progress keeps coming. */
8
7
  declare const RENEW_THROTTLE_MS = 30000;
9
8
  /** Why a held job must stop. */
@@ -31,6 +30,5 @@ interface JobLeaseKeeper {
31
30
  }
32
31
  /** Keep `job`'s lease on `queue` while the caller reports progress through `touch`. */
33
32
  declare function keepJobLease(queue: Pick<PollableCaptureQueue, "extend" | "inspect">, job: PollableJob, options?: LeaseKeeperOptions): JobLeaseKeeper;
34
- //#endregion
35
33
  export { JobLeaseKeeper, LeaseEnd, LeaseKeeperOptions, RENEW_THROTTLE_MS, keepJobLease };
36
34
  //# sourceMappingURL=keeper.d.mts.map
@@ -3,7 +3,7 @@ import "node:url";
3
3
  import.meta.url;
4
4
  import { REAL_TIMERS, repeatEvery } from "./timers.mjs";
5
5
  import "./cadence.mjs";
6
- //#region src/capture/db-queue/keeper.ts
6
+ // src/capture/db-queue/keeper.ts
7
7
  /** Longest gap between two renewals while progress keeps coming. */
8
8
  const RENEW_THROTTLE_MS = 3e4;
9
9
  /** Keep `job`'s lease on `queue` while the caller reports progress through `touch`. */
@@ -86,7 +86,6 @@ function renewInterval(job, options) {
86
86
  const third = job.leaseMs === void 0 ? RENEW_THROTTLE_MS : Math.floor(job.leaseMs / 3);
87
87
  return Math.max(1, Math.min(RENEW_THROTTLE_MS, third));
88
88
  }
89
- //#endregion
90
89
  export { RENEW_THROTTLE_MS, keepJobLease };
91
90
 
92
91
  //# sourceMappingURL=keeper.mjs.map
@@ -4,7 +4,7 @@ import.meta.url;
4
4
  import { isTerminalJob } from "../../models/capture-job.mjs";
5
5
  import { isoAt } from "./clock.mjs";
6
6
  import { attemptRef } from "./poll.mjs";
7
- //#region src/capture/db-queue/lease.ts
7
+ // src/capture/db-queue/lease.ts
8
8
  /**
9
9
  * Renew the lease by another `leaseMs`. The write touches only the holder's attempt row and returns
10
10
  * it: an attempt retired by another instance reads `expired` (lost), a flagged one `cancelled`.
@@ -40,7 +40,6 @@ async function renewOwn(rt, receipt) {
40
40
  throw error;
41
41
  }
42
42
  }
43
- //#endregion
44
43
  export { extendJob, inspectJob };
45
44
 
46
45
  //# sourceMappingURL=lease.mjs.map
@@ -1,7 +1,7 @@
1
1
  import "node:path";
2
2
  import "node:url";
3
3
  import.meta.url;
4
- //#region src/capture/db-queue/lifecycle.ts
4
+ // src/capture/db-queue/lifecycle.ts
5
5
  /** Id no row ever has: the health probe is a primary-key read that finds nothing. */
6
6
  const HEALTH_PROBE_ID = "~health";
7
7
  /**
@@ -30,7 +30,6 @@ function buildQueueLifecycle(rt) {
30
30
  }
31
31
  };
32
32
  }
33
- //#endregion
34
33
  export { buildQueueLifecycle };
35
34
 
36
35
  //# sourceMappingURL=lifecycle.mjs.map
@@ -5,7 +5,7 @@ import { ulid } from "../../utils/ulid.mjs";
5
5
  import { attemptRowId, isTerminalJob } from "../../models/capture-job.mjs";
6
6
  import { encodePayload, toQueueEntry } from "./codec.mjs";
7
7
  import { isoAt } from "./clock.mjs";
8
- //#region src/capture/db-queue/operations.ts
8
+ // src/capture/db-queue/operations.ts
9
9
  /** Insert a queued job row and wake this instance's poller; resolves to the job id. */
10
10
  async function enqueueJob(rt, job) {
11
11
  const id = ulid();
@@ -88,7 +88,6 @@ async function cancelOne(rt, row) {
88
88
  async function flagAttempt(rt, attemptId, now) {
89
89
  if ((await rt.model.get(attemptId))?.status === "running") await rt.model.flagCancel(attemptId, now);
90
90
  }
91
- //#endregion
92
91
  export { activeEntries, cancelJobs, enqueueCapture, enqueueJob, recentEntries, statusOf };
93
92
 
94
93
  //# sourceMappingURL=operations.mjs.map
@@ -3,7 +3,6 @@ import __tsdown_shims_url from 'node:url';
3
3
  import { Logger } from "../../logger.mjs";
4
4
  import { PollCadence } from "./cadence.mjs";
5
5
  import { DatabaseCaptureQueue, DatabaseJob } from "./types.mjs";
6
- //#region src/capture/db-queue/poll-loop.d.ts
7
6
  /** Options of {@link startPollLoop}. */
8
7
  interface PollLoopOptions {
9
8
  queue: Pick<DatabaseCaptureQueue, "poll" | "waitForWork">;
@@ -25,6 +24,5 @@ interface PollLoop {
25
24
  }
26
25
  /** Start polling `queue` with `slots` concurrent jobs. */
27
26
  declare function startPollLoop(options: PollLoopOptions): PollLoop;
28
- //#endregion
29
27
  export { PollLoop, PollLoopOptions, startPollLoop };
30
28
  //# sourceMappingURL=poll-loop.d.mts.map
@@ -2,7 +2,7 @@ import "node:path";
2
2
  import "node:url";
3
3
  import.meta.url;
4
4
  import { DEFAULT_CADENCE, nextPollDelay } from "./cadence.mjs";
5
- //#region src/capture/db-queue/poll-loop.ts
5
+ // src/capture/db-queue/poll-loop.ts
6
6
  /** Start polling `queue` with `slots` concurrent jobs. */
7
7
  function startPollLoop(options) {
8
8
  const state = {
@@ -83,7 +83,6 @@ async function nudged(state) {
83
83
  };
84
84
  await promise;
85
85
  }
86
- //#endregion
87
86
  export { startPollLoop };
88
87
 
89
88
  //# sourceMappingURL=poll-loop.mjs.map
@@ -2,9 +2,7 @@ import __tsdown_shims_path from 'node:path';
2
2
  import __tsdown_shims_url from 'node:url';
3
3
  import "../../adapter/capture-queue.mjs";
4
4
  import "./types.mjs";
5
- //#region src/capture/db-queue/poll.d.ts
6
5
  /** Longest a nack may delay a retry; larger delays are clamped. */
7
6
  declare const MAX_NACK_DELAY_MS: number;
8
- //#endregion
9
7
  export { MAX_NACK_DELAY_MS };
10
8
  //# sourceMappingURL=poll.d.mts.map
@@ -4,7 +4,7 @@ import.meta.url;
4
4
  import { isTerminalJob, parseAttemptRowId } from "../../models/capture-job.mjs";
5
5
  import { isoAt } from "./clock.mjs";
6
6
  import { claimNext } from "./claim.mjs";
7
- //#region src/capture/db-queue/poll.ts
7
+ // src/capture/db-queue/poll.ts
8
8
  /** Longest a nack may delay a retry; larger delays are clamped. */
9
9
  const MAX_NACK_DELAY_MS = 36e5;
10
10
  /**
@@ -63,7 +63,6 @@ function attemptRef(job) {
63
63
  ...parsed
64
64
  };
65
65
  }
66
- //#endregion
67
66
  export { MAX_NACK_DELAY_MS, ackJob, attemptRef, nackJob, pollJob };
68
67
 
69
68
  //# sourceMappingURL=poll.mjs.map
@@ -1,12 +1,10 @@
1
1
  import __tsdown_shims_path from 'node:path';
2
2
  import __tsdown_shims_url from 'node:url';
3
- //#region src/capture/db-queue/timers.d.ts
4
3
  /** Timer seam of the database queue: production uses the global timers, tests a manual clock. */
5
4
  /** The two timer calls the queue, its wake signal and the lease keeper make. */
6
5
  interface QueueTimers {
7
6
  setTimeout(callback: () => void, ms: number): unknown;
8
7
  clearTimeout(handle: unknown): void;
9
8
  }
10
- //#endregion
11
9
  export { QueueTimers };
12
10
  //# sourceMappingURL=timers.d.mts.map
@@ -1,7 +1,7 @@
1
1
  import "node:path";
2
2
  import "node:url";
3
3
  import.meta.url;
4
- //#region src/capture/db-queue/timers.ts
4
+ // src/capture/db-queue/timers.ts
5
5
  /** Global timers, unref'd so a waiting poll or a lease check never holds the process open. */
6
6
  const REAL_TIMERS = {
7
7
  setTimeout: (callback, ms) => {
@@ -31,7 +31,6 @@ function repeatEvery(timers, ms, callback) {
31
31
  timers.clearTimeout(handle);
32
32
  };
33
33
  }
34
- //#endregion
35
34
  export { REAL_TIMERS, repeatEvery };
36
35
 
37
36
  //# sourceMappingURL=timers.mjs.map
@@ -6,7 +6,6 @@ import { CaptureJob, LeaseRenewal, PollableCaptureQueue, PollableJob } from "../
6
6
  import { CaptureJobKind } from "../../schema/capture-job.mjs";
7
7
  import { QueueTimers } from "./timers.mjs";
8
8
  import "../../models/capture-job.mjs";
9
- //#region src/capture/db-queue/types.d.ts
10
9
  /** Options of {@link createDatabaseCaptureQueue}. */
11
10
  interface DatabaseCaptureQueueOptions {
12
11
  /** Job kinds this instance polls (default `["capture"]`); enqueue accepts every kind. */
@@ -78,6 +77,5 @@ interface DatabaseCaptureQueue extends PollableCaptureQueue {
78
77
  */
79
78
  waitForWork(ms: number): Promise<boolean>;
80
79
  }
81
- //#endregion
82
80
  export { DEFAULT_LEASE_MS, DEFAULT_RETRIES, DatabaseCaptureQueue, DatabaseCaptureQueueOptions, DatabaseJob, QueueJobInput };
83
81
  //# sourceMappingURL=types.d.mts.map