@storyshelf/core 0.6.2 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +49 -32
- package/dist/adapter/capture-queue.d.mts +44 -4
- package/dist/adapter/capture-runner.d.mts +134 -12
- package/dist/adapter/capture-runner.mjs +9 -12
- package/dist/adapter/database.d.mts +89 -10
- package/dist/adapter/database.mjs +4 -3
- package/dist/adapter/database.mjs.map +1 -1
- package/dist/adapter/design.d.mts +83 -0
- package/dist/adapter/design.mjs +27 -0
- package/dist/adapter/design.mjs.map +1 -0
- package/dist/adapter/email-sender.d.mts +0 -2
- package/dist/adapter/metadata.d.mts +3 -12
- package/dist/adapter/notifier.d.mts +6 -3
- package/dist/adapter/notifier.mjs +5 -1
- package/dist/adapter/oauth.d.mts +50 -0
- package/dist/adapter/setup.d.mts +4 -7
- package/dist/adapter/setup.mjs +3 -3
- package/dist/adapter/setup.mjs.map +1 -1
- package/dist/adapter/storage.d.mts +1 -3
- package/dist/adapter/webhook-events.d.mts +0 -2
- package/dist/adapter/webhook-events.mjs +13 -14
- package/dist/adapter/webhook-events.mjs.map +1 -1
- package/dist/adapters/capture-target-offers.d.mts +26 -0
- package/dist/adapters/capture-target-offers.mjs +57 -0
- package/dist/adapters/capture-target-offers.mjs.map +1 -0
- package/dist/adapters/capture-target.d.mts +69 -0
- package/dist/adapters/capture-target.mjs +75 -0
- package/dist/adapters/capture-target.mjs.map +1 -0
- package/dist/adapters/notifier/build-comment.d.mts +22 -0
- package/dist/adapters/notifier/build-comment.mjs +23 -0
- package/dist/adapters/notifier/build-comment.mjs.map +1 -0
- package/dist/adapters/notifier/build-state.d.mts +97 -0
- package/dist/adapters/notifier/build-state.mjs +217 -0
- package/dist/adapters/notifier/build-state.mjs.map +1 -0
- package/dist/adapters/notifier/events.d.mts +4 -4
- package/dist/adapters/notifier/events.mjs +32 -20
- package/dist/adapters/notifier/events.mjs.map +1 -1
- package/dist/adapters/notifier/format.d.mts +0 -2
- package/dist/adapters/notifier/format.mjs +1 -2
- package/dist/adapters/notifier/provider.d.mts +53 -9
- package/dist/adapters/notifier/provider.mjs +11 -0
- package/dist/adapters/notifier/provider.mjs.map +1 -0
- package/dist/adapters/notifier/state.d.mts +22 -0
- package/dist/adapters/notifier/state.mjs +65 -0
- package/dist/adapters/notifier/state.mjs.map +1 -0
- package/dist/adapters/notifier/types.d.mts +51 -4
- package/dist/adapters/remote-browser.d.mts +168 -0
- package/dist/adapters/remote-browser.mjs +201 -0
- package/dist/adapters/remote-browser.mjs.map +1 -0
- package/dist/adapters/remote-lease-attempt.mjs +39 -0
- package/dist/adapters/remote-lease-attempt.mjs.map +1 -0
- package/dist/adapters/remote-lease-error.d.mts +25 -0
- package/dist/adapters/remote-lease-error.mjs +54 -0
- package/dist/adapters/remote-lease-error.mjs.map +1 -0
- package/dist/adapters/remote-lease-held.d.mts +15 -0
- package/dist/adapters/remote-lease-held.mjs +86 -0
- package/dist/adapters/remote-lease-held.mjs.map +1 -0
- package/dist/adapters/remote-lease-shutdown.d.mts +12 -0
- package/dist/adapters/remote-lease-shutdown.mjs +32 -0
- package/dist/adapters/remote-lease-shutdown.mjs.map +1 -0
- package/dist/adapters/remote-lease.d.mts +39 -0
- package/dist/adapters/remote-lease.mjs +175 -0
- package/dist/adapters/remote-lease.mjs.map +1 -0
- package/dist/adapters/remote-limiter.mjs +121 -0
- package/dist/adapters/remote-limiter.mjs.map +1 -0
- package/dist/adapters/remote-pool.d.mts +56 -0
- package/dist/adapters/remote-pool.mjs +195 -0
- package/dist/adapters/remote-pool.mjs.map +1 -0
- package/dist/adapters/render-runs.d.mts +23 -0
- package/dist/adapters/render-runs.mjs +40 -0
- package/dist/adapters/render-runs.mjs.map +1 -0
- package/dist/adapters/setup-runner.d.mts +0 -2
- package/dist/adapters/setup-runner.mjs +3 -6
- package/dist/adapters/setup-runner.mjs.map +1 -1
- package/dist/adapters/sources.d.mts +10 -0
- package/dist/adapters/sources.mjs +19 -0
- package/dist/adapters/sources.mjs.map +1 -0
- package/dist/adapters/validate.d.mts +0 -2
- package/dist/adapters/validate.mjs +27 -20
- package/dist/adapters/validate.mjs.map +1 -1
- package/dist/ai.d.mts +103 -0
- package/dist/ai.mjs +18 -0
- package/dist/ai.mjs.map +1 -0
- package/dist/auth.d.mts +0 -2
- package/dist/auth.mjs +1 -2
- package/dist/brand-packs.d.mts +0 -2
- package/dist/brand-packs.mjs +0 -1
- package/dist/capture/a11y/axe-source.d.mts +16 -0
- package/dist/capture/a11y/axe-source.mjs +36 -0
- package/dist/capture/a11y/axe-source.mjs.map +1 -0
- package/dist/capture/a11y/in-page.d.mts +25 -0
- package/dist/capture/a11y/in-page.mjs +59 -0
- package/dist/capture/a11y/in-page.mjs.map +1 -0
- package/dist/capture/a11y/map.d.mts +22 -0
- package/dist/capture/a11y/map.mjs +47 -0
- package/dist/capture/a11y/map.mjs.map +1 -0
- package/dist/capture/a11y/options.d.mts +21 -0
- package/dist/capture/a11y/options.mjs +74 -0
- package/dist/capture/a11y/options.mjs.map +1 -0
- package/dist/capture/adapter.d.mts +46 -5
- package/dist/capture/adapter.mjs +1 -2
- package/dist/capture/adapter.mjs.map +1 -1
- package/dist/capture/affected.d.mts +2 -2
- package/dist/capture/affected.mjs +14 -6
- package/dist/capture/affected.mjs.map +1 -1
- package/dist/capture/attempt-logger.mjs +83 -0
- package/dist/capture/attempt-logger.mjs.map +1 -0
- package/dist/capture/browsers.d.mts +33 -0
- package/dist/capture/browsers.mjs +66 -0
- package/dist/capture/browsers.mjs.map +1 -0
- package/dist/capture/build-state/deliver.d.mts +30 -0
- package/dist/capture/build-state/deliver.mjs +117 -0
- package/dist/capture/build-state/deliver.mjs.map +1 -0
- package/dist/capture/build-state/index.d.mts +8 -0
- package/dist/capture/build-state/notify-job.d.mts +54 -0
- package/dist/capture/build-state/notify-job.mjs +132 -0
- package/dist/capture/build-state/notify-job.mjs.map +1 -0
- package/dist/capture/build-state/publisher.d.mts +21 -0
- package/dist/capture/build-state/publisher.mjs +106 -0
- package/dist/capture/build-state/publisher.mjs.map +1 -0
- package/dist/capture/build-state/resume.d.mts +7 -0
- package/dist/capture/build-state/resume.mjs +46 -0
- package/dist/capture/build-state/resume.mjs.map +1 -0
- package/dist/capture/build-state/types.d.mts +47 -0
- package/dist/capture/catalog/catalogue.d.mts +20 -0
- package/dist/capture/catalog/catalogue.mjs +52 -0
- package/dist/capture/catalog/catalogue.mjs.map +1 -0
- package/dist/capture/catalog/components.d.mts +21 -0
- package/dist/capture/catalog/components.mjs +54 -0
- package/dist/capture/catalog/components.mjs.map +1 -0
- package/dist/capture/catalog/history.d.mts +28 -0
- package/dist/capture/catalog/history.mjs +50 -0
- package/dist/capture/catalog/history.mjs.map +1 -0
- package/dist/capture/catalog/hook.d.mts +12 -0
- package/dist/capture/catalog/hook.mjs +18 -0
- package/dist/capture/catalog/hook.mjs.map +1 -0
- package/dist/capture/catalog/index.d.mts +11 -0
- package/dist/capture/catalog/load.d.mts +24 -0
- package/dist/capture/catalog/load.mjs +48 -0
- package/dist/capture/catalog/load.mjs.map +1 -0
- package/dist/capture/catalog/parse.d.mts +13 -0
- package/dist/capture/catalog/parse.mjs +55 -0
- package/dist/capture/catalog/parse.mjs.map +1 -0
- package/dist/capture/catalog/read.d.mts +15 -0
- package/dist/capture/catalog/read.mjs +39 -0
- package/dist/capture/catalog/read.mjs.map +1 -0
- package/dist/capture/catalog/types.d.mts +31 -0
- package/dist/capture/comparison-reference.d.mts +27 -0
- package/dist/capture/comparison-reference.mjs +75 -0
- package/dist/capture/comparison-reference.mjs.map +1 -0
- package/dist/capture/consumer/capture-handler.d.mts +56 -0
- package/dist/capture/consumer/capture-handler.mjs +117 -0
- package/dist/capture/consumer/capture-handler.mjs.map +1 -0
- package/dist/capture/consumer/idle.d.mts +15 -0
- package/dist/capture/consumer/idle.mjs +24 -0
- package/dist/capture/consumer/idle.mjs.map +1 -0
- package/dist/capture/consumer/index.d.mts +11 -0
- package/dist/capture/consumer/index.mjs +138 -0
- package/dist/capture/consumer/index.mjs.map +1 -0
- package/dist/capture/consumer/loop.mjs +109 -0
- package/dist/capture/consumer/loop.mjs.map +1 -0
- package/dist/capture/consumer/metrics.d.mts +39 -0
- package/dist/capture/consumer/metrics.mjs +37 -0
- package/dist/capture/consumer/metrics.mjs.map +1 -0
- package/dist/capture/consumer/retry.d.mts +31 -0
- package/dist/capture/consumer/retry.mjs +33 -0
- package/dist/capture/consumer/retry.mjs.map +1 -0
- package/dist/capture/consumer/run-job.mjs +194 -0
- package/dist/capture/consumer/run-job.mjs.map +1 -0
- package/dist/capture/consumer/startup.mjs +37 -0
- package/dist/capture/consumer/startup.mjs.map +1 -0
- package/dist/capture/consumer/types.d.mts +95 -0
- package/dist/capture/crash-failure.d.mts +23 -0
- package/dist/capture/crash-failure.mjs +69 -0
- package/dist/capture/crash-failure.mjs.map +1 -0
- package/dist/capture/db-queue/cadence.d.mts +30 -0
- package/dist/capture/db-queue/cadence.mjs +37 -0
- package/dist/capture/db-queue/cadence.mjs.map +1 -0
- package/dist/capture/db-queue/claim.d.mts +7 -0
- package/dist/capture/db-queue/claim.mjs +148 -0
- package/dist/capture/db-queue/claim.mjs.map +1 -0
- package/dist/capture/db-queue/clock.mjs +11 -0
- package/dist/capture/db-queue/clock.mjs.map +1 -0
- package/dist/capture/db-queue/codec.mjs +75 -0
- package/dist/capture/db-queue/codec.mjs.map +1 -0
- package/dist/capture/db-queue/index.d.mts +18 -0
- package/dist/capture/db-queue/index.mjs +89 -0
- package/dist/capture/db-queue/index.mjs.map +1 -0
- package/dist/capture/db-queue/keeper.d.mts +34 -0
- package/dist/capture/db-queue/keeper.mjs +91 -0
- package/dist/capture/db-queue/keeper.mjs.map +1 -0
- package/dist/capture/db-queue/lease.mjs +45 -0
- package/dist/capture/db-queue/lease.mjs.map +1 -0
- package/dist/capture/db-queue/lifecycle.mjs +35 -0
- package/dist/capture/db-queue/lifecycle.mjs.map +1 -0
- package/dist/capture/db-queue/operations.mjs +93 -0
- package/dist/capture/db-queue/operations.mjs.map +1 -0
- package/dist/capture/db-queue/poll-loop.d.mts +28 -0
- package/dist/capture/db-queue/poll-loop.mjs +88 -0
- package/dist/capture/db-queue/poll-loop.mjs.map +1 -0
- package/dist/capture/db-queue/poll.d.mts +8 -0
- package/dist/capture/db-queue/poll.mjs +68 -0
- package/dist/capture/db-queue/poll.mjs.map +1 -0
- package/dist/capture/db-queue/timers.d.mts +10 -0
- package/dist/capture/db-queue/timers.mjs +36 -0
- package/dist/capture/db-queue/timers.mjs.map +1 -0
- package/dist/capture/db-queue/types.d.mts +81 -0
- package/dist/capture/db-queue/types.mjs +11 -0
- package/dist/capture/db-queue/types.mjs.map +1 -0
- package/dist/capture/db-queue/wake.mjs +47 -0
- package/dist/capture/db-queue/wake.mjs.map +1 -0
- package/dist/capture/design.mjs +38 -0
- package/dist/capture/design.mjs.map +1 -0
- package/dist/capture/diff-record.mjs +24 -5
- package/dist/capture/diff-record.mjs.map +1 -1
- package/dist/capture/dispatch.d.mts +13 -10
- package/dist/capture/dispatch.mjs +102 -111
- package/dist/capture/dispatch.mjs.map +1 -1
- package/dist/capture/enrich.mjs +59 -0
- package/dist/capture/enrich.mjs.map +1 -0
- package/dist/capture/failure-sets.mjs +21 -0
- package/dist/capture/failure-sets.mjs.map +1 -0
- package/dist/capture/fingerprint.d.mts +40 -0
- package/dist/capture/fingerprint.mjs +82 -0
- package/dist/capture/fingerprint.mjs.map +1 -0
- package/dist/capture/forked/channel.d.mts +23 -0
- package/dist/capture/forked/child.d.mts +32 -0
- package/dist/capture/forked/child.mjs +201 -0
- package/dist/capture/forked/child.mjs.map +1 -0
- package/dist/capture/forked/crash-tracker.mjs +22 -0
- package/dist/capture/forked/crash-tracker.mjs.map +1 -0
- package/dist/capture/forked/decision.d.mts +24 -0
- package/dist/capture/forked/decision.mjs +26 -0
- package/dist/capture/forked/decision.mjs.map +1 -0
- package/dist/capture/forked/exit.mjs +11 -0
- package/dist/capture/forked/exit.mjs.map +1 -0
- package/dist/capture/forked/fork.d.mts +29 -0
- package/dist/capture/forked/fork.mjs +92 -0
- package/dist/capture/forked/fork.mjs.map +1 -0
- package/dist/capture/forked/forked-capture.d.mts +38 -0
- package/dist/capture/forked/forked-capture.mjs +239 -0
- package/dist/capture/forked/forked-capture.mjs.map +1 -0
- package/dist/capture/forked/lease-book.mjs +45 -0
- package/dist/capture/forked/lease-book.mjs.map +1 -0
- package/dist/capture/forked/protocol.d.mts +36 -0
- package/dist/capture/forked/protocol.mjs +24 -0
- package/dist/capture/forked/protocol.mjs.map +1 -0
- package/dist/capture/forked/runs.mjs +74 -0
- package/dist/capture/forked/runs.mjs.map +1 -0
- package/dist/capture/guards.mjs +1 -2
- package/dist/capture/ignore-regions.d.mts +36 -0
- package/dist/capture/ignore-regions.mjs +65 -0
- package/dist/capture/ignore-regions.mjs.map +1 -0
- package/dist/capture/isolate.mjs +140 -0
- package/dist/capture/isolate.mjs.map +1 -0
- package/dist/capture/job-lease.d.mts +26 -0
- package/dist/capture/job-lease.mjs +56 -0
- package/dist/capture/job-lease.mjs.map +1 -0
- package/dist/capture/matrix.mjs +298 -0
- package/dist/capture/matrix.mjs.map +1 -0
- package/dist/capture/modes.d.mts +23 -0
- package/dist/capture/modes.mjs +106 -0
- package/dist/capture/modes.mjs.map +1 -0
- package/dist/capture/orchestrator.d.mts +37 -7
- package/dist/capture/orchestrator.mjs +120 -110
- package/dist/capture/orchestrator.mjs.map +1 -1
- package/dist/capture/pipeline.d.mts +9 -4
- package/dist/capture/pipeline.mjs +284 -48
- package/dist/capture/pipeline.mjs.map +1 -1
- package/dist/capture/progress.d.mts +9 -0
- package/dist/capture/progress.mjs +27 -0
- package/dist/capture/progress.mjs.map +1 -0
- package/dist/capture/publish/accept.d.mts +37 -0
- package/dist/capture/publish/accept.mjs +27 -0
- package/dist/capture/publish/accept.mjs.map +1 -0
- package/dist/capture/publish/complete.d.mts +44 -0
- package/dist/capture/publish/complete.mjs +63 -0
- package/dist/capture/publish/complete.mjs.map +1 -0
- package/dist/capture/publish/extract.d.mts +18 -0
- package/dist/capture/publish/extract.mjs +120 -0
- package/dist/capture/publish/extract.mjs.map +1 -0
- package/dist/capture/publish/handler.d.mts +26 -0
- package/dist/capture/publish/handler.mjs +61 -0
- package/dist/capture/publish/handler.mjs.map +1 -0
- package/dist/capture/publish/index.d.mts +11 -0
- package/dist/capture/publish/invalid-zip.d.mts +8 -0
- package/dist/capture/publish/invalid-zip.mjs +11 -0
- package/dist/capture/publish/invalid-zip.mjs.map +1 -0
- package/dist/capture/publish/limits.d.mts +35 -0
- package/dist/capture/publish/limits.mjs +38 -0
- package/dist/capture/publish/limits.mjs.map +1 -0
- package/dist/capture/publish/published.d.mts +13 -0
- package/dist/capture/publish/published.mjs +17 -0
- package/dist/capture/publish/published.mjs.map +1 -0
- package/dist/capture/publish/run.d.mts +31 -0
- package/dist/capture/publish/run.mjs +29 -0
- package/dist/capture/publish/run.mjs.map +1 -0
- package/dist/capture/rediff.d.mts +1 -3
- package/dist/capture/rediff.mjs +23 -9
- package/dist/capture/rediff.mjs.map +1 -1
- package/dist/capture/render.mjs +52 -0
- package/dist/capture/render.mjs.map +1 -0
- package/dist/capture/scratch.d.mts +42 -0
- package/dist/capture/scratch.mjs +136 -0
- package/dist/capture/scratch.mjs.map +1 -0
- package/dist/capture/shard-plan.mjs +127 -0
- package/dist/capture/shard-plan.mjs.map +1 -0
- package/dist/capture/shards/context.mjs +51 -0
- package/dist/capture/shards/context.mjs.map +1 -0
- package/dist/capture/shards/execute.mjs +175 -0
- package/dist/capture/shards/execute.mjs.map +1 -0
- package/dist/capture/shards/fan-out.mjs +125 -0
- package/dist/capture/shards/fan-out.mjs.map +1 -0
- package/dist/capture/shards/history.mjs +34 -0
- package/dist/capture/shards/history.mjs.map +1 -0
- package/dist/capture/shards/reduce.mjs +96 -0
- package/dist/capture/shards/reduce.mjs.map +1 -0
- package/dist/capture/sizing.d.mts +0 -2
- package/dist/capture/sizing.mjs +2 -13
- package/dist/capture/sizing.mjs.map +1 -1
- package/dist/capture/skip-checks.mjs +3 -67
- package/dist/capture/skip-checks.mjs.map +1 -1
- package/dist/capture/statics.d.mts +7 -10
- package/dist/capture/statics.mjs +26 -74
- package/dist/capture/statics.mjs.map +1 -1
- package/dist/capture/storybook-urls.d.mts +38 -0
- package/dist/capture/storybook-urls.mjs +41 -0
- package/dist/capture/storybook-urls.mjs.map +1 -0
- package/dist/capture/storybook.d.mts +12 -6
- package/dist/capture/storybook.mjs +63 -19
- package/dist/capture/storybook.mjs.map +1 -1
- package/dist/capture/target.mjs +20 -0
- package/dist/capture/target.mjs.map +1 -0
- package/dist/capture/targets.d.mts +23 -0
- package/dist/capture/targets.mjs +31 -0
- package/dist/capture/targets.mjs.map +1 -0
- package/dist/capture/tests.d.mts +35 -0
- package/dist/capture/tests.mjs +136 -0
- package/dist/capture/tests.mjs.map +1 -0
- package/dist/capture/token-chunks.mjs +91 -0
- package/dist/capture/token-chunks.mjs.map +1 -0
- package/dist/capture.d.mts +63 -7
- package/dist/capture.mjs +51 -3
- package/dist/config.d.mts +136 -14
- package/dist/config.mjs +14 -8
- package/dist/config.mjs.map +1 -1
- package/dist/diff.d.mts +7 -3
- package/dist/diff.mjs +15 -3
- package/dist/diff.mjs.map +1 -0
- package/dist/index.d.mts +3 -3
- package/dist/index.mjs +2 -2
- package/dist/insights/budget.d.mts +18 -0
- package/dist/insights/budget.mjs +32 -0
- package/dist/insights/budget.mjs.map +1 -0
- package/dist/insights/envelope.d.mts +57 -0
- package/dist/insights/envelope.mjs +59 -0
- package/dist/insights/envelope.mjs.map +1 -0
- package/dist/insights/evidence-health.d.mts +30 -0
- package/dist/insights/evidence-health.mjs +27 -0
- package/dist/insights/evidence-health.mjs.map +1 -0
- package/dist/insights/evidence.d.mts +53 -0
- package/dist/insights/evidence.mjs +63 -0
- package/dist/insights/evidence.mjs.map +1 -0
- package/dist/insights/hash.d.mts +16 -0
- package/dist/insights/hash.mjs +20 -0
- package/dist/insights/hash.mjs.map +1 -0
- package/dist/insights/limits.d.mts +22 -0
- package/dist/insights/limits.mjs +23 -0
- package/dist/insights/limits.mjs.map +1 -0
- package/dist/insights/prompts/v1.d.mts +11 -0
- package/dist/insights/prompts/v1.mjs +33 -0
- package/dist/insights/prompts/v1.mjs.map +1 -0
- package/dist/insights/redact.d.mts +7 -0
- package/dist/insights/redact.mjs +23 -0
- package/dist/insights/redact.mjs.map +1 -0
- package/dist/insights/text.mjs +43 -0
- package/dist/insights/text.mjs.map +1 -0
- package/dist/insights.d.mts +11 -0
- package/dist/insights.mjs +12 -0
- package/dist/logger.d.mts +0 -2
- package/dist/logger.mjs +18 -3
- package/dist/logger.mjs.map +1 -1
- package/dist/models/ai-budget-alert.d.mts +21 -0
- package/dist/models/ai-budget-alert.mjs +37 -0
- package/dist/models/ai-budget-alert.mjs.map +1 -0
- package/dist/models/ai-usage.d.mts +38 -0
- package/dist/models/ai-usage.mjs +60 -0
- package/dist/models/ai-usage.mjs.map +1 -0
- package/dist/models/baseline-approval.d.mts +18 -0
- package/dist/models/baseline-approval.mjs +41 -0
- package/dist/models/baseline-approval.mjs.map +1 -0
- package/dist/models/baseline-archive.d.mts +82 -0
- package/dist/models/baseline-archive.mjs +105 -0
- package/dist/models/baseline-archive.mjs.map +1 -0
- package/dist/models/baseline-atomic.mjs +66 -0
- package/dist/models/baseline-atomic.mjs.map +1 -0
- package/dist/models/baseline-conflict.d.mts +6 -0
- package/dist/models/baseline-conflict.mjs +9 -0
- package/dist/models/baseline-conflict.mjs.map +1 -0
- package/dist/models/baseline-export.d.mts +17 -0
- package/dist/models/baseline-export.mjs +135 -0
- package/dist/models/baseline-export.mjs.map +1 -0
- package/dist/models/baseline-import.mjs +117 -0
- package/dist/models/baseline-import.mjs.map +1 -0
- package/dist/models/baseline-origin.d.mts +16 -0
- package/dist/models/baseline-origin.mjs +35 -0
- package/dist/models/baseline-origin.mjs.map +1 -0
- package/dist/models/baseline-status.d.mts +0 -2
- package/dist/models/baseline-status.mjs +1 -2
- package/dist/models/baseline-transfer.d.mts +48 -0
- package/dist/models/baseline-transfer.mjs +149 -0
- package/dist/models/baseline-transfer.mjs.map +1 -0
- package/dist/models/baseline.d.mts +37 -7
- package/dist/models/baseline.mjs +152 -28
- package/dist/models/baseline.mjs.map +1 -1
- package/dist/models/build-component.d.mts +26 -0
- package/dist/models/build-component.mjs +54 -0
- package/dist/models/build-component.mjs.map +1 -0
- package/dist/models/build-review-status.d.mts +27 -0
- package/dist/models/build-review-status.mjs +36 -0
- package/dist/models/build-review-status.mjs.map +1 -0
- package/dist/models/build-review.d.mts +26 -0
- package/dist/models/build-review.mjs +53 -0
- package/dist/models/build-review.mjs.map +1 -0
- package/dist/models/build.d.mts +25 -5
- package/dist/models/build.mjs +53 -15
- package/dist/models/build.mjs.map +1 -1
- package/dist/models/capture-attempt.d.mts +7 -3
- package/dist/models/capture-attempt.mjs +30 -6
- package/dist/models/capture-attempt.mjs.map +1 -1
- package/dist/models/capture-job.d.mts +104 -0
- package/dist/models/capture-job.mjs +287 -0
- package/dist/models/capture-job.mjs.map +1 -0
- package/dist/models/capture-log.d.mts +1 -3
- package/dist/models/capture-log.mjs +5 -5
- package/dist/models/capture-log.mjs.map +1 -1
- package/dist/models/capture-shard.d.mts +60 -0
- package/dist/models/capture-shard.mjs +189 -0
- package/dist/models/capture-shard.mjs.map +1 -0
- package/dist/models/changeset.d.mts +46 -0
- package/dist/models/changeset.mjs +80 -0
- package/dist/models/changeset.mjs.map +1 -0
- package/dist/models/columns.mjs +18 -0
- package/dist/models/columns.mjs.map +1 -0
- package/dist/models/comment.d.mts +4 -3
- package/dist/models/comment.mjs +8 -6
- package/dist/models/comment.mjs.map +1 -1
- package/dist/models/component.d.mts +41 -0
- package/dist/models/component.mjs +59 -0
- package/dist/models/component.mjs.map +1 -0
- package/dist/models/connections.d.mts +39 -0
- package/dist/models/connections.mjs +111 -0
- package/dist/models/connections.mjs.map +1 -0
- package/dist/models/content-ref.d.mts +1 -3
- package/dist/models/content-ref.mjs +2 -3
- package/dist/models/content-ref.mjs.map +1 -1
- package/dist/models/credentials.d.mts +0 -2
- package/dist/models/credentials.mjs +13 -4
- package/dist/models/credentials.mjs.map +1 -1
- package/dist/models/design-credentials.d.mts +39 -0
- package/dist/models/design-credentials.mjs +85 -0
- package/dist/models/design-credentials.mjs.map +1 -0
- package/dist/models/design-health.d.mts +14 -0
- package/dist/models/design-health.mjs +24 -0
- package/dist/models/design-health.mjs.map +1 -0
- package/dist/models/design-nodes.d.mts +81 -0
- package/dist/models/design-nodes.mjs +221 -0
- package/dist/models/design-nodes.mjs.map +1 -0
- package/dist/models/design-renders.mjs +73 -0
- package/dist/models/design-renders.mjs.map +1 -0
- package/dist/models/design-resolve.d.mts +27 -0
- package/dist/models/design-resolve.mjs +40 -0
- package/dist/models/design-resolve.mjs.map +1 -0
- package/dist/models/design.d.mts +37 -0
- package/dist/models/design.mjs +89 -0
- package/dist/models/design.mjs.map +1 -0
- package/dist/models/inherited-ratio.d.mts +19 -0
- package/dist/models/inherited-ratio.mjs +21 -0
- package/dist/models/inherited-ratio.mjs.map +1 -0
- package/dist/models/insight.d.mts +68 -0
- package/dist/models/insight.mjs +161 -0
- package/dist/models/insight.mjs.map +1 -0
- package/dist/models/label.d.mts +4 -4
- package/dist/models/label.mjs +26 -12
- package/dist/models/label.mjs.map +1 -1
- package/dist/models/member.d.mts +1 -3
- package/dist/models/member.mjs +6 -6
- package/dist/models/member.mjs.map +1 -1
- package/dist/models/notification-channel.d.mts +37 -5
- package/dist/models/notification-channel.mjs +89 -11
- package/dist/models/notification-channel.mjs.map +1 -1
- package/dist/models/notification-subscription.d.mts +1 -4
- package/dist/models/notification-subscription.mjs +8 -11
- package/dist/models/notification-subscription.mjs.map +1 -1
- package/dist/models/project-group-mapping.d.mts +6 -3
- package/dist/models/project-group-mapping.mjs +15 -6
- package/dist/models/project-group-mapping.mjs.map +1 -1
- package/dist/models/project.d.mts +9 -3
- package/dist/models/project.mjs +10 -6
- package/dist/models/project.mjs.map +1 -1
- package/dist/models/public-origin.d.mts +61 -0
- package/dist/models/public-origin.mjs +113 -0
- package/dist/models/public-origin.mjs.map +1 -0
- package/dist/models/review-switch-off.d.mts +12 -0
- package/dist/models/review-switch-off.mjs +25 -0
- package/dist/models/review-switch-off.mjs.map +1 -0
- package/dist/models/site-settings.d.mts +21 -0
- package/dist/models/site-settings.mjs +47 -0
- package/dist/models/site-settings.mjs.map +1 -0
- package/dist/models/snapshot.d.mts +39 -3
- package/dist/models/snapshot.mjs +54 -5
- package/dist/models/snapshot.mjs.map +1 -1
- package/dist/models/token.d.mts +13 -3
- package/dist/models/token.mjs +24 -7
- package/dist/models/token.mjs.map +1 -1
- package/dist/models/usage.d.mts +74 -0
- package/dist/models/usage.mjs +148 -0
- package/dist/models/usage.mjs.map +1 -0
- package/dist/models/user.d.mts +1 -3
- package/dist/models/user.mjs +5 -5
- package/dist/models/user.mjs.map +1 -1
- package/dist/models/webhook.d.mts +15 -3
- package/dist/models/webhook.mjs +34 -6
- package/dist/models/webhook.mjs.map +1 -1
- package/dist/models.d.mts +30 -4
- package/dist/models.mjs +31 -6
- package/dist/options.d.mts +16 -0
- package/dist/options.mjs +88 -0
- package/dist/options.mjs.map +1 -0
- package/dist/paths.d.mts +21 -6
- package/dist/paths.mjs +57 -12
- package/dist/paths.mjs.map +1 -1
- package/dist/retention/ai.d.mts +16 -0
- package/dist/retention/ai.mjs +22 -0
- package/dist/retention/ai.mjs.map +1 -0
- package/dist/retention/pending.mjs +46 -0
- package/dist/retention/pending.mjs.map +1 -0
- package/dist/retention/published-gzip-sweep.mjs +28 -0
- package/dist/retention/published-gzip-sweep.mjs.map +1 -0
- package/dist/retention/screenshot-sweep.d.mts +49 -0
- package/dist/retention/screenshot-sweep.mjs +127 -0
- package/dist/retention/screenshot-sweep.mjs.map +1 -0
- package/dist/retention.d.mts +16 -4
- package/dist/retention.mjs +76 -16
- package/dist/retention.mjs.map +1 -1
- package/dist/schema/baseline.d.mts +8 -2
- package/dist/schema/build-component.d.mts +23 -0
- package/dist/schema/build-review.d.mts +15 -0
- package/dist/schema/build.d.mts +7 -2
- package/dist/schema/capture-attempt.d.mts +0 -2
- package/dist/schema/capture-job.d.mts +58 -0
- package/dist/schema/capture-shard.d.mts +33 -0
- package/dist/schema/comment.d.mts +2 -2
- package/dist/schema/connection.d.mts +22 -0
- package/dist/schema/content-ref.d.mts +0 -2
- package/dist/schema/design.d.mts +56 -0
- package/dist/schema/insight.d.mts +52 -0
- package/dist/schema/label.d.mts +0 -2
- package/dist/schema/member.d.mts +0 -2
- package/dist/schema/notification.d.mts +4 -2
- package/dist/schema/project-group-mapping.d.mts +0 -2
- package/dist/schema/project.d.mts +21 -2
- package/dist/schema/site-setting.d.mts +19 -0
- package/dist/schema/snapshot.d.mts +17 -2
- package/dist/schema/token.d.mts +0 -2
- package/dist/schema/usage.d.mts +28 -0
- package/dist/schema/user.d.mts +0 -2
- package/dist/schema/webhook.d.mts +0 -2
- package/dist/schema.d.mts +12 -6
- package/dist/serverless.d.mts +19 -0
- package/dist/serverless.mjs +36 -0
- package/dist/serverless.mjs.map +1 -0
- package/dist/test-helpers/build-reference-contract.d.mts +14 -0
- package/dist/test-helpers/build-reference-contract.mjs +66 -0
- package/dist/test-helpers/build-reference-contract.mjs.map +1 -0
- package/dist/test-helpers/create-project.d.mts +1 -3
- package/dist/test-helpers/create-project.mjs +1 -2
- package/dist/test-helpers/database-contract.d.mts +0 -2
- package/dist/test-helpers/database-contract.mjs +37 -2
- package/dist/test-helpers/database-contract.mjs.map +1 -1
- package/dist/test-helpers/deferred.d.mts +37 -0
- package/dist/test-helpers/deferred.mjs +60 -0
- package/dist/test-helpers/deferred.mjs.map +1 -0
- package/dist/test-helpers/design-contract.d.mts +19 -0
- package/dist/test-helpers/design-contract.mjs +39 -0
- package/dist/test-helpers/design-contract.mjs.map +1 -0
- package/dist/test-helpers/fake-adapters.d.mts +0 -2
- package/dist/test-helpers/fake-adapters.mjs +1 -2
- package/dist/test-helpers/fake-database.d.mts +0 -2
- package/dist/test-helpers/fake-database.mjs +21 -4
- package/dist/test-helpers/fake-database.mjs.map +1 -1
- package/dist/test-helpers/fake-design.d.mts +41 -0
- package/dist/test-helpers/fake-design.mjs +113 -0
- package/dist/test-helpers/fake-design.mjs.map +1 -0
- package/dist/test-helpers/fake-notifier.d.mts +19 -0
- package/dist/test-helpers/fake-notifier.mjs +43 -0
- package/dist/test-helpers/fake-notifier.mjs.map +1 -0
- package/dist/test-helpers/fake-storage.d.mts +0 -2
- package/dist/test-helpers/fake-storage.mjs +1 -2
- package/dist/test-helpers/fake-tables.mjs +260 -69
- package/dist/test-helpers/fake-tables.mjs.map +1 -1
- package/dist/test-helpers/manual-clock.d.mts +25 -0
- package/dist/test-helpers/manual-clock.mjs +55 -0
- package/dist/test-helpers/manual-clock.mjs.map +1 -0
- package/dist/test-helpers/notifier-contract.d.mts +7 -3
- package/dist/test-helpers/notifier-contract.mjs +33 -5
- package/dist/test-helpers/notifier-contract.mjs.map +1 -1
- package/dist/test-helpers/queue-contract.d.mts +16 -4
- package/dist/test-helpers/queue-contract.mjs +196 -3
- package/dist/test-helpers/queue-contract.mjs.map +1 -1
- package/dist/test-helpers/queue-multi-instance.d.mts +18 -0
- package/dist/test-helpers/queue-multi-instance.mjs +205 -0
- package/dist/test-helpers/queue-multi-instance.mjs.map +1 -0
- package/dist/test-helpers/runner-contract.d.mts +0 -2
- package/dist/test-helpers/runner-contract.mjs +12 -2
- package/dist/test-helpers/runner-contract.mjs.map +1 -1
- package/dist/test-helpers/sql-chunks.mjs +25 -2
- package/dist/test-helpers/sql-chunks.mjs.map +1 -1
- package/dist/test-helpers/storage-contract.d.mts +0 -2
- package/dist/test-helpers/storage-contract.mjs +2 -3
- package/dist/test-helpers.d.mts +10 -4
- package/dist/test-helpers.mjs +9 -3
- package/dist/tracing.mjs +36 -6
- package/dist/tracing.mjs.map +1 -1
- package/dist/types.d.mts +14 -5
- package/dist/types.mjs +22 -6
- package/dist/types.mjs.map +1 -1
- package/dist/urls.d.mts +4 -2
- package/dist/urls.mjs +12 -4
- package/dist/urls.mjs.map +1 -1
- package/dist/utils/adaptive-concurrency.d.mts +64 -0
- package/dist/utils/adaptive-concurrency.mjs +148 -0
- package/dist/utils/adaptive-concurrency.mjs.map +1 -0
- package/dist/utils/connect-retry.d.mts +26 -0
- package/dist/utils/connect-retry.mjs +42 -0
- package/dist/utils/connect-retry.mjs.map +1 -0
- package/dist/utils/encrypt.d.mts +0 -2
- package/dist/utils/encrypt.mjs +1 -2
- package/dist/utils/environment.d.mts +17 -0
- package/dist/utils/environment.mjs +58 -0
- package/dist/utils/environment.mjs.map +1 -0
- package/dist/utils/hash.d.mts +0 -2
- package/dist/utils/hash.mjs +1 -2
- package/dist/utils/http.d.mts +29 -3
- package/dist/utils/http.mjs +100 -19
- package/dist/utils/http.mjs.map +1 -1
- package/dist/utils/map-adaptive.d.mts +13 -0
- package/dist/utils/map-adaptive.mjs +71 -0
- package/dist/utils/map-adaptive.mjs.map +1 -0
- package/dist/utils/map-limit.d.mts +8 -0
- package/dist/utils/map-limit.mjs +31 -0
- package/dist/utils/map-limit.mjs.map +1 -0
- package/dist/utils/mime.d.mts +0 -2
- package/dist/utils/mime.mjs +1 -2
- package/dist/utils/page-limiter.d.mts +35 -0
- package/dist/utils/page-limiter.mjs +55 -0
- package/dist/utils/page-limiter.mjs.map +1 -0
- package/dist/utils/path-security.d.mts +0 -2
- package/dist/utils/path-security.mjs +2 -4
- package/dist/utils/path-security.mjs.map +1 -1
- package/dist/utils/public-origin.d.mts +18 -0
- package/dist/utils/public-origin.mjs +74 -0
- package/dist/utils/public-origin.mjs.map +1 -0
- package/dist/utils/redact.d.mts +0 -2
- package/dist/utils/redact.mjs +4 -2
- package/dist/utils/redact.mjs.map +1 -1
- package/dist/utils/remote-environment.d.mts +76 -0
- package/dist/utils/remote-environment.mjs +163 -0
- package/dist/utils/remote-environment.mjs.map +1 -0
- package/dist/utils/resources.d.mts +62 -0
- package/dist/utils/resources.mjs +121 -0
- package/dist/utils/resources.mjs.map +1 -0
- package/dist/utils/screenshot-store.d.mts +13 -0
- package/dist/utils/screenshot-store.mjs +40 -0
- package/dist/utils/screenshot-store.mjs.map +1 -0
- package/dist/utils/session-gate.d.mts +23 -0
- package/dist/utils/session-gate.mjs +69 -0
- package/dist/utils/session-gate.mjs.map +1 -0
- package/dist/utils/storybook-token.d.mts +89 -0
- package/dist/utils/storybook-token.mjs +135 -0
- package/dist/utils/storybook-token.mjs.map +1 -0
- package/dist/utils/storybook-url.d.mts +13 -0
- package/dist/utils/storybook-url.mjs +20 -0
- package/dist/utils/storybook-url.mjs.map +1 -0
- package/dist/utils/timing.d.mts +0 -2
- package/dist/utils/timing.mjs +2 -3
- package/dist/utils/timing.mjs.map +1 -1
- package/dist/utils/ulid.d.mts +0 -2
- package/dist/utils/ulid.mjs +1 -2
- package/dist/utils/zip-read.mjs +128 -0
- package/dist/utils/zip-read.mjs.map +1 -0
- package/dist/utils/zip-write.d.mts +16 -0
- package/dist/utils/zip-write.mjs +187 -0
- package/dist/utils/zip-write.mjs.map +1 -0
- package/dist/utils.d.mts +17 -3
- package/dist/utils.mjs +18 -4
- package/package.json +35 -26
- package/dist/adapter/capture-runner.mjs.map +0 -1
- package/dist/adapter/git-host/comments.d.mts +0 -41
- package/dist/adapter/git-host/comments.mjs +0 -54
- package/dist/adapter/git-host/comments.mjs.map +0 -1
- package/dist/adapter/git-host/helpers.d.mts +0 -13
- package/dist/adapter/git-host/helpers.mjs +0 -30
- package/dist/adapter/git-host/helpers.mjs.map +0 -1
- package/dist/adapter/git-host.d.mts +0 -42
- package/dist/capture/queue.d.mts +0 -38
- package/dist/capture/queue.mjs +0 -98
- package/dist/capture/queue.mjs.map +0 -1
- package/dist/capture/recovery.d.mts +0 -21
- package/dist/capture/recovery.mjs +0 -83
- package/dist/capture/recovery.mjs.map +0 -1
- package/dist/capture/status-fanout.mjs +0 -72
- package/dist/capture/status-fanout.mjs.map +0 -1
- package/dist/diff/engine.d.mts +0 -16
- package/dist/diff/engine.mjs +0 -87
- package/dist/diff/engine.mjs.map +0 -1
- package/dist/diff/options.d.mts +0 -42
- package/dist/diff/options.mjs +0 -15
- package/dist/diff/options.mjs.map +0 -1
- package/dist/models/status-config.d.mts +0 -38
- package/dist/models/status-config.mjs +0 -63
- package/dist/models/status-config.mjs.map +0 -1
- package/dist/schema/status-config.d.mts +0 -16
- package/dist/test-helpers/git-contract.d.mts +0 -11
- package/dist/test-helpers/git-contract.mjs +0 -34
- package/dist/test-helpers/git-contract.mjs.map +0 -1
- /package/dist/adapter/{git-host.mjs → oauth.mjs} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codec.mjs","names":[],"sources":["../../../src/capture/db-queue/codec.ts"],"sourcesContent":["/** Codec of the database queue: job payload JSON and the row → job / queue-entry mappings. */\nimport type { JobStatus, QueueEntry } from \"../../adapters/capture-queue.ts\";\nimport { attemptRowId } from \"../../models/capture-job.ts\";\nimport type { CaptureJobRow } from \"../../schema/capture-job.ts\";\nimport type { DatabaseJob, QueueJobInput } from \"./types.ts\";\n\n/** What the `payload` column holds. */\ninterface StoredPayload {\n reqId?: string;\n traceparent?: string;\n data?: Record<string, unknown>;\n}\n\n/** Serialize the request id, trace context and kind-specific fields of a job; null when empty. */\nexport function encodePayload(job: QueueJobInput): string | null {\n const stored: StoredPayload = {};\n if (job.reqId !== undefined) {\n stored.reqId = job.reqId;\n }\n if (job.traceparent !== undefined) {\n stored.traceparent = job.traceparent;\n }\n if (job.data !== undefined && Object.keys(job.data).length > 0) {\n stored.data = job.data;\n }\n return Object.keys(stored).length === 0 ? null : JSON.stringify(stored);\n}\n\n/** Parse a stored payload. A malformed one (a poison row) decodes as empty rather than throwing. */\nexport function decodePayload(raw: string | null): StoredPayload {\n if (raw === null || raw === \"\") {\n return {};\n }\n try {\n const parsed: unknown = JSON.parse(raw);\n return isRecord(parsed) ? pickPayload(parsed) : {};\n } catch {\n return {};\n }\n}\n\n/** The job handed to a consumer for attempt `attempt` of a job row. */\nexport function toDatabaseJob(row: CaptureJobRow, attempt: number, leaseMs: number): DatabaseJob {\n const payload = decodePayload(row.payload);\n const job: DatabaseJob = {\n buildId: row.buildId ?? \"\",\n jobId: row.jobId,\n kind: row.kind,\n attempt,\n attempts: attempt - 1,\n maxAttempts: row.maxAttempts,\n receipt: attemptRowId(row.jobId, attempt),\n leaseMs,\n data: payload.data ?? {},\n };\n return withOptional(job, row, payload);\n}\n\n/** The queue-view entry of a job row. */\nexport function toQueueEntry(row: CaptureJobRow): QueueEntry {\n const entry: QueueEntry = {\n buildId: row.buildId ?? \"\",\n status: entryStatus(row.status),\n queuedAt: row.createdAt,\n };\n if (row.shardId !== null) {\n entry.shard = row.shardId;\n }\n if (row.startedAt !== null) {\n entry.startedAt = row.startedAt;\n }\n if (row.finishedAt !== null) {\n entry.finishedAt = row.finishedAt;\n }\n if (row.error !== null) {\n entry.error = row.error;\n }\n return entry;\n}\n\nfunction withOptional(job: DatabaseJob, row: CaptureJobRow, payload: StoredPayload): DatabaseJob {\n if (row.shardId !== null) {\n job.shard = row.shardId;\n }\n if (payload.reqId !== undefined) {\n job.reqId = payload.reqId;\n }\n if (payload.traceparent !== undefined) {\n job.traceparent = payload.traceparent;\n }\n return job;\n}\n\nfunction entryStatus(status: CaptureJobRow[\"status\"]): JobStatus {\n if (status === \"done\") {\n return \"completed\";\n }\n if (status === \"expired\") {\n return \"failed\";\n }\n return status;\n}\n\nfunction pickPayload(parsed: Record<string, unknown>): StoredPayload {\n const stored: StoredPayload = {};\n if (typeof parsed[\"reqId\"] === \"string\") {\n stored.reqId = parsed[\"reqId\"];\n }\n if (typeof parsed[\"traceparent\"] === \"string\") {\n stored.traceparent = parsed[\"traceparent\"];\n }\n if (isRecord(parsed[\"data\"])) {\n stored.data = parsed[\"data\"];\n }\n return stored;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n"],"mappings":";;;;;;AAcA,SAAgB,cAAc,KAAmC;CAC/D,MAAM,SAAwB,CAAC;CAC/B,IAAI,IAAI,UAAU,KAAA,GAChB,OAAO,QAAQ,IAAI;CAErB,IAAI,IAAI,gBAAgB,KAAA,GACtB,OAAO,cAAc,IAAI;CAE3B,IAAI,IAAI,SAAS,KAAA,KAAa,OAAO,KAAK,IAAI,IAAI,CAAC,CAAC,SAAS,GAC3D,OAAO,OAAO,IAAI;CAEpB,OAAO,OAAO,KAAK,MAAM,CAAC,CAAC,WAAW,IAAI,OAAO,KAAK,UAAU,MAAM;AACxE;;AAGA,SAAgB,cAAc,KAAmC;CAC/D,IAAI,QAAQ,QAAQ,QAAQ,IAC1B,OAAO,CAAC;CAEV,IAAI;EACF,MAAM,SAAkB,KAAK,MAAM,GAAG;EACtC,OAAO,SAAS,MAAM,IAAI,YAAY,MAAM,IAAI,CAAC;CACnD,QAAQ;EACN,OAAO,CAAC;CACV;AACF;;AAGA,SAAgB,cAAc,KAAoB,SAAiB,SAA8B;CAC/F,MAAM,UAAU,cAAc,IAAI,OAAO;CAYzC,OAAO,aAAa;EAVlB,SAAS,IAAI,WAAW;EACxB,OAAO,IAAI;EACX,MAAM,IAAI;EACV;EACA,UAAU,UAAU;EACpB,aAAa,IAAI;EACjB,SAAS,aAAa,IAAI,OAAO,OAAO;EACxC;EACA,MAAM,QAAQ,QAAQ,CAAC;CAEH,GAAG,KAAK,OAAO;AACvC;;AAGA,SAAgB,aAAa,KAAgC;CAC3D,MAAM,QAAoB;EACxB,SAAS,IAAI,WAAW;EACxB,QAAQ,YAAY,IAAI,MAAM;EAC9B,UAAU,IAAI;CAChB;CACA,IAAI,IAAI,YAAY,MAClB,MAAM,QAAQ,IAAI;CAEpB,IAAI,IAAI,cAAc,MACpB,MAAM,YAAY,IAAI;CAExB,IAAI,IAAI,eAAe,MACrB,MAAM,aAAa,IAAI;CAEzB,IAAI,IAAI,UAAU,MAChB,MAAM,QAAQ,IAAI;CAEpB,OAAO;AACT;AAEA,SAAS,aAAa,KAAkB,KAAoB,SAAqC;CAC/F,IAAI,IAAI,YAAY,MAClB,IAAI,QAAQ,IAAI;CAElB,IAAI,QAAQ,UAAU,KAAA,GACpB,IAAI,QAAQ,QAAQ;CAEtB,IAAI,QAAQ,gBAAgB,KAAA,GAC1B,IAAI,cAAc,QAAQ;CAE5B,OAAO;AACT;AAEA,SAAS,YAAY,QAA4C;CAC/D,IAAI,WAAW,QACb,OAAO;CAET,IAAI,WAAW,WACb,OAAO;CAET,OAAO;AACT;AAEA,SAAS,YAAY,QAAgD;CACnE,MAAM,SAAwB,CAAC;CAC/B,IAAI,OAAO,OAAO,aAAa,UAC7B,OAAO,QAAQ,OAAO;CAExB,IAAI,OAAO,OAAO,mBAAmB,UACnC,OAAO,cAAc,OAAO;CAE9B,IAAI,SAAS,OAAO,OAAO,GACzB,OAAO,OAAO,OAAO;CAEvB,OAAO;AACT;AAEA,SAAS,SAAS,OAAkD;CAClE,OAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC5E"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import __tsdown_shims_path from 'node:path';
|
|
2
|
+
import __tsdown_shims_url from 'node:url';
|
|
3
|
+
import { DatabaseAdapter } from "../../adapter/database.mjs";
|
|
4
|
+
import { DEFAULT_LEASE_MS, DEFAULT_RETRIES, DatabaseCaptureQueue, DatabaseCaptureQueueOptions, DatabaseJob, QueueJobInput } from "./types.mjs";
|
|
5
|
+
import { LEASE_EXHAUSTED_ERROR } from "./claim.mjs";
|
|
6
|
+
import { MAX_NACK_DELAY_MS } from "./poll.mjs";
|
|
7
|
+
/** What the database queue reports about itself; hosts show it before the queue is built. */
|
|
8
|
+
declare const DATABASE_QUEUE_METADATA: {
|
|
9
|
+
readonly name: "Database Queue";
|
|
10
|
+
readonly version: string;
|
|
11
|
+
readonly description: "Capture queue on the app database (capture_jobs)";
|
|
12
|
+
readonly kind: "database";
|
|
13
|
+
readonly category: "capture-queue";
|
|
14
|
+
};
|
|
15
|
+
/** A `PollableCaptureQueue` over `db`'s `capture_jobs` table. */
|
|
16
|
+
declare function createDatabaseCaptureQueue(db: DatabaseAdapter, options?: DatabaseCaptureQueueOptions): DatabaseCaptureQueue;
|
|
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 };
|
|
18
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import "node:path";
|
|
2
|
+
import "node:url";
|
|
3
|
+
import.meta.url;
|
|
4
|
+
import { ulid } from "../../utils/ulid.mjs";
|
|
5
|
+
import { CaptureJobModel } from "../../models/capture-job.mjs";
|
|
6
|
+
import { LEASE_EXHAUSTED_ERROR } from "./claim.mjs";
|
|
7
|
+
import { MAX_NACK_DELAY_MS, ackJob, nackJob, pollJob } from "./poll.mjs";
|
|
8
|
+
import { extendJob, inspectJob } from "./lease.mjs";
|
|
9
|
+
import { buildQueueLifecycle } from "./lifecycle.mjs";
|
|
10
|
+
import { activeEntries, cancelJobs, enqueueCapture, enqueueJob, recentEntries, statusOf } from "./operations.mjs";
|
|
11
|
+
import { DEFAULT_LEASE_MS, DEFAULT_RETRIES } from "./types.mjs";
|
|
12
|
+
import { createWakeSignal } from "./wake.mjs";
|
|
13
|
+
import { hostname } from "node:os";
|
|
14
|
+
// src/capture/db-queue/index.ts
|
|
15
|
+
/**
|
|
16
|
+
* Create the database capture queue (ADR 0006, decision 4): `capture_jobs` on the app's own
|
|
17
|
+
* `DatabaseAdapter` is the queue, safe with any number of instances.
|
|
18
|
+
*
|
|
19
|
+
* Composition root: wires the runtime, lifecycle, enqueue/cancel/views (`operations`), the claim
|
|
20
|
+
* (`claim`, `poll`) and the lease (`lease`) into a `PollableCaptureQueue`. Every attempt has its own
|
|
21
|
+
* row `<jobId>:<attempt>`, created by a unique-key insert, so claiming needs no compare-and-swap and
|
|
22
|
+
* a holder only ever writes its own attempt row.
|
|
23
|
+
*/
|
|
24
|
+
/** What the database queue reports about itself; hosts show it before the queue is built. */
|
|
25
|
+
const DATABASE_QUEUE_METADATA = {
|
|
26
|
+
name: "Database Queue",
|
|
27
|
+
version: "0.8.0",
|
|
28
|
+
description: "Capture queue on the app database (capture_jobs)",
|
|
29
|
+
kind: "database",
|
|
30
|
+
category: "capture-queue"
|
|
31
|
+
};
|
|
32
|
+
/** A `PollableCaptureQueue` over `db`'s `capture_jobs` table. */
|
|
33
|
+
function createDatabaseCaptureQueue(db, options = {}) {
|
|
34
|
+
const rt = resolveRuntime(db, options);
|
|
35
|
+
return {
|
|
36
|
+
metadata: DATABASE_QUEUE_METADATA,
|
|
37
|
+
lifecycle: buildQueueLifecycle(rt),
|
|
38
|
+
setLogger(bound) {
|
|
39
|
+
rt.logger ??= bound;
|
|
40
|
+
},
|
|
41
|
+
enqueue: async (job) => {
|
|
42
|
+
await enqueueCapture(rt, job);
|
|
43
|
+
},
|
|
44
|
+
enqueueJob: async (job) => await enqueueJob(rt, job),
|
|
45
|
+
status: async (buildId) => await statusOf(rt, buildId),
|
|
46
|
+
active: async () => await activeEntries(rt),
|
|
47
|
+
recent: async (limit) => await recentEntries(rt, limit),
|
|
48
|
+
cancel: async (id) => await cancelJobs(rt, id),
|
|
49
|
+
poll: async (pollOptions) => await pollJob(rt, pollOptions),
|
|
50
|
+
ack: async (job) => {
|
|
51
|
+
await ackJob(rt, job);
|
|
52
|
+
},
|
|
53
|
+
nack: async (job, nackOptions) => {
|
|
54
|
+
await nackJob(rt, job, nackOptions);
|
|
55
|
+
},
|
|
56
|
+
extend: async (job) => await extendJob(rt, job),
|
|
57
|
+
inspect: async (job) => await inspectJob(rt, job),
|
|
58
|
+
waitForWork: async (ms) => await rt.wake.wait(ms, rt.pollVersion)
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
function resolveRuntime(db, options) {
|
|
62
|
+
const kinds = options.kinds ?? ["capture"];
|
|
63
|
+
const retries = options.retries ?? 2;
|
|
64
|
+
if (kinds.length === 0) throw new Error("createDatabaseCaptureQueue: `kinds` must name at least one job kind");
|
|
65
|
+
if (!Number.isInteger(retries) || retries < 0) throw new Error("createDatabaseCaptureQueue: `retries` must be a non-negative integer");
|
|
66
|
+
return withHooks({
|
|
67
|
+
model: new CaptureJobModel(db),
|
|
68
|
+
kinds,
|
|
69
|
+
leaseMs: positive(options.leaseMs, DEFAULT_LEASE_MS),
|
|
70
|
+
maxAttempts: retries + 1,
|
|
71
|
+
owner: options.owner ?? `${hostname()}:${String(process.pid)}:${ulid().slice(-6)}`,
|
|
72
|
+
now: options.now ?? Date.now,
|
|
73
|
+
timers: options.timers,
|
|
74
|
+
wake: createWakeSignal(options.timers),
|
|
75
|
+
pollVersion: 0
|
|
76
|
+
}, options);
|
|
77
|
+
}
|
|
78
|
+
/** The optional logger and exhausted-job hook, when given. */
|
|
79
|
+
function withHooks(rt, options) {
|
|
80
|
+
if (options.logger !== void 0) rt.logger = options.logger;
|
|
81
|
+
if (options.onExhausted !== void 0) rt.onExhausted = options.onExhausted;
|
|
82
|
+
return rt;
|
|
83
|
+
}
|
|
84
|
+
function positive(value, fallback) {
|
|
85
|
+
return value !== void 0 && Number.isFinite(value) && value > 0 ? value : fallback;
|
|
86
|
+
}
|
|
87
|
+
export { DATABASE_QUEUE_METADATA, DEFAULT_LEASE_MS, DEFAULT_RETRIES, LEASE_EXHAUSTED_ERROR, MAX_NACK_DELAY_MS, createDatabaseCaptureQueue };
|
|
88
|
+
|
|
89
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +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 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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import __tsdown_shims_path from 'node:path';
|
|
2
|
+
import __tsdown_shims_url from 'node:url';
|
|
3
|
+
import { Logger } from "../../logger.mjs";
|
|
4
|
+
import { LeaseRenewal, PollableCaptureQueue, PollableJob } from "../../adapter/capture-queue.mjs";
|
|
5
|
+
import { QueueTimers } from "./timers.mjs";
|
|
6
|
+
/** Longest gap between two renewals while progress keeps coming. */
|
|
7
|
+
declare const RENEW_THROTTLE_MS = 30000;
|
|
8
|
+
/** Why a held job must stop. */
|
|
9
|
+
type LeaseEnd = Exclude<LeaseRenewal, "ok">;
|
|
10
|
+
/** Options of {@link keepJobLease}. */
|
|
11
|
+
interface LeaseKeeperOptions {
|
|
12
|
+
/** Renew at most this often (default `min(RENEW_THROTTLE_MS, leaseMs / 3)`). */
|
|
13
|
+
renewEveryMs?: number;
|
|
14
|
+
/** State check interval (default {@link CANCEL_CHECK_MS}). */
|
|
15
|
+
checkMs?: number;
|
|
16
|
+
/** Clock in epoch ms (default `Date.now`). */
|
|
17
|
+
now?: () => number;
|
|
18
|
+
/** Timers of the state check (default the global timers). */
|
|
19
|
+
timers?: QueueTimers;
|
|
20
|
+
logger?: Logger;
|
|
21
|
+
}
|
|
22
|
+
/** Handle on a held job's lease. */
|
|
23
|
+
interface JobLeaseKeeper {
|
|
24
|
+
/** Report progress: renews the lease when the throttle allows. */
|
|
25
|
+
touch(): void;
|
|
26
|
+
/** Resolves once, when the job was cancelled or the lease lost; never while the job is ours. */
|
|
27
|
+
readonly ended: Promise<LeaseEnd>;
|
|
28
|
+
/** Stop checking; idempotent. */
|
|
29
|
+
stop(): void;
|
|
30
|
+
}
|
|
31
|
+
/** Keep `job`'s lease on `queue` while the caller reports progress through `touch`. */
|
|
32
|
+
declare function keepJobLease(queue: Pick<PollableCaptureQueue, "extend" | "inspect">, job: PollableJob, options?: LeaseKeeperOptions): JobLeaseKeeper;
|
|
33
|
+
export { JobLeaseKeeper, LeaseEnd, LeaseKeeperOptions, RENEW_THROTTLE_MS, keepJobLease };
|
|
34
|
+
//# sourceMappingURL=keeper.d.mts.map
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import "node:path";
|
|
2
|
+
import "node:url";
|
|
3
|
+
import.meta.url;
|
|
4
|
+
import { REAL_TIMERS, repeatEvery } from "./timers.mjs";
|
|
5
|
+
import "./cadence.mjs";
|
|
6
|
+
// src/capture/db-queue/keeper.ts
|
|
7
|
+
/** Longest gap between two renewals while progress keeps coming. */
|
|
8
|
+
const RENEW_THROTTLE_MS = 3e4;
|
|
9
|
+
/** Keep `job`'s lease on `queue` while the caller reports progress through `touch`. */
|
|
10
|
+
function keepJobLease(queue, job, options = {}) {
|
|
11
|
+
const now = options.now ?? Date.now;
|
|
12
|
+
const { promise, resolve } = Promise.withResolvers();
|
|
13
|
+
const state = {
|
|
14
|
+
lastRenewAt: now(),
|
|
15
|
+
renewing: false,
|
|
16
|
+
warned: false,
|
|
17
|
+
stopped: false,
|
|
18
|
+
settle: (end) => {
|
|
19
|
+
state.stopped = true;
|
|
20
|
+
resolve(end);
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
const stopChecks = startChecks(queue, job, state, options);
|
|
24
|
+
const stopBeat = startHeartbeat(queue, job, state, {
|
|
25
|
+
...options,
|
|
26
|
+
now
|
|
27
|
+
});
|
|
28
|
+
const stop = () => {
|
|
29
|
+
state.stopped = true;
|
|
30
|
+
stopChecks();
|
|
31
|
+
stopBeat();
|
|
32
|
+
};
|
|
33
|
+
promise.then(stop, stop);
|
|
34
|
+
return {
|
|
35
|
+
touch: () => {
|
|
36
|
+
renewIfDue(queue, job, state, {
|
|
37
|
+
...options,
|
|
38
|
+
now
|
|
39
|
+
});
|
|
40
|
+
},
|
|
41
|
+
ended: promise,
|
|
42
|
+
stop
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function startChecks(queue, job, state, options) {
|
|
46
|
+
const { inspect } = queue;
|
|
47
|
+
if (inspect === void 0) return () => {};
|
|
48
|
+
return repeatEvery(options.timers ?? REAL_TIMERS, options.checkMs ?? 5e3, () => {
|
|
49
|
+
if (!state.stopped) report(state, inspect(job), options.logger, job).catch(() => {});
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
/** Renew on a timer, so a silent stage keeps its lease; progress renewals count toward the interval. */
|
|
53
|
+
function startHeartbeat(queue, job, state, options) {
|
|
54
|
+
if (queue.extend === void 0) return () => {};
|
|
55
|
+
return repeatEvery(options.timers ?? REAL_TIMERS, renewInterval(job, options), () => {
|
|
56
|
+
renewIfDue(queue, job, state, options);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
function renewIfDue(queue, job, state, options) {
|
|
60
|
+
const { extend } = queue;
|
|
61
|
+
const at = options.now();
|
|
62
|
+
if (extend === void 0 || state.stopped || state.renewing || at - state.lastRenewAt < renewInterval(job, options)) return;
|
|
63
|
+
state.renewing = true;
|
|
64
|
+
state.lastRenewAt = at;
|
|
65
|
+
report(state, extend(job), options.logger, job).finally(() => {
|
|
66
|
+
state.renewing = false;
|
|
67
|
+
}).catch(() => {});
|
|
68
|
+
}
|
|
69
|
+
/** Settle on a non-ok outcome; a failed call is transient (warned once, the next one retries). */
|
|
70
|
+
async function report(state, outcome, logger, job) {
|
|
71
|
+
try {
|
|
72
|
+
const result = await outcome;
|
|
73
|
+
if (result !== "ok" && !state.stopped) state.settle(result);
|
|
74
|
+
} catch (error) {
|
|
75
|
+
if (!state.warned) {
|
|
76
|
+
state.warned = true;
|
|
77
|
+
logger?.warn({
|
|
78
|
+
err: error,
|
|
79
|
+
buildId: job.buildId
|
|
80
|
+
}, "failed to renew or check queue lease");
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function renewInterval(job, options) {
|
|
85
|
+
if (options.renewEveryMs !== void 0) return options.renewEveryMs;
|
|
86
|
+
const third = job.leaseMs === void 0 ? RENEW_THROTTLE_MS : Math.floor(job.leaseMs / 3);
|
|
87
|
+
return Math.max(1, Math.min(RENEW_THROTTLE_MS, third));
|
|
88
|
+
}
|
|
89
|
+
export { RENEW_THROTTLE_MS, keepJobLease };
|
|
90
|
+
|
|
91
|
+
//# sourceMappingURL=keeper.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keeper.mjs","names":[],"sources":["../../../src/capture/db-queue/keeper.ts"],"sourcesContent":["/**\n * The holder's side of a lease: while the handler is alive the lease is renewed by a heartbeat\n * timer (every `min(30 s, lease / 3)`) and by progress (throttled to the same interval), so a stage\n * that prints nothing for longer than the lease is not redelivered. A holder that dies stops\n * renewing and its lease expires. A separate timer reads the job's state every 5 s, so cancel and\n * takeover are seen within that interval even while the run is hung. The heartbeat stops with the\n * keeper: on completion, on a lost lease and on cancel.\n */\nimport type {\n LeaseRenewal,\n PollableCaptureQueue,\n PollableJob,\n} from \"../../adapters/capture-queue.ts\";\nimport type { Logger } from \"../../logger.ts\";\nimport { CANCEL_CHECK_MS } from \"./cadence.ts\";\nimport { REAL_TIMERS, repeatEvery, type QueueTimers } from \"./timers.ts\";\n\n/** Longest gap between two renewals while progress keeps coming. */\nexport const RENEW_THROTTLE_MS = 30_000;\n\n/** Why a held job must stop. */\nexport type LeaseEnd = Exclude<LeaseRenewal, \"ok\">;\n\n/** Options of {@link keepJobLease}. */\nexport interface LeaseKeeperOptions {\n /** Renew at most this often (default `min(RENEW_THROTTLE_MS, leaseMs / 3)`). */\n renewEveryMs?: number;\n /** State check interval (default {@link CANCEL_CHECK_MS}). */\n checkMs?: number;\n /** Clock in epoch ms (default `Date.now`). */\n now?: () => number;\n /** Timers of the state check (default the global timers). */\n timers?: QueueTimers;\n logger?: Logger;\n}\n\n/** Handle on a held job's lease. */\nexport interface JobLeaseKeeper {\n /** Report progress: renews the lease when the throttle allows. */\n touch(): void;\n /** Resolves once, when the job was cancelled or the lease lost; never while the job is ours. */\n readonly ended: Promise<LeaseEnd>;\n /** Stop checking; idempotent. */\n stop(): void;\n}\n\ninterface KeeperState {\n lastRenewAt: number;\n renewing: boolean;\n warned: boolean;\n stopped: boolean;\n settle: (end: LeaseEnd) => void;\n}\n\n/** Keep `job`'s lease on `queue` while the caller reports progress through `touch`. */\nexport function keepJobLease(\n queue: Pick<PollableCaptureQueue, \"extend\" | \"inspect\">,\n job: PollableJob,\n options: LeaseKeeperOptions = {},\n): JobLeaseKeeper {\n const now = options.now ?? Date.now;\n const { promise, resolve } = Promise.withResolvers<LeaseEnd>();\n const state: KeeperState = {\n lastRenewAt: now(),\n renewing: false,\n warned: false,\n stopped: false,\n settle: (end) => {\n state.stopped = true;\n resolve(end);\n },\n };\n const stopChecks = startChecks(queue, job, state, options);\n const stopBeat = startHeartbeat(queue, job, state, { ...options, now });\n const stop = (): void => {\n state.stopped = true;\n stopChecks();\n stopBeat();\n };\n promise.then(stop, stop);\n return {\n touch: () => {\n renewIfDue(queue, job, state, { ...options, now });\n },\n ended: promise,\n stop,\n };\n}\n\nfunction startChecks(\n queue: Pick<PollableCaptureQueue, \"inspect\">,\n job: PollableJob,\n state: KeeperState,\n options: LeaseKeeperOptions,\n): () => void {\n const { inspect } = queue;\n if (inspect === undefined) {\n return () => {};\n }\n return repeatEvery(options.timers ?? REAL_TIMERS, options.checkMs ?? CANCEL_CHECK_MS, () => {\n if (!state.stopped) {\n report(state, inspect(job), options.logger, job).catch(() => {});\n }\n });\n}\n\n/** Renew on a timer, so a silent stage keeps its lease; progress renewals count toward the interval. */\nfunction startHeartbeat(\n queue: Pick<PollableCaptureQueue, \"extend\">,\n job: PollableJob,\n state: KeeperState,\n options: LeaseKeeperOptions & { now: () => number },\n): () => void {\n if (queue.extend === undefined) {\n return () => {};\n }\n return repeatEvery(options.timers ?? REAL_TIMERS, renewInterval(job, options), () => {\n renewIfDue(queue, job, state, options);\n });\n}\n\nfunction renewIfDue(\n queue: Pick<PollableCaptureQueue, \"extend\">,\n job: PollableJob,\n state: KeeperState,\n options: LeaseKeeperOptions & { now: () => number },\n): void {\n const { extend } = queue;\n const at = options.now();\n if (\n extend === undefined ||\n state.stopped ||\n state.renewing ||\n at - state.lastRenewAt < renewInterval(job, options)\n ) {\n return;\n }\n state.renewing = true;\n state.lastRenewAt = at;\n report(state, extend(job), options.logger, job)\n .finally(() => {\n state.renewing = false;\n })\n .catch(() => {});\n}\n\n/** Settle on a non-ok outcome; a failed call is transient (warned once, the next one retries). */\nasync function report(\n state: KeeperState,\n outcome: Promise<LeaseRenewal>,\n logger: Logger | undefined,\n job: PollableJob,\n): Promise<void> {\n try {\n const result = await outcome;\n if (result !== \"ok\" && !state.stopped) {\n state.settle(result);\n }\n } catch (error) {\n if (!state.warned) {\n state.warned = true;\n logger?.warn({ err: error, buildId: job.buildId }, \"failed to renew or check queue lease\");\n }\n }\n}\n\nfunction renewInterval(job: PollableJob, options: LeaseKeeperOptions): number {\n if (options.renewEveryMs !== undefined) {\n return options.renewEveryMs;\n }\n const third = job.leaseMs === undefined ? RENEW_THROTTLE_MS : Math.floor(job.leaseMs / 3);\n return Math.max(1, Math.min(RENEW_THROTTLE_MS, third));\n}\n"],"mappings":";;;;;;;AAkBA,MAAa,oBAAoB;;AAqCjC,SAAgB,aACd,OACA,KACA,UAA8B,CAAC,GACf;CAChB,MAAM,MAAM,QAAQ,OAAO,KAAK;CAChC,MAAM,EAAE,SAAS,YAAY,QAAQ,cAAwB;CAC7D,MAAM,QAAqB;EACzB,aAAa,IAAI;EACjB,UAAU;EACV,QAAQ;EACR,SAAS;EACT,SAAS,QAAQ;GACf,MAAM,UAAU;GAChB,QAAQ,GAAG;EACb;CACF;CACA,MAAM,aAAa,YAAY,OAAO,KAAK,OAAO,OAAO;CACzD,MAAM,WAAW,eAAe,OAAO,KAAK,OAAO;EAAE,GAAG;EAAS;CAAI,CAAC;CACtE,MAAM,aAAmB;EACvB,MAAM,UAAU;EAChB,WAAW;EACX,SAAS;CACX;CACA,QAAQ,KAAK,MAAM,IAAI;CACvB,OAAO;EACL,aAAa;GACX,WAAW,OAAO,KAAK,OAAO;IAAE,GAAG;IAAS;GAAI,CAAC;EACnD;EACA,OAAO;EACP;CACF;AACF;AAEA,SAAS,YACP,OACA,KACA,OACA,SACY;CACZ,MAAM,EAAE,YAAY;CACpB,IAAI,YAAY,KAAA,GACd,aAAa,CAAC;CAEhB,OAAO,YAAY,QAAQ,UAAU,aAAa,QAAQ,WAAA,WAAkC;EAC1F,IAAI,CAAC,MAAM,SACT,OAAO,OAAO,QAAQ,GAAG,GAAG,QAAQ,QAAQ,GAAG,CAAC,CAAC,YAAY,CAAC,CAAC;CAEnE,CAAC;AACH;;AAGA,SAAS,eACP,OACA,KACA,OACA,SACY;CACZ,IAAI,MAAM,WAAW,KAAA,GACnB,aAAa,CAAC;CAEhB,OAAO,YAAY,QAAQ,UAAU,aAAa,cAAc,KAAK,OAAO,SAAS;EACnF,WAAW,OAAO,KAAK,OAAO,OAAO;CACvC,CAAC;AACH;AAEA,SAAS,WACP,OACA,KACA,OACA,SACM;CACN,MAAM,EAAE,WAAW;CACnB,MAAM,KAAK,QAAQ,IAAI;CACvB,IACE,WAAW,KAAA,KACX,MAAM,WACN,MAAM,YACN,KAAK,MAAM,cAAc,cAAc,KAAK,OAAO,GAEnD;CAEF,MAAM,WAAW;CACjB,MAAM,cAAc;CACpB,OAAO,OAAO,OAAO,GAAG,GAAG,QAAQ,QAAQ,GAAG,CAAC,CAC5C,cAAc;EACb,MAAM,WAAW;CACnB,CAAC,CAAC,CACD,YAAY,CAAC,CAAC;AACnB;;AAGA,eAAe,OACb,OACA,SACA,QACA,KACe;CACf,IAAI;EACF,MAAM,SAAS,MAAM;EACrB,IAAI,WAAW,QAAQ,CAAC,MAAM,SAC5B,MAAM,OAAO,MAAM;CAEvB,SAAS,OAAO;EACd,IAAI,CAAC,MAAM,QAAQ;GACjB,MAAM,SAAS;GACf,QAAQ,KAAK;IAAE,KAAK;IAAO,SAAS,IAAI;GAAQ,GAAG,sCAAsC;EAC3F;CACF;AACF;AAEA,SAAS,cAAc,KAAkB,SAAqC;CAC5E,IAAI,QAAQ,iBAAiB,KAAA,GAC3B,OAAO,QAAQ;CAEjB,MAAM,QAAQ,IAAI,YAAY,KAAA,IAAY,oBAAoB,KAAK,MAAM,IAAI,UAAU,CAAC;CACxF,OAAO,KAAK,IAAI,GAAG,KAAK,IAAI,mBAAmB,KAAK,CAAC;AACvD"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import "node:path";
|
|
2
|
+
import "node:url";
|
|
3
|
+
import.meta.url;
|
|
4
|
+
import { isTerminalJob } from "../../models/capture-job.mjs";
|
|
5
|
+
import { isoAt } from "./clock.mjs";
|
|
6
|
+
import { attemptRef } from "./poll.mjs";
|
|
7
|
+
// src/capture/db-queue/lease.ts
|
|
8
|
+
/**
|
|
9
|
+
* Renew the lease by another `leaseMs`. The write touches only the holder's attempt row and returns
|
|
10
|
+
* it: an attempt retired by another instance reads `expired` (lost), a flagged one `cancelled`.
|
|
11
|
+
* When the attempt is still ours, the job row is read too, so a job finished by another attempt or
|
|
12
|
+
* cancelled is noticed at this progress touch.
|
|
13
|
+
*/
|
|
14
|
+
async function extendJob(rt, job) {
|
|
15
|
+
const row = await renewOwn(rt, attemptRef(job).receipt);
|
|
16
|
+
const own = attemptState(row);
|
|
17
|
+
if (row !== null && row.status !== "running") await rt.model.clearVisibility(row.id, isoAt(rt));
|
|
18
|
+
return own === "ok" ? await inspectJob(rt, job) : own;
|
|
19
|
+
}
|
|
20
|
+
/** The job's state for the holder of `job`, without renewing: the periodic cancel check. */
|
|
21
|
+
async function inspectJob(rt, job) {
|
|
22
|
+
const ref = attemptRef(job);
|
|
23
|
+
return jobState(await rt.model.get(ref.jobId), ref.attempt);
|
|
24
|
+
}
|
|
25
|
+
function attemptState(row) {
|
|
26
|
+
if (row?.status !== "running") return "lost";
|
|
27
|
+
return row.cancelRequestedAt === null ? "ok" : "cancelled";
|
|
28
|
+
}
|
|
29
|
+
function jobState(row, attempt) {
|
|
30
|
+
if (row === null) return "lost";
|
|
31
|
+
if (row.status === "cancelled" || row.cancelRequestedAt !== null && !isTerminalJob(row)) return "cancelled";
|
|
32
|
+
return isTerminalJob(row) || row.attempt !== attempt ? "lost" : "ok";
|
|
33
|
+
}
|
|
34
|
+
/** Renew an attempt row; a row that no longer exists is lost, any other failure is transient. */
|
|
35
|
+
async function renewOwn(rt, receipt) {
|
|
36
|
+
try {
|
|
37
|
+
return await rt.model.renew(receipt, isoAt(rt, rt.leaseMs), isoAt(rt));
|
|
38
|
+
} catch (error) {
|
|
39
|
+
if (await rt.model.get(receipt) === null) return null;
|
|
40
|
+
throw error;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
export { extendJob, inspectJob };
|
|
44
|
+
|
|
45
|
+
//# sourceMappingURL=lease.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lease.mjs","names":[],"sources":["../../../src/capture/db-queue/lease.ts"],"sourcesContent":["/**\n * Lease operations of the database queue: `extend` renews the holder's own attempt row (and never\n * any other), `inspect` reads the job row for cancel and supersession without renewing anything.\n */\nimport type { LeaseRenewal, PollableJob } from \"../../adapters/capture-queue.ts\";\nimport { isTerminalJob } from \"../../models/capture-job.ts\";\nimport type { CaptureJobRow } from \"../../schema/capture-job.ts\";\nimport { isoAt } from \"./clock.ts\";\nimport { attemptRef } from \"./poll.ts\";\nimport type { QueueRuntime } from \"./types.ts\";\n\n/**\n * Renew the lease by another `leaseMs`. The write touches only the holder's attempt row and returns\n * it: an attempt retired by another instance reads `expired` (lost), a flagged one `cancelled`.\n * When the attempt is still ours, the job row is read too, so a job finished by another attempt or\n * cancelled is noticed at this progress touch.\n */\nexport async function extendJob(rt: QueueRuntime, job: PollableJob): Promise<LeaseRenewal> {\n const ref = attemptRef(job);\n const row = await renewOwn(rt, ref.receipt);\n const own = attemptState(row);\n if (row !== null && row.status !== \"running\") {\n // A late renewal of a retired row put a lease back on it; take the row out of the poll's range.\n await rt.model.clearVisibility(row.id, isoAt(rt));\n }\n return own === \"ok\" ? await inspectJob(rt, job) : own;\n}\n\n/** The job's state for the holder of `job`, without renewing: the periodic cancel check. */\nexport async function inspectJob(rt: QueueRuntime, job: PollableJob): Promise<LeaseRenewal> {\n const ref = attemptRef(job);\n return jobState(await rt.model.get(ref.jobId), ref.attempt);\n}\n\nfunction attemptState(row: CaptureJobRow | null): LeaseRenewal {\n if (row?.status !== \"running\") {\n return \"lost\";\n }\n return row.cancelRequestedAt === null ? \"ok\" : \"cancelled\";\n}\n\nfunction jobState(row: CaptureJobRow | null, attempt: number): LeaseRenewal {\n if (row === null) {\n return \"lost\";\n }\n if (row.status === \"cancelled\" || (row.cancelRequestedAt !== null && !isTerminalJob(row))) {\n return \"cancelled\";\n }\n return isTerminalJob(row) || row.attempt !== attempt ? \"lost\" : \"ok\";\n}\n\n/** Renew an attempt row; a row that no longer exists is lost, any other failure is transient. */\nasync function renewOwn(rt: QueueRuntime, receipt: string): Promise<CaptureJobRow | null> {\n try {\n return await rt.model.renew(receipt, isoAt(rt, rt.leaseMs), isoAt(rt));\n } catch (error) {\n if ((await rt.model.get(receipt)) === null) {\n return null;\n }\n throw error;\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAiBA,eAAsB,UAAU,IAAkB,KAAyC;CAEzF,MAAM,MAAM,MAAM,SAAS,IADf,WAAW,GACU,CAAC,CAAC,OAAO;CAC1C,MAAM,MAAM,aAAa,GAAG;CAC5B,IAAI,QAAQ,QAAQ,IAAI,WAAW,WAEjC,MAAM,GAAG,MAAM,gBAAgB,IAAI,IAAI,MAAM,EAAE,CAAC;CAElD,OAAO,QAAQ,OAAO,MAAM,WAAW,IAAI,GAAG,IAAI;AACpD;;AAGA,eAAsB,WAAW,IAAkB,KAAyC;CAC1F,MAAM,MAAM,WAAW,GAAG;CAC1B,OAAO,SAAS,MAAM,GAAG,MAAM,IAAI,IAAI,KAAK,GAAG,IAAI,OAAO;AAC5D;AAEA,SAAS,aAAa,KAAyC;CAC7D,IAAI,KAAK,WAAW,WAClB,OAAO;CAET,OAAO,IAAI,sBAAsB,OAAO,OAAO;AACjD;AAEA,SAAS,SAAS,KAA2B,SAA+B;CAC1E,IAAI,QAAQ,MACV,OAAO;CAET,IAAI,IAAI,WAAW,eAAgB,IAAI,sBAAsB,QAAQ,CAAC,cAAc,GAAG,GACrF,OAAO;CAET,OAAO,cAAc,GAAG,KAAK,IAAI,YAAY,UAAU,SAAS;AAClE;;AAGA,eAAe,SAAS,IAAkB,SAAgD;CACxF,IAAI;EACF,OAAO,MAAM,GAAG,MAAM,MAAM,SAAS,MAAM,IAAI,GAAG,OAAO,GAAG,MAAM,EAAE,CAAC;CACvE,SAAS,OAAO;EACd,IAAK,MAAM,GAAG,MAAM,IAAI,OAAO,MAAO,MACpC,OAAO;EAET,MAAM;CACR;AACF"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import "node:path";
|
|
2
|
+
import "node:url";
|
|
3
|
+
import.meta.url;
|
|
4
|
+
// src/capture/db-queue/lifecycle.ts
|
|
5
|
+
/** Id no row ever has: the health probe is a primary-key read that finds nothing. */
|
|
6
|
+
const HEALTH_PROBE_ID = "~health";
|
|
7
|
+
/**
|
|
8
|
+
* Setup is a no-op (the database adapter's own setup creates `capture_jobs`); teardown releases any
|
|
9
|
+
* poll waiting on a local wake; health reads the table by primary key.
|
|
10
|
+
*/
|
|
11
|
+
function buildQueueLifecycle(rt) {
|
|
12
|
+
return {
|
|
13
|
+
setup: async () => {
|
|
14
|
+
await Promise.resolve();
|
|
15
|
+
},
|
|
16
|
+
teardown: async () => {
|
|
17
|
+
rt.wake.close();
|
|
18
|
+
await Promise.resolve();
|
|
19
|
+
},
|
|
20
|
+
health: async () => {
|
|
21
|
+
try {
|
|
22
|
+
await rt.model.get(HEALTH_PROBE_ID);
|
|
23
|
+
return { ok: true };
|
|
24
|
+
} catch (error) {
|
|
25
|
+
return {
|
|
26
|
+
ok: false,
|
|
27
|
+
detail: error instanceof Error ? error.message : String(error)
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export { buildQueueLifecycle };
|
|
34
|
+
|
|
35
|
+
//# sourceMappingURL=lifecycle.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lifecycle.mjs","names":[],"sources":["../../../src/capture/db-queue/lifecycle.ts"],"sourcesContent":["/** Lifecycle of the database queue: the database adapter owns its connection, the queue its waiters. */\nimport type { AdapterLifecycle } from \"../../adapters/metadata.ts\";\nimport type { QueueRuntime } from \"./types.ts\";\n\n/** Id no row ever has: the health probe is a primary-key read that finds nothing. */\nconst HEALTH_PROBE_ID = \"~health\";\n\n/**\n * Setup is a no-op (the database adapter's own setup creates `capture_jobs`); teardown releases any\n * poll waiting on a local wake; health reads the table by primary key.\n */\nexport function buildQueueLifecycle(rt: QueueRuntime): AdapterLifecycle {\n return {\n setup: async () => {\n await Promise.resolve();\n },\n teardown: async () => {\n rt.wake.close();\n await Promise.resolve();\n },\n health: async () => {\n try {\n await rt.model.get(HEALTH_PROBE_ID);\n return { ok: true };\n } catch (error) {\n return { ok: false, detail: error instanceof Error ? error.message : String(error) };\n }\n },\n };\n}\n"],"mappings":";;;;;AAKA,MAAM,kBAAkB;;;;;AAMxB,SAAgB,oBAAoB,IAAoC;CACtE,OAAO;EACL,OAAO,YAAY;GACjB,MAAM,QAAQ,QAAQ;EACxB;EACA,UAAU,YAAY;GACpB,GAAG,KAAK,MAAM;GACd,MAAM,QAAQ,QAAQ;EACxB;EACA,QAAQ,YAAY;GAClB,IAAI;IACF,MAAM,GAAG,MAAM,IAAI,eAAe;IAClC,OAAO,EAAE,IAAI,KAAK;GACpB,SAAS,OAAO;IACd,OAAO;KAAE,IAAI;KAAO,QAAQ,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;IAAE;GACrF;EACF;CACF;AACF"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import "node:path";
|
|
2
|
+
import "node:url";
|
|
3
|
+
import.meta.url;
|
|
4
|
+
import { ulid } from "../../utils/ulid.mjs";
|
|
5
|
+
import { attemptRowId, isTerminalJob } from "../../models/capture-job.mjs";
|
|
6
|
+
import { encodePayload, toQueueEntry } from "./codec.mjs";
|
|
7
|
+
import { isoAt } from "./clock.mjs";
|
|
8
|
+
// src/capture/db-queue/operations.ts
|
|
9
|
+
/** Insert a queued job row and wake this instance's poller; resolves to the job id. */
|
|
10
|
+
async function enqueueJob(rt, job) {
|
|
11
|
+
const id = ulid();
|
|
12
|
+
const now = isoAt(rt);
|
|
13
|
+
await rt.model.create({
|
|
14
|
+
id,
|
|
15
|
+
kind: job.kind,
|
|
16
|
+
buildId: job.buildId ?? null,
|
|
17
|
+
shardId: job.shard ?? null,
|
|
18
|
+
maxAttempts: job.maxAttempts ?? rt.maxAttempts,
|
|
19
|
+
payload: encodePayload(job)
|
|
20
|
+
}, now);
|
|
21
|
+
rt.logger?.info({
|
|
22
|
+
jobId: id,
|
|
23
|
+
kind: job.kind,
|
|
24
|
+
buildId: job.buildId
|
|
25
|
+
}, "job queued");
|
|
26
|
+
rt.wake.notify();
|
|
27
|
+
return id;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The kinds the queue's views (`status`, `active`, `recent`, `cancel`) show: every polled kind but
|
|
31
|
+
* `notify` (unless it is the only one), whose many short delivery jobs would bury a build's capture and publish jobs.
|
|
32
|
+
*/
|
|
33
|
+
function viewKinds(rt) {
|
|
34
|
+
const shown = rt.kinds.filter((kind) => kind !== "notify");
|
|
35
|
+
return shown.length > 0 ? shown : rt.kinds;
|
|
36
|
+
}
|
|
37
|
+
/** `CaptureQueue.enqueue`: a capture job for a build or one of its shards. */
|
|
38
|
+
async function enqueueCapture(rt, job) {
|
|
39
|
+
await enqueueJob(rt, {
|
|
40
|
+
...job,
|
|
41
|
+
kind: "capture"
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
/** The build's own job most recently queued, as a queue entry. */
|
|
45
|
+
async function statusOf(rt, buildId) {
|
|
46
|
+
const row = await rt.model.latestForBuild(buildId, viewKinds(rt));
|
|
47
|
+
return row === null ? null : toQueueEntry(row);
|
|
48
|
+
}
|
|
49
|
+
/** Queued and running jobs of this queue's kinds on every instance, oldest first. */
|
|
50
|
+
async function activeEntries(rt) {
|
|
51
|
+
return (await rt.model.listActive(viewKinds(rt))).map((row) => toQueueEntry(row));
|
|
52
|
+
}
|
|
53
|
+
/** The newest jobs of this queue's kinds, newest first. */
|
|
54
|
+
async function recentEntries(rt, limit) {
|
|
55
|
+
return (await rt.model.listRecent(viewKinds(rt), limit)).map((row) => toQueueEntry(row));
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Cancel a job (by job id) or every unfinished job of a build (by build id), of every kind that
|
|
59
|
+
* shares the table (capture, publish and notify), whichever kinds this queue polls. A queued job ends `cancelled` at once; a running one is flagged on its job row and on
|
|
60
|
+
* its current attempt row, so the holder sees it on its next renewal or cancel check.
|
|
61
|
+
*/
|
|
62
|
+
async function cancelJobs(rt, id) {
|
|
63
|
+
const targets = (await targetsOf(rt, id)).filter((row) => !isTerminalJob(row));
|
|
64
|
+
await Promise.all(targets.map(async (row) => {
|
|
65
|
+
await cancelOne(rt, row);
|
|
66
|
+
}));
|
|
67
|
+
if (targets.length > 0) rt.logger?.info({
|
|
68
|
+
id,
|
|
69
|
+
jobs: targets.length
|
|
70
|
+
}, "cancel requested");
|
|
71
|
+
return targets.length > 0;
|
|
72
|
+
}
|
|
73
|
+
async function targetsOf(rt, id) {
|
|
74
|
+
const row = await rt.model.get(id);
|
|
75
|
+
if (row?.entry === "job") return [row];
|
|
76
|
+
return await rt.model.listForBuild(id);
|
|
77
|
+
}
|
|
78
|
+
async function cancelOne(rt, row) {
|
|
79
|
+
const now = isoAt(rt);
|
|
80
|
+
await rt.model.flagCancel(row.jobId, now);
|
|
81
|
+
if (row.status === "queued") {
|
|
82
|
+
await rt.model.finishJob(row.jobId, "cancelled", now);
|
|
83
|
+
await flagAttempt(rt, attemptRowId(row.jobId, row.attempt + 1), now);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
await flagAttempt(rt, attemptRowId(row.jobId, row.attempt), now);
|
|
87
|
+
}
|
|
88
|
+
async function flagAttempt(rt, attemptId, now) {
|
|
89
|
+
if ((await rt.model.get(attemptId))?.status === "running") await rt.model.flagCancel(attemptId, now);
|
|
90
|
+
}
|
|
91
|
+
export { activeEntries, cancelJobs, enqueueCapture, enqueueJob, recentEntries, statusOf };
|
|
92
|
+
|
|
93
|
+
//# sourceMappingURL=operations.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operations.mjs","names":[],"sources":["../../../src/capture/db-queue/operations.ts"],"sourcesContent":["/** Enqueue, cancel and the cross-instance views (`status`/`active`/`recent`) of the database queue. */\nimport type { CaptureJob, QueueEntry } from \"../../adapters/capture-queue.ts\";\nimport { attemptRowId, isTerminalJob } from \"../../models/capture-job.ts\";\nimport type { CaptureJobKind, CaptureJobRow } from \"../../schema/capture-job.ts\";\nimport { ulid } from \"../../utils/ulid.ts\";\nimport { isoAt } from \"./clock.ts\";\nimport { encodePayload, toQueueEntry } from \"./codec.ts\";\nimport type { QueueJobInput, QueueRuntime } from \"./types.ts\";\n\n/** Insert a queued job row and wake this instance's poller; resolves to the job id. */\nexport async function enqueueJob(rt: QueueRuntime, job: QueueJobInput): Promise<string> {\n const id = ulid();\n const now = isoAt(rt);\n await rt.model.create(\n {\n id,\n kind: job.kind,\n buildId: job.buildId ?? null,\n shardId: job.shard ?? null,\n maxAttempts: job.maxAttempts ?? rt.maxAttempts,\n payload: encodePayload(job),\n },\n now,\n );\n rt.logger?.info({ jobId: id, kind: job.kind, buildId: job.buildId }, \"job queued\");\n rt.wake.notify();\n return id;\n}\n\n/**\n * The kinds the queue's views (`status`, `active`, `recent`, `cancel`) show: every polled kind but\n * `notify` (unless it is the only one), whose many short delivery jobs would bury a build's capture and publish jobs.\n */\nfunction viewKinds(rt: QueueRuntime): readonly CaptureJobKind[] {\n const shown = rt.kinds.filter((kind) => kind !== \"notify\");\n return shown.length > 0 ? shown : rt.kinds;\n}\n\n/** `CaptureQueue.enqueue`: a capture job for a build or one of its shards. */\nexport async function enqueueCapture(rt: QueueRuntime, job: CaptureJob): Promise<void> {\n await enqueueJob(rt, { ...job, kind: \"capture\" });\n}\n\n/** The build's own job most recently queued, as a queue entry. */\nexport async function statusOf(rt: QueueRuntime, buildId: string): Promise<QueueEntry | null> {\n const row = await rt.model.latestForBuild(buildId, viewKinds(rt));\n return row === null ? null : toQueueEntry(row);\n}\n\n/** Queued and running jobs of this queue's kinds on every instance, oldest first. */\nexport async function activeEntries(rt: QueueRuntime): Promise<QueueEntry[]> {\n return (await rt.model.listActive(viewKinds(rt))).map((row) => toQueueEntry(row));\n}\n\n/** The newest jobs of this queue's kinds, newest first. */\nexport async function recentEntries(rt: QueueRuntime, limit: number): Promise<QueueEntry[]> {\n return (await rt.model.listRecent(viewKinds(rt), limit)).map((row) => toQueueEntry(row));\n}\n\n/**\n * Cancel a job (by job id) or every unfinished job of a build (by build id), of every kind that\n * shares the table (capture, publish and notify), whichever kinds this queue polls. A queued job ends `cancelled` at once; a running one is flagged on its job row and on\n * its current attempt row, so the holder sees it on its next renewal or cancel check.\n */\nexport async function cancelJobs(rt: QueueRuntime, id: string): Promise<boolean> {\n const targets = (await targetsOf(rt, id)).filter((row) => !isTerminalJob(row));\n await Promise.all(\n targets.map(async (row) => {\n await cancelOne(rt, row);\n }),\n );\n if (targets.length > 0) {\n rt.logger?.info({ id, jobs: targets.length }, \"cancel requested\");\n }\n return targets.length > 0;\n}\n\nasync function targetsOf(rt: QueueRuntime, id: string): Promise<CaptureJobRow[]> {\n const row = await rt.model.get(id);\n if (row?.entry === \"job\") {\n return [row];\n }\n return await rt.model.listForBuild(id);\n}\n\nasync function cancelOne(rt: QueueRuntime, row: CaptureJobRow): Promise<void> {\n const now = isoAt(rt);\n // The flag goes first: it is never cleared, so a claim racing this cancel still sees it.\n await rt.model.flagCancel(row.jobId, now);\n if (row.status === \"queued\") {\n await rt.model.finishJob(row.jobId, \"cancelled\", now);\n // A claimer may have inserted the next attempt between our read and the write above.\n await flagAttempt(rt, attemptRowId(row.jobId, row.attempt + 1), now);\n return;\n }\n await flagAttempt(rt, attemptRowId(row.jobId, row.attempt), now);\n}\n\nasync function flagAttempt(rt: QueueRuntime, attemptId: string, now: string): Promise<void> {\n const attempt = await rt.model.get(attemptId);\n if (attempt?.status === \"running\") {\n await rt.model.flagCancel(attemptId, now);\n }\n}\n"],"mappings":";;;;;;;;;AAUA,eAAsB,WAAW,IAAkB,KAAqC;CACtF,MAAM,KAAK,KAAK;CAChB,MAAM,MAAM,MAAM,EAAE;CACpB,MAAM,GAAG,MAAM,OACb;EACE;EACA,MAAM,IAAI;EACV,SAAS,IAAI,WAAW;EACxB,SAAS,IAAI,SAAS;EACtB,aAAa,IAAI,eAAe,GAAG;EACnC,SAAS,cAAc,GAAG;CAC5B,GACA,GACF;CACA,GAAG,QAAQ,KAAK;EAAE,OAAO;EAAI,MAAM,IAAI;EAAM,SAAS,IAAI;CAAQ,GAAG,YAAY;CACjF,GAAG,KAAK,OAAO;CACf,OAAO;AACT;;;;;AAMA,SAAS,UAAU,IAA6C;CAC9D,MAAM,QAAQ,GAAG,MAAM,QAAQ,SAAS,SAAS,QAAQ;CACzD,OAAO,MAAM,SAAS,IAAI,QAAQ,GAAG;AACvC;;AAGA,eAAsB,eAAe,IAAkB,KAAgC;CACrF,MAAM,WAAW,IAAI;EAAE,GAAG;EAAK,MAAM;CAAU,CAAC;AAClD;;AAGA,eAAsB,SAAS,IAAkB,SAA6C;CAC5F,MAAM,MAAM,MAAM,GAAG,MAAM,eAAe,SAAS,UAAU,EAAE,CAAC;CAChE,OAAO,QAAQ,OAAO,OAAO,aAAa,GAAG;AAC/C;;AAGA,eAAsB,cAAc,IAAyC;CAC3E,QAAQ,MAAM,GAAG,MAAM,WAAW,UAAU,EAAE,CAAC,EAAA,CAAG,KAAK,QAAQ,aAAa,GAAG,CAAC;AAClF;;AAGA,eAAsB,cAAc,IAAkB,OAAsC;CAC1F,QAAQ,MAAM,GAAG,MAAM,WAAW,UAAU,EAAE,GAAG,KAAK,EAAA,CAAG,KAAK,QAAQ,aAAa,GAAG,CAAC;AACzF;;;;;;AAOA,eAAsB,WAAW,IAAkB,IAA8B;CAC/E,MAAM,WAAW,MAAM,UAAU,IAAI,EAAE,EAAA,CAAG,QAAQ,QAAQ,CAAC,cAAc,GAAG,CAAC;CAC7E,MAAM,QAAQ,IACZ,QAAQ,IAAI,OAAO,QAAQ;EACzB,MAAM,UAAU,IAAI,GAAG;CACzB,CAAC,CACH;CACA,IAAI,QAAQ,SAAS,GACnB,GAAG,QAAQ,KAAK;EAAE;EAAI,MAAM,QAAQ;CAAO,GAAG,kBAAkB;CAElE,OAAO,QAAQ,SAAS;AAC1B;AAEA,eAAe,UAAU,IAAkB,IAAsC;CAC/E,MAAM,MAAM,MAAM,GAAG,MAAM,IAAI,EAAE;CACjC,IAAI,KAAK,UAAU,OACjB,OAAO,CAAC,GAAG;CAEb,OAAO,MAAM,GAAG,MAAM,aAAa,EAAE;AACvC;AAEA,eAAe,UAAU,IAAkB,KAAmC;CAC5E,MAAM,MAAM,MAAM,EAAE;CAEpB,MAAM,GAAG,MAAM,WAAW,IAAI,OAAO,GAAG;CACxC,IAAI,IAAI,WAAW,UAAU;EAC3B,MAAM,GAAG,MAAM,UAAU,IAAI,OAAO,aAAa,GAAG;EAEpD,MAAM,YAAY,IAAI,aAAa,IAAI,OAAO,IAAI,UAAU,CAAC,GAAG,GAAG;EACnE;CACF;CACA,MAAM,YAAY,IAAI,aAAa,IAAI,OAAO,IAAI,OAAO,GAAG,GAAG;AACjE;AAEA,eAAe,YAAY,IAAkB,WAAmB,KAA4B;CAE1F,KAAI,MADkB,GAAG,MAAM,IAAI,SAAS,EAAA,EAC/B,WAAW,WACtB,MAAM,GAAG,MAAM,WAAW,WAAW,GAAG;AAE5C"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import __tsdown_shims_path from 'node:path';
|
|
2
|
+
import __tsdown_shims_url from 'node:url';
|
|
3
|
+
import { Logger } from "../../logger.mjs";
|
|
4
|
+
import { PollCadence } from "./cadence.mjs";
|
|
5
|
+
import { DatabaseCaptureQueue, DatabaseJob } from "./types.mjs";
|
|
6
|
+
/** Options of {@link startPollLoop}. */
|
|
7
|
+
interface PollLoopOptions {
|
|
8
|
+
queue: Pick<DatabaseCaptureQueue, "poll" | "waitForWork">;
|
|
9
|
+
/** Jobs this instance runs at once (`testing.concurrency`). */
|
|
10
|
+
slots: number;
|
|
11
|
+
/** Run one claimed job to its end (ack or nack it); rejections are logged, never fatal. */
|
|
12
|
+
run: (job: DatabaseJob) => Promise<void>;
|
|
13
|
+
cadence?: PollCadence;
|
|
14
|
+
now?: () => number;
|
|
15
|
+
random?: () => number;
|
|
16
|
+
logger?: Logger;
|
|
17
|
+
}
|
|
18
|
+
/** Handle on a running poll loop. */
|
|
19
|
+
interface PollLoop {
|
|
20
|
+
/** Jobs running right now. */
|
|
21
|
+
readonly busy: number;
|
|
22
|
+
/** Stop polling and wait for the jobs in flight to finish; idempotent. */
|
|
23
|
+
stop(): Promise<void>;
|
|
24
|
+
}
|
|
25
|
+
/** Start polling `queue` with `slots` concurrent jobs. */
|
|
26
|
+
declare function startPollLoop(options: PollLoopOptions): PollLoop;
|
|
27
|
+
export { PollLoop, PollLoopOptions, startPollLoop };
|
|
28
|
+
//# sourceMappingURL=poll-loop.d.mts.map
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import "node:path";
|
|
2
|
+
import "node:url";
|
|
3
|
+
import.meta.url;
|
|
4
|
+
import { DEFAULT_CADENCE, nextPollDelay } from "./cadence.mjs";
|
|
5
|
+
// src/capture/db-queue/poll-loop.ts
|
|
6
|
+
/** Start polling `queue` with `slots` concurrent jobs. */
|
|
7
|
+
function startPollLoop(options) {
|
|
8
|
+
const state = {
|
|
9
|
+
busy: 0,
|
|
10
|
+
stopped: false,
|
|
11
|
+
lastWorkAt: null,
|
|
12
|
+
inFlight: /* @__PURE__ */ new Set(),
|
|
13
|
+
nudge: () => {}
|
|
14
|
+
};
|
|
15
|
+
const done = loop(options, state);
|
|
16
|
+
return {
|
|
17
|
+
get busy() {
|
|
18
|
+
return state.busy;
|
|
19
|
+
},
|
|
20
|
+
stop: async () => {
|
|
21
|
+
state.stopped = true;
|
|
22
|
+
state.nudge();
|
|
23
|
+
await done;
|
|
24
|
+
await Promise.allSettled(state.inFlight);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
async function loop(options, state) {
|
|
29
|
+
const now = options.now ?? Date.now;
|
|
30
|
+
while (!state.stopped) await step(options, state, now);
|
|
31
|
+
}
|
|
32
|
+
/** One turn: wait for a slot (no poll while all are busy), else probe once and run or idle. */
|
|
33
|
+
async function step(options, state, now) {
|
|
34
|
+
if (state.busy >= options.slots) {
|
|
35
|
+
await nudged(state);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const job = await pollOnce(options);
|
|
39
|
+
if (job === null) {
|
|
40
|
+
await idle(options, state, now);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
state.lastWorkAt = now();
|
|
44
|
+
launch(options, state, job);
|
|
45
|
+
}
|
|
46
|
+
async function pollOnce(options) {
|
|
47
|
+
try {
|
|
48
|
+
return await options.queue.poll();
|
|
49
|
+
} catch (error) {
|
|
50
|
+
options.logger?.warn({ err: error }, "queue poll failed");
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
async function idle(options, state, now) {
|
|
55
|
+
const delay = nextPollDelay(state.lastWorkAt, now(), options.cadence ?? DEFAULT_CADENCE, options.random);
|
|
56
|
+
if (await Promise.race([options.queue.waitForWork(delay), nudged(state).then(() => false)])) state.lastWorkAt = now();
|
|
57
|
+
}
|
|
58
|
+
function launch(options, state, job) {
|
|
59
|
+
state.busy += 1;
|
|
60
|
+
const running = runSafely(options, job).finally(() => {
|
|
61
|
+
state.busy -= 1;
|
|
62
|
+
state.inFlight.delete(running);
|
|
63
|
+
state.nudge();
|
|
64
|
+
});
|
|
65
|
+
state.inFlight.add(running);
|
|
66
|
+
}
|
|
67
|
+
async function runSafely(options, job) {
|
|
68
|
+
try {
|
|
69
|
+
await options.run(job);
|
|
70
|
+
} catch (error) {
|
|
71
|
+
options.logger?.error({
|
|
72
|
+
err: error,
|
|
73
|
+
jobId: job.jobId
|
|
74
|
+
}, "queue job run failed");
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/** A promise the next nudge (slot freed, stop) resolves. */
|
|
78
|
+
async function nudged(state) {
|
|
79
|
+
if (state.stopped) return;
|
|
80
|
+
const { promise, resolve } = Promise.withResolvers();
|
|
81
|
+
state.nudge = () => {
|
|
82
|
+
resolve(null);
|
|
83
|
+
};
|
|
84
|
+
await promise;
|
|
85
|
+
}
|
|
86
|
+
export { startPollLoop };
|
|
87
|
+
|
|
88
|
+
//# sourceMappingURL=poll-loop.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"poll-loop.mjs","names":[],"sources":["../../../src/capture/db-queue/poll-loop.ts"],"sourcesContent":["/**\n * The slot-aware poll loop over the database queue: an instance polls only while it has a free\n * slot, at the cadence of `cadence.ts`, and dispatches at once on a local enqueue. Each claimed job\n * runs in a slot; the caller's `run` owns ack/nack and the lease. The full consumer (retries, the\n * final-attempt rule, drain on SIGTERM) builds on this loop.\n */\nimport type { Logger } from \"../../logger.ts\";\nimport { DEFAULT_CADENCE, nextPollDelay, type PollCadence } from \"./cadence.ts\";\nimport type { DatabaseCaptureQueue, DatabaseJob } from \"./types.ts\";\n\n/** Options of {@link startPollLoop}. */\nexport interface PollLoopOptions {\n queue: Pick<DatabaseCaptureQueue, \"poll\" | \"waitForWork\">;\n /** Jobs this instance runs at once (`testing.concurrency`). */\n slots: number;\n /** Run one claimed job to its end (ack or nack it); rejections are logged, never fatal. */\n run: (job: DatabaseJob) => Promise<void>;\n cadence?: PollCadence;\n now?: () => number;\n random?: () => number;\n logger?: Logger;\n}\n\n/** Handle on a running poll loop. */\nexport interface PollLoop {\n /** Jobs running right now. */\n readonly busy: number;\n /** Stop polling and wait for the jobs in flight to finish; idempotent. */\n stop(): Promise<void>;\n}\n\ninterface LoopState {\n busy: number;\n stopped: boolean;\n lastWorkAt: number | null;\n inFlight: Set<Promise<void>>;\n /** Resolves the current idle wait early (slot freed or stop). */\n nudge: () => void;\n}\n\n/** Start polling `queue` with `slots` concurrent jobs. */\nexport function startPollLoop(options: PollLoopOptions): PollLoop {\n const state: LoopState = {\n busy: 0,\n stopped: false,\n lastWorkAt: null,\n inFlight: new Set(),\n nudge: () => {},\n };\n const done = loop(options, state);\n return {\n get busy() {\n return state.busy;\n },\n stop: async () => {\n state.stopped = true;\n state.nudge();\n await done;\n await Promise.allSettled(state.inFlight);\n },\n };\n}\n\nasync function loop(options: PollLoopOptions, state: LoopState): Promise<void> {\n const now = options.now ?? Date.now;\n while (!state.stopped) {\n // oxlint-disable-next-line no-await-in-loop -- one step at a time is the loop\n await step(options, state, now);\n }\n}\n\n/** One turn: wait for a slot (no poll while all are busy), else probe once and run or idle. */\nasync function step(options: PollLoopOptions, state: LoopState, now: () => number): Promise<void> {\n if (state.busy >= options.slots) {\n await nudged(state);\n return;\n }\n const job = await pollOnce(options);\n if (job === null) {\n await idle(options, state, now);\n return;\n }\n state.lastWorkAt = now();\n launch(options, state, job);\n}\n\nasync function pollOnce(options: PollLoopOptions): Promise<DatabaseJob | null> {\n try {\n return await options.queue.poll();\n } catch (error) {\n options.logger?.warn({ err: error }, \"queue poll failed\");\n return null;\n }\n}\n\nasync function idle(options: PollLoopOptions, state: LoopState, now: () => number): Promise<void> {\n const delay = nextPollDelay(\n state.lastWorkAt,\n now(),\n options.cadence ?? DEFAULT_CADENCE,\n options.random,\n );\n const woken = await Promise.race([\n options.queue.waitForWork(delay),\n nudged(state).then(() => false),\n ]);\n if (woken) {\n state.lastWorkAt = now();\n }\n}\n\nfunction launch(options: PollLoopOptions, state: LoopState, job: DatabaseJob): void {\n state.busy += 1;\n const running = runSafely(options, job).finally(() => {\n state.busy -= 1;\n state.inFlight.delete(running);\n state.nudge();\n });\n state.inFlight.add(running);\n}\n\nasync function runSafely(options: PollLoopOptions, job: DatabaseJob): Promise<void> {\n try {\n await options.run(job);\n } catch (error) {\n options.logger?.error({ err: error, jobId: job.jobId }, \"queue job run failed\");\n }\n}\n\n/** A promise the next nudge (slot freed, stop) resolves. */\nasync function nudged(state: LoopState): Promise<void> {\n if (state.stopped) {\n return;\n }\n const { promise, resolve } = Promise.withResolvers<null>();\n state.nudge = (): void => {\n resolve(null);\n };\n await promise;\n}\n"],"mappings":";;;;;;AAyCA,SAAgB,cAAc,SAAoC;CAChE,MAAM,QAAmB;EACvB,MAAM;EACN,SAAS;EACT,YAAY;EACZ,0BAAU,IAAI,IAAI;EAClB,aAAa,CAAC;CAChB;CACA,MAAM,OAAO,KAAK,SAAS,KAAK;CAChC,OAAO;EACL,IAAI,OAAO;GACT,OAAO,MAAM;EACf;EACA,MAAM,YAAY;GAChB,MAAM,UAAU;GAChB,MAAM,MAAM;GACZ,MAAM;GACN,MAAM,QAAQ,WAAW,MAAM,QAAQ;EACzC;CACF;AACF;AAEA,eAAe,KAAK,SAA0B,OAAiC;CAC7E,MAAM,MAAM,QAAQ,OAAO,KAAK;CAChC,OAAO,CAAC,MAAM,SAEZ,MAAM,KAAK,SAAS,OAAO,GAAG;AAElC;;AAGA,eAAe,KAAK,SAA0B,OAAkB,KAAkC;CAChG,IAAI,MAAM,QAAQ,QAAQ,OAAO;EAC/B,MAAM,OAAO,KAAK;EAClB;CACF;CACA,MAAM,MAAM,MAAM,SAAS,OAAO;CAClC,IAAI,QAAQ,MAAM;EAChB,MAAM,KAAK,SAAS,OAAO,GAAG;EAC9B;CACF;CACA,MAAM,aAAa,IAAI;CACvB,OAAO,SAAS,OAAO,GAAG;AAC5B;AAEA,eAAe,SAAS,SAAuD;CAC7E,IAAI;EACF,OAAO,MAAM,QAAQ,MAAM,KAAK;CAClC,SAAS,OAAO;EACd,QAAQ,QAAQ,KAAK,EAAE,KAAK,MAAM,GAAG,mBAAmB;EACxD,OAAO;CACT;AACF;AAEA,eAAe,KAAK,SAA0B,OAAkB,KAAkC;CAChG,MAAM,QAAQ,cACZ,MAAM,YACN,IAAI,GACJ,QAAQ,WAAW,iBACnB,QAAQ,MACV;CAKA,IAAI,MAJgB,QAAQ,KAAK,CAC/B,QAAQ,MAAM,YAAY,KAAK,GAC/B,OAAO,KAAK,CAAC,CAAC,WAAW,KAAK,CAChC,CAAC,GAEC,MAAM,aAAa,IAAI;AAE3B;AAEA,SAAS,OAAO,SAA0B,OAAkB,KAAwB;CAClF,MAAM,QAAQ;CACd,MAAM,UAAU,UAAU,SAAS,GAAG,CAAC,CAAC,cAAc;EACpD,MAAM,QAAQ;EACd,MAAM,SAAS,OAAO,OAAO;EAC7B,MAAM,MAAM;CACd,CAAC;CACD,MAAM,SAAS,IAAI,OAAO;AAC5B;AAEA,eAAe,UAAU,SAA0B,KAAiC;CAClF,IAAI;EACF,MAAM,QAAQ,IAAI,GAAG;CACvB,SAAS,OAAO;EACd,QAAQ,QAAQ,MAAM;GAAE,KAAK;GAAO,OAAO,IAAI;EAAM,GAAG,sBAAsB;CAChF;AACF;;AAGA,eAAe,OAAO,OAAiC;CACrD,IAAI,MAAM,SACR;CAEF,MAAM,EAAE,SAAS,YAAY,QAAQ,cAAoB;CACzD,MAAM,cAAoB;EACxB,QAAQ,IAAI;CACd;CACA,MAAM;AACR"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import __tsdown_shims_path from 'node:path';
|
|
2
|
+
import __tsdown_shims_url from 'node:url';
|
|
3
|
+
import "../../adapter/capture-queue.mjs";
|
|
4
|
+
import "./types.mjs";
|
|
5
|
+
/** Longest a nack may delay a retry; larger delays are clamped. */
|
|
6
|
+
declare const MAX_NACK_DELAY_MS: number;
|
|
7
|
+
export { MAX_NACK_DELAY_MS };
|
|
8
|
+
//# sourceMappingURL=poll.d.mts.map
|