@rikalabs/akter 0.1.0-alpha.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/CHANGELOG.md +15 -0
- package/LICENSE +202 -0
- package/NOTICE +8 -0
- package/README.md +116 -0
- package/dist/actor/codecs.d.ts +77 -0
- package/dist/actor/codecs.js +87 -0
- package/dist/actor/connections.d.ts +34 -0
- package/dist/actor/connections.js +145 -0
- package/dist/actor/definition.d.ts +893 -0
- package/dist/actor/definition.js +147 -0
- package/dist/actor/descriptor.d.ts +172 -0
- package/dist/actor/descriptor.js +367 -0
- package/dist/actor/handles.d.ts +77 -0
- package/dist/actor/handles.js +265 -0
- package/dist/actor/jobs.d.ts +10 -0
- package/dist/actor/jobs.js +137 -0
- package/dist/actor/layers.d.ts +41 -0
- package/dist/actor/layers.js +177 -0
- package/dist/actor/reads.d.ts +47 -0
- package/dist/actor/reads.js +224 -0
- package/dist/actor/served.d.ts +120 -0
- package/dist/actor/served.js +72 -0
- package/dist/actor/turns.d.ts +13 -0
- package/dist/actor/turns.js +332 -0
- package/dist/actor/workflows.d.ts +16 -0
- package/dist/actor/workflows.js +37 -0
- package/dist/client/calls.d.ts +47 -0
- package/dist/client/calls.js +425 -0
- package/dist/client/clock.d.ts +56 -0
- package/dist/client/clock.js +119 -0
- package/dist/client/fleet-page.d.ts +15 -0
- package/dist/client/fleet-page.js +13 -0
- package/dist/client/fleet.d.ts +29 -0
- package/dist/client/fleet.js +51 -0
- package/dist/client/index.d.ts +17 -0
- package/dist/client/index.js +6 -0
- package/dist/client/make.d.ts +157 -0
- package/dist/client/make.js +221 -0
- package/dist/client/offline/queue.d.ts +118 -0
- package/dist/client/offline/queue.js +292 -0
- package/dist/client/offline/store.d.ts +74 -0
- package/dist/client/offline/store.js +78 -0
- package/dist/client/optimistic.d.ts +57 -0
- package/dist/client/optimistic.js +136 -0
- package/dist/client/report.d.ts +2 -0
- package/dist/client/report.js +8 -0
- package/dist/client/sessions/connection.d.ts +118 -0
- package/dist/client/sessions/connection.js +162 -0
- package/dist/client/sessions/feed.d.ts +42 -0
- package/dist/client/sessions/feed.js +43 -0
- package/dist/client/sessions/sse.d.ts +47 -0
- package/dist/client/sessions/sse.js +112 -0
- package/dist/client/sessions/stream.d.ts +28 -0
- package/dist/client/sessions/stream.js +35 -0
- package/dist/client/sessions/watch.d.ts +34 -0
- package/dist/client/sessions/watch.js +40 -0
- package/dist/client/transport.d.ts +37 -0
- package/dist/client/transport.js +66 -0
- package/dist/contexts/command.d.ts +132 -0
- package/dist/contexts/command.js +20 -0
- package/dist/contexts/connection.d.ts +68 -0
- package/dist/contexts/connection.js +0 -0
- package/dist/contexts/job.d.ts +49 -0
- package/dist/contexts/job.js +0 -0
- package/dist/contexts/workflow.d.ts +147 -0
- package/dist/contexts/workflow.js +22 -0
- package/dist/errors/actor.d.ts +200 -0
- package/dist/errors/actor.js +271 -0
- package/dist/errors/content.d.ts +19 -0
- package/dist/errors/content.js +14 -0
- package/dist/errors/database.d.ts +22 -0
- package/dist/errors/database.js +23 -0
- package/dist/errors/events.d.ts +17 -0
- package/dist/errors/events.js +14 -0
- package/dist/errors/subscription.d.ts +12 -0
- package/dist/errors/subscription.js +8 -0
- package/dist/errors/workflow.d.ts +28 -0
- package/dist/errors/workflow.js +17 -0
- package/dist/handles/actors.d.ts +17 -0
- package/dist/handles/actors.js +7 -0
- package/dist/handles/content.d.ts +59 -0
- package/dist/handles/content.js +36 -0
- package/dist/handles/intents.d.ts +164 -0
- package/dist/handles/intents.js +214 -0
- package/dist/handles/run.d.ts +31 -0
- package/dist/handles/run.js +21 -0
- package/dist/handles/workflow.d.ts +27 -0
- package/dist/handles/workflow.js +23 -0
- package/dist/identity/caller.d.ts +105 -0
- package/dist/identity/caller.js +68 -0
- package/dist/identity/child.d.ts +18 -0
- package/dist/identity/child.js +39 -0
- package/dist/identity/command.d.ts +19 -0
- package/dist/identity/command.js +21 -0
- package/dist/identity/connection.d.ts +24 -0
- package/dist/identity/connection.js +29 -0
- package/dist/identity/content.d.ts +18 -0
- package/dist/identity/content.js +12 -0
- package/dist/identity/digest.d.ts +4 -0
- package/dist/identity/digest.js +5 -0
- package/dist/identity/execution.d.ts +32 -0
- package/dist/identity/execution.js +63 -0
- package/dist/identity/mint.d.ts +51 -0
- package/dist/identity/mint.js +76 -0
- package/dist/identity/version.d.ts +2 -0
- package/dist/identity/version.js +3 -0
- package/dist/index.d.ts +159 -0
- package/dist/index.js +97 -0
- package/dist/members/blob.d.ts +43 -0
- package/dist/members/blob.js +29 -0
- package/dist/members/command.d.ts +109 -0
- package/dist/members/command.js +61 -0
- package/dist/members/connection.d.ts +55 -0
- package/dist/members/connection.js +49 -0
- package/dist/members/event.d.ts +36 -0
- package/dist/members/event.js +24 -0
- package/dist/members/job.d.ts +157 -0
- package/dist/members/job.js +67 -0
- package/dist/members/payload.d.ts +93 -0
- package/dist/members/payload.js +145 -0
- package/dist/members/reducer.d.ts +64 -0
- package/dist/members/reducer.js +27 -0
- package/dist/members/stream.d.ts +36 -0
- package/dist/members/stream.js +14 -0
- package/dist/members/subscription.d.ts +182 -0
- package/dist/members/subscription.js +91 -0
- package/dist/members/workflow.d.ts +99 -0
- package/dist/members/workflow.js +2 -0
- package/dist/policies/access.d.ts +35 -0
- package/dist/policies/access.js +6 -0
- package/dist/policies/command.d.ts +127 -0
- package/dist/policies/command.js +45 -0
- package/dist/policies/job.d.ts +28 -0
- package/dist/policies/job.js +60 -0
- package/dist/policies/schedules.d.ts +33 -0
- package/dist/policies/schedules.js +131 -0
- package/dist/protocol/frames.d.ts +66 -0
- package/dist/protocol/frames.js +55 -0
- package/dist/protocol/inspection.d.ts +807 -0
- package/dist/protocol/inspection.js +243 -0
- package/dist/protocol/wire.d.ts +184 -0
- package/dist/protocol/wire.js +150 -0
- package/dist/runtime/actors.d.ts +155 -0
- package/dist/runtime/actors.js +4 -0
- package/dist/runtime/admission.d.ts +34 -0
- package/dist/runtime/admission.js +72 -0
- package/dist/runtime/adoption/backfill.d.ts +27 -0
- package/dist/runtime/adoption/backfill.js +144 -0
- package/dist/runtime/adoption/enforce.d.ts +55 -0
- package/dist/runtime/adoption/enforce.js +241 -0
- package/dist/runtime/adoption/observe.d.ts +43 -0
- package/dist/runtime/adoption/observe.js +139 -0
- package/dist/runtime/adoption/plan.d.ts +45 -0
- package/dist/runtime/adoption/plan.js +192 -0
- package/dist/runtime/adoption/startup.d.ts +32 -0
- package/dist/runtime/adoption/startup.js +76 -0
- package/dist/runtime/adoption/status.d.ts +23 -0
- package/dist/runtime/adoption/status.js +47 -0
- package/dist/runtime/adoption/target.d.ts +33 -0
- package/dist/runtime/adoption/target.js +49 -0
- package/dist/runtime/connections/holder.d.ts +221 -0
- package/dist/runtime/connections/holder.js +816 -0
- package/dist/runtime/connections/owner.d.ts +263 -0
- package/dist/runtime/connections/owner.js +896 -0
- package/dist/runtime/connections/protocol.d.ts +441 -0
- package/dist/runtime/connections/protocol.js +222 -0
- package/dist/runtime/connections/reads.d.ts +24 -0
- package/dist/runtime/connections/reads.js +19 -0
- package/dist/runtime/connections/streams.d.ts +62 -0
- package/dist/runtime/connections/streams.js +128 -0
- package/dist/runtime/connections/transport.d.ts +40 -0
- package/dist/runtime/connections/transport.js +68 -0
- package/dist/runtime/connections/watch.d.ts +52 -0
- package/dist/runtime/connections/watch.js +159 -0
- package/dist/runtime/content/grant.d.ts +34 -0
- package/dist/runtime/content/grant.js +58 -0
- package/dist/runtime/content/store.d.ts +63 -0
- package/dist/runtime/content/store.js +294 -0
- package/dist/runtime/cron/key.d.ts +2 -0
- package/dist/runtime/cron/key.js +2 -0
- package/dist/runtime/cron/schedule.d.ts +69 -0
- package/dist/runtime/cron/schedule.js +144 -0
- package/dist/runtime/database/bounded.d.ts +43 -0
- package/dist/runtime/database/bounded.js +108 -0
- package/dist/runtime/database/connection.d.ts +8 -0
- package/dist/runtime/database/connection.js +18 -0
- package/dist/runtime/database/coordination.d.ts +19 -0
- package/dist/runtime/database/coordination.js +72 -0
- package/dist/runtime/database/flock.d.ts +10 -0
- package/dist/runtime/database/flock.js +60 -0
- package/dist/runtime/database/gate.d.ts +26 -0
- package/dist/runtime/database/gate.js +54 -0
- package/dist/runtime/database/keepalive.d.ts +11 -0
- package/dist/runtime/database/keepalive.js +22 -0
- package/dist/runtime/database/migrations.d.ts +177 -0
- package/dist/runtime/database/migrations.js +1018 -0
- package/dist/runtime/database/neki/migrations.d.ts +31 -0
- package/dist/runtime/database/neki/migrations.js +276 -0
- package/dist/runtime/database/neki/session.d.ts +23 -0
- package/dist/runtime/database/neki/session.js +31 -0
- package/dist/runtime/database/pglite.d.ts +21 -0
- package/dist/runtime/database/pglite.js +74 -0
- package/dist/runtime/database/replica.d.ts +41 -0
- package/dist/runtime/database/replica.js +51 -0
- package/dist/runtime/database/shards.d.ts +21 -0
- package/dist/runtime/database/shards.js +37 -0
- package/dist/runtime/database/snapshot.d.ts +7 -0
- package/dist/runtime/database/snapshot.js +7 -0
- package/dist/runtime/database/tenancy.d.ts +69 -0
- package/dist/runtime/database/tenancy.js +145 -0
- package/dist/runtime/database/transient.d.ts +10 -0
- package/dist/runtime/database/transient.js +25 -0
- package/dist/runtime/drain.d.ts +132 -0
- package/dist/runtime/drain.js +109 -0
- package/dist/runtime/entity/mailbox.d.ts +86 -0
- package/dist/runtime/entity/mailbox.js +121 -0
- package/dist/runtime/entity/register.d.ts +424 -0
- package/dist/runtime/entity/register.js +669 -0
- package/dist/runtime/events/append.d.ts +192 -0
- package/dist/runtime/events/append.js +128 -0
- package/dist/runtime/events/cursor.d.ts +2 -0
- package/dist/runtime/events/cursor.js +5 -0
- package/dist/runtime/events/replay.d.ts +20 -0
- package/dist/runtime/events/replay.js +45 -0
- package/dist/runtime/feeds.d.ts +26 -0
- package/dist/runtime/feeds.js +100 -0
- package/dist/runtime/fleet/checks.d.ts +17 -0
- package/dist/runtime/fleet/checks.js +106 -0
- package/dist/runtime/fleet/maintainer.d.ts +38 -0
- package/dist/runtime/fleet/maintainer.js +383 -0
- package/dist/runtime/fleet/pgoutput.d.ts +41 -0
- package/dist/runtime/fleet/pgoutput.js +102 -0
- package/dist/runtime/fleet/setup.d.ts +36 -0
- package/dist/runtime/fleet/setup.js +58 -0
- package/dist/runtime/fleet/subscribe.d.ts +42 -0
- package/dist/runtime/fleet/subscribe.js +147 -0
- package/dist/runtime/index.d.ts +66 -0
- package/dist/runtime/index.js +37 -0
- package/dist/runtime/inspector/http.d.ts +19 -0
- package/dist/runtime/inspector/http.js +36 -0
- package/dist/runtime/inspector/layer.d.ts +46 -0
- package/dist/runtime/inspector/layer.js +180 -0
- package/dist/runtime/inspector/queries.d.ts +711 -0
- package/dist/runtime/inspector/queries.js +494 -0
- package/dist/runtime/jobs/attempt.d.ts +254 -0
- package/dist/runtime/jobs/attempt.js +413 -0
- package/dist/runtime/jobs/isolation.d.ts +20 -0
- package/dist/runtime/jobs/isolation.js +10 -0
- package/dist/runtime/jobs/progress.d.ts +95 -0
- package/dist/runtime/jobs/progress.js +144 -0
- package/dist/runtime/layer.d.ts +260 -0
- package/dist/runtime/layer.js +876 -0
- package/dist/runtime/members.d.ts +381 -0
- package/dist/runtime/members.js +8 -0
- package/dist/runtime/operators/audit.d.ts +64 -0
- package/dist/runtime/operators/audit.js +56 -0
- package/dist/runtime/operators/auth.d.ts +29 -0
- package/dist/runtime/operators/auth.js +42 -0
- package/dist/runtime/operators/export.d.ts +68 -0
- package/dist/runtime/operators/export.js +137 -0
- package/dist/runtime/operators/grants.d.ts +45 -0
- package/dist/runtime/operators/grants.js +40 -0
- package/dist/runtime/operators/repair.d.ts +206 -0
- package/dist/runtime/operators/repair.js +226 -0
- package/dist/runtime/operators/routes.d.ts +35 -0
- package/dist/runtime/operators/routes.js +190 -0
- package/dist/runtime/operators/seed.d.ts +123 -0
- package/dist/runtime/operators/seed.js +123 -0
- package/dist/runtime/payloads/versions.d.ts +65 -0
- package/dist/runtime/payloads/versions.js +240 -0
- package/dist/runtime/peering/authority.d.ts +42 -0
- package/dist/runtime/peering/authority.js +132 -0
- package/dist/runtime/peering/credentials.d.ts +21 -0
- package/dist/runtime/peering/credentials.js +13 -0
- package/dist/runtime/peering/transport.d.ts +51 -0
- package/dist/runtime/peering/transport.js +175 -0
- package/dist/runtime/queries.d.ts +18 -0
- package/dist/runtime/queries.js +169 -0
- package/dist/runtime/readiness.d.ts +36 -0
- package/dist/runtime/readiness.js +44 -0
- package/dist/runtime/registration.d.ts +58 -0
- package/dist/runtime/registration.js +186 -0
- package/dist/runtime/request.d.ts +158 -0
- package/dist/runtime/request.js +102 -0
- package/dist/runtime/retry.d.ts +8 -0
- package/dist/runtime/retry.js +11 -0
- package/dist/runtime/runner.d.ts +93 -0
- package/dist/runtime/runner.js +122 -0
- package/dist/runtime/storage/codec.d.ts +39 -0
- package/dist/runtime/storage/codec.js +41 -0
- package/dist/runtime/storage/generation.d.ts +69 -0
- package/dist/runtime/storage/generation.js +49 -0
- package/dist/runtime/storage/placements.d.ts +15 -0
- package/dist/runtime/storage/placements.js +38 -0
- package/dist/runtime/storage/platform.d.ts +6 -0
- package/dist/runtime/storage/platform.js +9 -0
- package/dist/runtime/storage/retention.d.ts +73 -0
- package/dist/runtime/storage/retention.js +158 -0
- package/dist/runtime/subscriptions/identity.d.ts +31 -0
- package/dist/runtime/subscriptions/identity.js +45 -0
- package/dist/runtime/subscriptions/relay.d.ts +175 -0
- package/dist/runtime/subscriptions/relay.js +763 -0
- package/dist/runtime/subscriptions/storage.d.ts +40 -0
- package/dist/runtime/subscriptions/storage.js +98 -0
- package/dist/runtime/sweeps.d.ts +39 -0
- package/dist/runtime/sweeps.js +54 -0
- package/dist/runtime/telemetry/defects.d.ts +57 -0
- package/dist/runtime/telemetry/defects.js +43 -0
- package/dist/runtime/telemetry/metrics.d.ts +52 -0
- package/dist/runtime/telemetry/metrics.js +138 -0
- package/dist/runtime/telemetry/routes.d.ts +19 -0
- package/dist/runtime/telemetry/routes.js +18 -0
- package/dist/runtime/telemetry/sampler.d.ts +26 -0
- package/dist/runtime/telemetry/sampler.js +101 -0
- package/dist/runtime/telemetry/spans.d.ts +38 -0
- package/dist/runtime/telemetry/spans.js +44 -0
- package/dist/runtime/telemetry/usage.d.ts +52 -0
- package/dist/runtime/telemetry/usage.js +30 -0
- package/dist/runtime/topology/admission.d.ts +13 -0
- package/dist/runtime/topology/admission.js +36 -0
- package/dist/runtime/topology/locks.d.ts +56 -0
- package/dist/runtime/topology/locks.js +81 -0
- package/dist/runtime/topology/messages.d.ts +15 -0
- package/dist/runtime/topology/messages.js +32 -0
- package/dist/runtime/turn/admission.d.ts +22 -0
- package/dist/runtime/turn/admission.js +41 -0
- package/dist/runtime/turn/blobs.d.ts +38 -0
- package/dist/runtime/turn/blobs.js +215 -0
- package/dist/runtime/turn/execute.d.ts +208 -0
- package/dist/runtime/turn/execute.js +972 -0
- package/dist/runtime/turn/group.d.ts +165 -0
- package/dist/runtime/turn/group.js +326 -0
- package/dist/runtime/turn/hooks.d.ts +44 -0
- package/dist/runtime/turn/hooks.js +28 -0
- package/dist/runtime/turn/outbox.d.ts +159 -0
- package/dist/runtime/turn/outbox.js +269 -0
- package/dist/runtime/turn/pipeline.d.ts +68 -0
- package/dist/runtime/turn/pipeline.js +83 -0
- package/dist/runtime/turn/receipt.d.ts +81 -0
- package/dist/runtime/turn/receipt.js +32 -0
- package/dist/runtime/turn/relay.d.ts +179 -0
- package/dist/runtime/turn/relay.js +685 -0
- package/dist/runtime/turn/rows.d.ts +43 -0
- package/dist/runtime/turn/rows.js +592 -0
- package/dist/runtime/workflows/compatibility.d.ts +125 -0
- package/dist/runtime/workflows/compatibility.js +285 -0
- package/dist/runtime/workflows/engine.d.ts +107 -0
- package/dist/runtime/workflows/engine.js +826 -0
- package/dist/runtime/workflows/manifest.d.ts +34 -0
- package/dist/runtime/workflows/manifest.js +39 -0
- package/dist/runtime/workflows/steps.d.ts +33 -0
- package/dist/runtime/workflows/steps.js +152 -0
- package/dist/serve/api.d.ts +99 -0
- package/dist/serve/api.js +403 -0
- package/dist/serve/assertion/binding.d.ts +41 -0
- package/dist/serve/assertion/binding.js +92 -0
- package/dist/serve/assertion/verify.d.ts +93 -0
- package/dist/serve/assertion/verify.js +189 -0
- package/dist/serve/auth.d.ts +200 -0
- package/dist/serve/auth.js +92 -0
- package/dist/serve/clock.d.ts +10 -0
- package/dist/serve/clock.js +25 -0
- package/dist/serve/jwt.d.ts +65 -0
- package/dist/serve/jwt.js +202 -0
- package/dist/serve/layer.d.ts +98 -0
- package/dist/serve/layer.js +809 -0
- package/dist/serve/mcp/endpoint.d.ts +39 -0
- package/dist/serve/mcp/endpoint.js +187 -0
- package/dist/serve/mcp/tools.d.ts +37 -0
- package/dist/serve/mcp/tools.js +125 -0
- package/dist/serve/origin.d.ts +6 -0
- package/dist/serve/origin.js +21 -0
- package/dist/serve/sessions/feed.d.ts +79 -0
- package/dist/serve/sessions/feed.js +115 -0
- package/dist/serve/sessions/socket.d.ts +56 -0
- package/dist/serve/sessions/socket.js +212 -0
- package/dist/serve/sessions/sse.d.ts +27 -0
- package/dist/serve/sessions/sse.js +26 -0
- package/dist/serve/sessions/stream.d.ts +9 -0
- package/dist/serve/sessions/stream.js +9 -0
- package/dist/serve/sessions/watch.d.ts +12 -0
- package/dist/serve/sessions/watch.js +11 -0
- package/dist/serve/wire.d.ts +16 -0
- package/dist/serve/wire.js +50 -0
- package/dist/state/blob.d.ts +71 -0
- package/dist/state/blob.js +0 -0
- package/dist/state/migration.d.ts +53 -0
- package/dist/state/migration.js +29 -0
- package/dist/tables/fleet.d.ts +170 -0
- package/dist/tables/fleet.js +214 -0
- package/dist/tables/owned.d.ts +250 -0
- package/dist/tables/owned.js +233 -0
- package/dist/testing/actor-test.d.ts +360 -0
- package/dist/testing/actor-test.js +337 -0
- package/dist/testing/cluster.d.ts +93 -0
- package/dist/testing/cluster.js +296 -0
- package/dist/testing/conformance/access.d.ts +5 -0
- package/dist/testing/conformance/access.js +531 -0
- package/dist/testing/conformance/admission.d.ts +11 -0
- package/dist/testing/conformance/admission.js +182 -0
- package/dist/testing/conformance/adoption.d.ts +2 -0
- package/dist/testing/conformance/adoption.js +1019 -0
- package/dist/testing/conformance/assertions.d.ts +202 -0
- package/dist/testing/conformance/assertions.js +849 -0
- package/dist/testing/conformance/batches.d.ts +41 -0
- package/dist/testing/conformance/batches.js +388 -0
- package/dist/testing/conformance/blobs.d.ts +14 -0
- package/dist/testing/conformance/blobs.js +405 -0
- package/dist/testing/conformance/capacity.d.ts +8 -0
- package/dist/testing/conformance/capacity.js +433 -0
- package/dist/testing/conformance/client.d.ts +5 -0
- package/dist/testing/conformance/client.js +719 -0
- package/dist/testing/conformance/cold-serve.d.ts +16 -0
- package/dist/testing/conformance/cold-serve.js +254 -0
- package/dist/testing/conformance/connections/actors.d.ts +1143 -0
- package/dist/testing/conformance/connections/actors.js +180 -0
- package/dist/testing/conformance/connections/harness.d.ts +1754 -0
- package/dist/testing/conformance/connections/harness.js +142 -0
- package/dist/testing/conformance/connections/holders.d.ts +4 -0
- package/dist/testing/conformance/connections/holders.js +165 -0
- package/dist/testing/conformance/connections/lifecycle.d.ts +4 -0
- package/dist/testing/conformance/connections/lifecycle.js +113 -0
- package/dist/testing/conformance/connections/limits.d.ts +4 -0
- package/dist/testing/conformance/connections/limits.js +127 -0
- package/dist/testing/conformance/connections/reauthorization.d.ts +4 -0
- package/dist/testing/conformance/connections/reauthorization.js +170 -0
- package/dist/testing/conformance/connections/resync.d.ts +4 -0
- package/dist/testing/conformance/connections/resync.js +360 -0
- package/dist/testing/conformance/connections/takeover.d.ts +4 -0
- package/dist/testing/conformance/connections/takeover.js +287 -0
- package/dist/testing/conformance/connections.d.ts +4 -0
- package/dist/testing/conformance/connections.js +15 -0
- package/dist/testing/conformance/content-blobs.d.ts +16 -0
- package/dist/testing/conformance/content-blobs.js +534 -0
- package/dist/testing/conformance/counter.d.ts +16 -0
- package/dist/testing/conformance/counter.js +813 -0
- package/dist/testing/conformance/cron.d.ts +5 -0
- package/dist/testing/conformance/cron.js +665 -0
- package/dist/testing/conformance/drain.d.ts +26 -0
- package/dist/testing/conformance/drain.js +540 -0
- package/dist/testing/conformance/effect-control.d.ts +38 -0
- package/dist/testing/conformance/effect-control.js +1059 -0
- package/dist/testing/conformance/effects.d.ts +23 -0
- package/dist/testing/conformance/effects.js +432 -0
- package/dist/testing/conformance/events.d.ts +28 -0
- package/dist/testing/conformance/events.js +335 -0
- package/dist/testing/conformance/export.d.ts +2 -0
- package/dist/testing/conformance/export.js +368 -0
- package/dist/testing/conformance/fleet.d.ts +444 -0
- package/dist/testing/conformance/fleet.js +1009 -0
- package/dist/testing/conformance/groups.d.ts +7 -0
- package/dist/testing/conformance/groups.js +353 -0
- package/dist/testing/conformance/heap.d.ts +3 -0
- package/dist/testing/conformance/heap.js +149 -0
- package/dist/testing/conformance/http.d.ts +2809 -0
- package/dist/testing/conformance/http.js +1234 -0
- package/dist/testing/conformance/inspection-views.d.ts +8 -0
- package/dist/testing/conformance/inspection-views.js +272 -0
- package/dist/testing/conformance/inspector.d.ts +7 -0
- package/dist/testing/conformance/inspector.js +650 -0
- package/dist/testing/conformance/mint.d.ts +58 -0
- package/dist/testing/conformance/mint.js +692 -0
- package/dist/testing/conformance/multi-runner.d.ts +8 -0
- package/dist/testing/conformance/multi-runner.js +403 -0
- package/dist/testing/conformance/neki/plan.d.ts +19 -0
- package/dist/testing/conformance/neki/plan.js +30 -0
- package/dist/testing/conformance/observability.d.ts +3 -0
- package/dist/testing/conformance/observability.js +343 -0
- package/dist/testing/conformance/offline.d.ts +4 -0
- package/dist/testing/conformance/offline.js +474 -0
- package/dist/testing/conformance/operator-harness.d.ts +57 -0
- package/dist/testing/conformance/operator-harness.js +78 -0
- package/dist/testing/conformance/operator.d.ts +3 -0
- package/dist/testing/conformance/operator.js +379 -0
- package/dist/testing/conformance/outbox-cross-shard.d.ts +14 -0
- package/dist/testing/conformance/outbox-cross-shard.js +160 -0
- package/dist/testing/conformance/outbox.d.ts +36 -0
- package/dist/testing/conformance/outbox.js +437 -0
- package/dist/testing/conformance/payload-migrations.d.ts +3 -0
- package/dist/testing/conformance/payload-migrations.js +612 -0
- package/dist/testing/conformance/pipeline.d.ts +3 -0
- package/dist/testing/conformance/pipeline.js +1040 -0
- package/dist/testing/conformance/placement.d.ts +22 -0
- package/dist/testing/conformance/placement.js +539 -0
- package/dist/testing/conformance/platform.d.ts +40 -0
- package/dist/testing/conformance/platform.js +101 -0
- package/dist/testing/conformance/progress.d.ts +39 -0
- package/dist/testing/conformance/progress.js +666 -0
- package/dist/testing/conformance/properties.d.ts +6 -0
- package/dist/testing/conformance/properties.js +295 -0
- package/dist/testing/conformance/protocols.d.ts +4 -0
- package/dist/testing/conformance/protocols.js +618 -0
- package/dist/testing/conformance/provider/advertise.d.ts +21 -0
- package/dist/testing/conformance/provider/advertise.js +44 -0
- package/dist/testing/conformance/read-your-writes.d.ts +20 -0
- package/dist/testing/conformance/read-your-writes.js +192 -0
- package/dist/testing/conformance/reducers.d.ts +8 -0
- package/dist/testing/conformance/reducers.js +258 -0
- package/dist/testing/conformance/relay.d.ts +42 -0
- package/dist/testing/conformance/relay.js +1115 -0
- package/dist/testing/conformance/restore.d.ts +43 -0
- package/dist/testing/conformance/restore.js +341 -0
- package/dist/testing/conformance/retention.d.ts +14 -0
- package/dist/testing/conformance/retention.js +463 -0
- package/dist/testing/conformance/rls.d.ts +24 -0
- package/dist/testing/conformance/rls.js +576 -0
- package/dist/testing/conformance/simulation.d.ts +31 -0
- package/dist/testing/conformance/simulation.js +167 -0
- package/dist/testing/conformance/single-shard.d.ts +2 -0
- package/dist/testing/conformance/single-shard.js +125 -0
- package/dist/testing/conformance/singleton.d.ts +3 -0
- package/dist/testing/conformance/singleton.js +293 -0
- package/dist/testing/conformance/statements.d.ts +60 -0
- package/dist/testing/conformance/statements.js +108 -0
- package/dist/testing/conformance/streams.d.ts +7 -0
- package/dist/testing/conformance/streams.js +280 -0
- package/dist/testing/conformance/subscriptions/access.d.ts +4 -0
- package/dist/testing/conformance/subscriptions/access.js +98 -0
- package/dist/testing/conformance/subscriptions/actors.d.ts +4910 -0
- package/dist/testing/conformance/subscriptions/actors.js +372 -0
- package/dist/testing/conformance/subscriptions/cluster.d.ts +4 -0
- package/dist/testing/conformance/subscriptions/cluster.js +89 -0
- package/dist/testing/conformance/subscriptions/delivery.d.ts +4 -0
- package/dist/testing/conformance/subscriptions/delivery.js +253 -0
- package/dist/testing/conformance/subscriptions/deploys.d.ts +4 -0
- package/dist/testing/conformance/subscriptions/deploys.js +162 -0
- package/dist/testing/conformance/subscriptions/epochs.d.ts +4 -0
- package/dist/testing/conformance/subscriptions/epochs.js +169 -0
- package/dist/testing/conformance/subscriptions/failures.d.ts +4 -0
- package/dist/testing/conformance/subscriptions/failures.js +108 -0
- package/dist/testing/conformance/subscriptions/feeds.d.ts +4 -0
- package/dist/testing/conformance/subscriptions/feeds.js +218 -0
- package/dist/testing/conformance/subscriptions/harness.d.ts +124 -0
- package/dist/testing/conformance/subscriptions/harness.js +143 -0
- package/dist/testing/conformance/subscriptions/operator.d.ts +4 -0
- package/dist/testing/conformance/subscriptions/operator.js +128 -0
- package/dist/testing/conformance/subscriptions/retention.d.ts +4 -0
- package/dist/testing/conformance/subscriptions/retention.js +288 -0
- package/dist/testing/conformance/subscriptions/routing.d.ts +4 -0
- package/dist/testing/conformance/subscriptions/routing.js +179 -0
- package/dist/testing/conformance/subscriptions.d.ts +4 -0
- package/dist/testing/conformance/subscriptions.js +19 -0
- package/dist/testing/conformance/tables.d.ts +125 -0
- package/dist/testing/conformance/tables.js +664 -0
- package/dist/testing/conformance/transports/actors.d.ts +1907 -0
- package/dist/testing/conformance/transports/actors.js +163 -0
- package/dist/testing/conformance/transports/client.d.ts +3 -0
- package/dist/testing/conformance/transports/client.js +237 -0
- package/dist/testing/conformance/transports/feeds.d.ts +3 -0
- package/dist/testing/conformance/transports/feeds.js +232 -0
- package/dist/testing/conformance/transports/harness.d.ts +93 -0
- package/dist/testing/conformance/transports/harness.js +84 -0
- package/dist/testing/conformance/transports/streams.d.ts +3 -0
- package/dist/testing/conformance/transports/streams.js +96 -0
- package/dist/testing/conformance/transports/websocket.d.ts +3 -0
- package/dist/testing/conformance/transports/websocket.js +384 -0
- package/dist/testing/conformance/transports/wire.d.ts +141 -0
- package/dist/testing/conformance/transports/wire.js +204 -0
- package/dist/testing/conformance/transports.d.ts +3 -0
- package/dist/testing/conformance/transports.js +11 -0
- package/dist/testing/conformance/watch.d.ts +59 -0
- package/dist/testing/conformance/watch.js +879 -0
- package/dist/testing/conformance/workflow-engine.d.ts +97 -0
- package/dist/testing/conformance/workflow-engine.js +253 -0
- package/dist/testing/conformance/workflow-versions.d.ts +3 -0
- package/dist/testing/conformance/workflow-versions.js +545 -0
- package/dist/testing/conformance/workflows/access.d.ts +4 -0
- package/dist/testing/conformance/workflows/access.js +147 -0
- package/dist/testing/conformance/workflows/actors.d.ts +2317 -0
- package/dist/testing/conformance/workflows/actors.js +305 -0
- package/dist/testing/conformance/workflows/basics.d.ts +4 -0
- package/dist/testing/conformance/workflows/basics.js +144 -0
- package/dist/testing/conformance/workflows/engine.d.ts +4 -0
- package/dist/testing/conformance/workflows/engine.js +80 -0
- package/dist/testing/conformance/workflows/guards.d.ts +4 -0
- package/dist/testing/conformance/workflows/guards.js +172 -0
- package/dist/testing/conformance/workflows/harness.d.ts +14 -0
- package/dist/testing/conformance/workflows/harness.js +44 -0
- package/dist/testing/conformance/workflows/recovery.d.ts +4 -0
- package/dist/testing/conformance/workflows/recovery.js +181 -0
- package/dist/testing/conformance/workflows/starts.d.ts +4 -0
- package/dist/testing/conformance/workflows/starts.js +57 -0
- package/dist/testing/conformance/workflows/suspension.d.ts +4 -0
- package/dist/testing/conformance/workflows/suspension.js +106 -0
- package/dist/testing/conformance/workflows/waits.d.ts +4 -0
- package/dist/testing/conformance/workflows/waits.js +284 -0
- package/dist/testing/conformance/workflows.d.ts +4 -0
- package/dist/testing/conformance/workflows.js +19 -0
- package/dist/testing/conformance.d.ts +330 -0
- package/dist/testing/conformance.js +364 -0
- package/dist/testing/database.d.ts +31 -0
- package/dist/testing/database.js +70 -0
- package/dist/testing/foundation.d.ts +41 -0
- package/dist/testing/foundation.js +517 -0
- package/dist/testing/index.d.ts +20 -0
- package/dist/testing/index.js +12 -0
- package/dist/testing/property.d.ts +40 -0
- package/dist/testing/property.js +95 -0
- package/dist/testing/simulate-cluster.d.ts +112 -0
- package/dist/testing/simulate-cluster.js +257 -0
- package/dist/testing/simulate.d.ts +90 -0
- package/dist/testing/simulate.js +127 -0
- package/package.json +1 -0
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import { Data, Deferred, Effect } from "effect";
|
|
2
|
+
import { SqlClient, type Statement } from "effect/sql";
|
|
3
|
+
import type { JobFailure, JobRoute, RegisteredJob } from "../members.ts";
|
|
4
|
+
import type { progressPool } from "./progress.ts";
|
|
5
|
+
/** A job row as a claim returned it. */
|
|
6
|
+
export interface ClaimedJob {
|
|
7
|
+
readonly routing_key: string;
|
|
8
|
+
readonly intent_id: string;
|
|
9
|
+
readonly attempts: number;
|
|
10
|
+
readonly last_error: string | null;
|
|
11
|
+
readonly ambiguous: boolean;
|
|
12
|
+
readonly tenant_id: string;
|
|
13
|
+
readonly actor_type: string;
|
|
14
|
+
readonly actor_id: string;
|
|
15
|
+
readonly command: string;
|
|
16
|
+
readonly payload: string;
|
|
17
|
+
readonly payload_version: number;
|
|
18
|
+
readonly caller: string;
|
|
19
|
+
/** The claim's `due_at_ms`: the lease end the claim wrote. */
|
|
20
|
+
readonly claimed_until: string;
|
|
21
|
+
/** Cancelled by a turn: settled with what is known, never attempted again. */
|
|
22
|
+
readonly cancelled: boolean;
|
|
23
|
+
/** An earlier attempt may have applied the call. */
|
|
24
|
+
readonly maybe_applied: boolean;
|
|
25
|
+
/** Its retries ran out, or an attempt's failure was final, before this claim. */
|
|
26
|
+
readonly exhausted: boolean;
|
|
27
|
+
}
|
|
28
|
+
/** One job type of one actor whose attempts run under a per-actor cap. */
|
|
29
|
+
export interface CappedGroup {
|
|
30
|
+
readonly routing_key: string;
|
|
31
|
+
readonly tenant_id: string;
|
|
32
|
+
readonly actor_type: string;
|
|
33
|
+
readonly actor_id: string;
|
|
34
|
+
readonly command: string;
|
|
35
|
+
}
|
|
36
|
+
/** The job rows of `group`, as the outbox row aliased `o`. */
|
|
37
|
+
export declare const groupRow: ({ sql, group, }: {
|
|
38
|
+
readonly sql: SqlClient.SqlClient;
|
|
39
|
+
readonly group: CappedGroup;
|
|
40
|
+
}) => Statement.Statement<import("effect/sql/SqlConnection").Row>;
|
|
41
|
+
/**
|
|
42
|
+
* The actor's shard-local generation row serializes claims and wakes of its
|
|
43
|
+
* capped jobs, and conflicts with an actor turn's own lock on it. The lock
|
|
44
|
+
* is `NO KEY UPDATE` so it does not block the key-share lock a settling
|
|
45
|
+
* attempt's dead-letter insert takes on the row while it holds the job row
|
|
46
|
+
* this claim then waits for; a stronger lock would deadlock the two.
|
|
47
|
+
*/
|
|
48
|
+
export declare const groupLock: ({ sql, group, }: {
|
|
49
|
+
readonly sql: SqlClient.SqlClient;
|
|
50
|
+
readonly group: CappedGroup;
|
|
51
|
+
}) => Statement.Statement<import("effect/sql/SqlConnection").Row>;
|
|
52
|
+
/**
|
|
53
|
+
* Makes the oldest waiting row of `group` due now, after one of its attempts
|
|
54
|
+
* settled. It takes the group's lock like a claim, so it never overlaps one:
|
|
55
|
+
* a claim's `SKIP LOCKED` would pass over the row this update holds and start
|
|
56
|
+
* a younger row ahead of it, breaking enqueue order. The lock also means no
|
|
57
|
+
* claim is taking the row while the update reads it. The outer guard refuses
|
|
58
|
+
* a row that is running by the time the update reaches it, so a wake never
|
|
59
|
+
* moves a claimed attempt's lease end to now, which would stop the cap
|
|
60
|
+
* counting an attempt that still runs.
|
|
61
|
+
*/
|
|
62
|
+
export declare const wakeWaiting: ({ sql, group, at, }: {
|
|
63
|
+
readonly sql: SqlClient.SqlClient;
|
|
64
|
+
readonly group: CappedGroup;
|
|
65
|
+
readonly at: number;
|
|
66
|
+
}) => Effect.Effect<readonly import("effect/sql/SqlConnection").Row[], import("effect/sql/SqlError").SqlError, never>;
|
|
67
|
+
/**
|
|
68
|
+
* What one claim of a job reported, decided from the executor's exit and the
|
|
69
|
+
* claim alone, before the row is written. `Rejected` is a result the
|
|
70
|
+
* `onSuccess` route cannot accept: the provider applied the call, so it is
|
|
71
|
+
* final and ambiguous. `Interrupted` is an attempt stopped by its
|
|
72
|
+
* cancellation; `Unattempted` a cancelled or exhausted row claimed only to
|
|
73
|
+
* be settled.
|
|
74
|
+
*/
|
|
75
|
+
export type Reported = Data.TaggedEnum<{
|
|
76
|
+
Succeeded: {
|
|
77
|
+
readonly success: JobRoute | undefined;
|
|
78
|
+
readonly cancelled: JobRoute | undefined;
|
|
79
|
+
};
|
|
80
|
+
Rejected: {
|
|
81
|
+
readonly failure: JobFailure;
|
|
82
|
+
readonly cancelled: JobRoute | undefined;
|
|
83
|
+
};
|
|
84
|
+
Failed: {
|
|
85
|
+
readonly failure: JobFailure;
|
|
86
|
+
};
|
|
87
|
+
Interrupted: {};
|
|
88
|
+
Unattempted: {};
|
|
89
|
+
}>;
|
|
90
|
+
/** Constructors and matchers for `Reported`. */
|
|
91
|
+
export declare const Reported: {
|
|
92
|
+
readonly $is: <Tag extends "Failed" | "Interrupted" | "Rejected" | "Succeeded" | "Unattempted">(tag: Tag) => (u: unknown) => u is Extract<{
|
|
93
|
+
readonly _tag: "Failed";
|
|
94
|
+
readonly failure: JobFailure;
|
|
95
|
+
}, {
|
|
96
|
+
readonly _tag: Tag;
|
|
97
|
+
}> | Extract<{
|
|
98
|
+
readonly _tag: "Interrupted";
|
|
99
|
+
}, {
|
|
100
|
+
readonly _tag: Tag;
|
|
101
|
+
}> | Extract<{
|
|
102
|
+
readonly _tag: "Rejected";
|
|
103
|
+
readonly failure: JobFailure;
|
|
104
|
+
readonly cancelled: JobRoute | undefined;
|
|
105
|
+
}, {
|
|
106
|
+
readonly _tag: Tag;
|
|
107
|
+
}> | Extract<{
|
|
108
|
+
readonly _tag: "Succeeded";
|
|
109
|
+
readonly success: JobRoute | undefined;
|
|
110
|
+
readonly cancelled: JobRoute | undefined;
|
|
111
|
+
}, {
|
|
112
|
+
readonly _tag: Tag;
|
|
113
|
+
}> | Extract<{
|
|
114
|
+
readonly _tag: "Unattempted";
|
|
115
|
+
}, {
|
|
116
|
+
readonly _tag: Tag;
|
|
117
|
+
}>;
|
|
118
|
+
readonly $match: {
|
|
119
|
+
<Cases extends { readonly [Tag in "Failed" | "Interrupted" | "Rejected" | "Succeeded" | "Unattempted"]: (args: Extract<{
|
|
120
|
+
readonly _tag: "Failed";
|
|
121
|
+
readonly failure: JobFailure;
|
|
122
|
+
} | {
|
|
123
|
+
readonly _tag: "Interrupted";
|
|
124
|
+
} | {
|
|
125
|
+
readonly _tag: "Rejected";
|
|
126
|
+
readonly failure: JobFailure;
|
|
127
|
+
readonly cancelled: JobRoute | undefined;
|
|
128
|
+
} | {
|
|
129
|
+
readonly _tag: "Succeeded";
|
|
130
|
+
readonly success: JobRoute | undefined;
|
|
131
|
+
readonly cancelled: JobRoute | undefined;
|
|
132
|
+
} | {
|
|
133
|
+
readonly _tag: "Unattempted";
|
|
134
|
+
}, {
|
|
135
|
+
readonly _tag: Tag;
|
|
136
|
+
}>) => any; }>(cases: Cases): (value: {
|
|
137
|
+
readonly _tag: "Failed";
|
|
138
|
+
readonly failure: JobFailure;
|
|
139
|
+
} | {
|
|
140
|
+
readonly _tag: "Interrupted";
|
|
141
|
+
} | {
|
|
142
|
+
readonly _tag: "Rejected";
|
|
143
|
+
readonly failure: JobFailure;
|
|
144
|
+
readonly cancelled: JobRoute | undefined;
|
|
145
|
+
} | {
|
|
146
|
+
readonly _tag: "Succeeded";
|
|
147
|
+
readonly success: JobRoute | undefined;
|
|
148
|
+
readonly cancelled: JobRoute | undefined;
|
|
149
|
+
} | {
|
|
150
|
+
readonly _tag: "Unattempted";
|
|
151
|
+
}) => import("effect/Unify").Unify<ReturnType<Cases["Failed" | "Interrupted" | "Rejected" | "Succeeded" | "Unattempted"]>>;
|
|
152
|
+
<Cases extends { readonly [Tag in "Failed" | "Interrupted" | "Rejected" | "Succeeded" | "Unattempted"]: (args: Extract<{
|
|
153
|
+
readonly _tag: "Failed";
|
|
154
|
+
readonly failure: JobFailure;
|
|
155
|
+
} | {
|
|
156
|
+
readonly _tag: "Interrupted";
|
|
157
|
+
} | {
|
|
158
|
+
readonly _tag: "Rejected";
|
|
159
|
+
readonly failure: JobFailure;
|
|
160
|
+
readonly cancelled: JobRoute | undefined;
|
|
161
|
+
} | {
|
|
162
|
+
readonly _tag: "Succeeded";
|
|
163
|
+
readonly success: JobRoute | undefined;
|
|
164
|
+
readonly cancelled: JobRoute | undefined;
|
|
165
|
+
} | {
|
|
166
|
+
readonly _tag: "Unattempted";
|
|
167
|
+
}, {
|
|
168
|
+
readonly _tag: Tag;
|
|
169
|
+
}>) => any; }>(value: {
|
|
170
|
+
readonly _tag: "Failed";
|
|
171
|
+
readonly failure: JobFailure;
|
|
172
|
+
} | {
|
|
173
|
+
readonly _tag: "Interrupted";
|
|
174
|
+
} | {
|
|
175
|
+
readonly _tag: "Rejected";
|
|
176
|
+
readonly failure: JobFailure;
|
|
177
|
+
readonly cancelled: JobRoute | undefined;
|
|
178
|
+
} | {
|
|
179
|
+
readonly _tag: "Succeeded";
|
|
180
|
+
readonly success: JobRoute | undefined;
|
|
181
|
+
readonly cancelled: JobRoute | undefined;
|
|
182
|
+
} | {
|
|
183
|
+
readonly _tag: "Unattempted";
|
|
184
|
+
}, cases: Cases): import("effect/Unify").Unify<ReturnType<Cases["Failed" | "Interrupted" | "Rejected" | "Succeeded" | "Unattempted"]>>;
|
|
185
|
+
};
|
|
186
|
+
readonly Failed: Data.TaggedEnum.ConstructorFrom<{
|
|
187
|
+
readonly _tag: "Failed";
|
|
188
|
+
readonly failure: JobFailure;
|
|
189
|
+
}, "_tag">;
|
|
190
|
+
readonly Interrupted: Data.TaggedEnum.ConstructorFrom<{
|
|
191
|
+
readonly _tag: "Interrupted";
|
|
192
|
+
}, "_tag">;
|
|
193
|
+
readonly Rejected: Data.TaggedEnum.ConstructorFrom<{
|
|
194
|
+
readonly _tag: "Rejected";
|
|
195
|
+
readonly failure: JobFailure;
|
|
196
|
+
readonly cancelled: JobRoute | undefined;
|
|
197
|
+
}, "_tag">;
|
|
198
|
+
readonly Succeeded: Data.TaggedEnum.ConstructorFrom<{
|
|
199
|
+
readonly _tag: "Succeeded";
|
|
200
|
+
readonly success: JobRoute | undefined;
|
|
201
|
+
readonly cancelled: JobRoute | undefined;
|
|
202
|
+
}, "_tag">;
|
|
203
|
+
readonly Unattempted: Data.TaggedEnum.ConstructorFrom<{
|
|
204
|
+
readonly _tag: "Unattempted";
|
|
205
|
+
}, "_tag">;
|
|
206
|
+
};
|
|
207
|
+
/**
|
|
208
|
+
* How a pass handed a claimed row to its attempt: when the claim was sent,
|
|
209
|
+
* the cancellation check current at the claim and a way to read the next one,
|
|
210
|
+
* and the lease end the relay moves with clock jumps.
|
|
211
|
+
*/
|
|
212
|
+
interface Claim {
|
|
213
|
+
readonly at: bigint;
|
|
214
|
+
readonly signal: Deferred.Deferred<void>;
|
|
215
|
+
readonly next: () => Deferred.Deferred<void>;
|
|
216
|
+
readonly lease: {
|
|
217
|
+
until: number;
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* The job attempts of one runner's relay. `run` executes one claimed row and
|
|
222
|
+
* settles it; the returned effect reports whether the row reached a terminal
|
|
223
|
+
* settle, which closes the job's progress.
|
|
224
|
+
*
|
|
225
|
+
* An attempt renews its claim every `renewEveryMs` while it runs, which also
|
|
226
|
+
* picks up a cancellation committed on another runner; `signal` is the local
|
|
227
|
+
* cancellation check. The lease is measured on this runner from when the last
|
|
228
|
+
* claim or renewal was sent, so the database's lease can only end later, and
|
|
229
|
+
* an attempt that outlives it is interrupted, or never started, since another
|
|
230
|
+
* runner may hold the row and a started call can't be undone. A failed
|
|
231
|
+
* renewal retries at the next interval, and a renewal never shortens a
|
|
232
|
+
* deadline. The attempt is raced against its renewals, which are stopped and
|
|
233
|
+
* awaited before any settling write, so a late renewal can't overwrite a
|
|
234
|
+
* failure's backoff with a fresh lease.
|
|
235
|
+
*
|
|
236
|
+
* Settling first classifies the exit as `Reported`, then applies guarded
|
|
237
|
+
* writes in a fixed order until one takes: a success tries the uncancelled
|
|
238
|
+
* row, then the cancelled one, and otherwise is late; a failure is recorded
|
|
239
|
+
* at its attempt, then ends the row when it was final, the last, or
|
|
240
|
+
* cancelled. A failure is recorded before its dead letter, so a failed
|
|
241
|
+
* dead-letter transaction is retried with this attempt's cause and never
|
|
242
|
+
* reruns the provider. A late success marks the dead letter ambiguous, or
|
|
243
|
+
* records an ambiguous one when its cancellation already settled; it never
|
|
244
|
+
* routes a second outcome. A dead letter that loses to a cancellation settles
|
|
245
|
+
* the row as cancelled instead, and an attempt that never started keeps the
|
|
246
|
+
* row as ambiguous as earlier attempts left it (`maybe_applied`).
|
|
247
|
+
*/
|
|
248
|
+
export declare const jobAttempts: (options: {
|
|
249
|
+
readonly progress: Effect.Success<ReturnType<typeof progressPool>>;
|
|
250
|
+
readonly leaseMs: number;
|
|
251
|
+
readonly renewEveryMs: number;
|
|
252
|
+
readonly wake: Effect.Effect<void>;
|
|
253
|
+
}) => Effect.Effect<(row: ClaimedJob, registered: RegisteredJob, claim: Claim) => Effect.Effect<boolean, import("effect/sql/SqlError").SqlError, SqlClient.SqlClient>, never, SqlClient.SqlClient>;
|
|
254
|
+
export {};
|
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
import { Cause, Clock, Data, Deferred, Effect, Option, Result, Schema } from "effect";
|
|
2
|
+
import { SqlClient } from "effect/sql";
|
|
3
|
+
import { ActorRef, principal } from "../../identity/caller.js";
|
|
4
|
+
import { Request } from "../request.js";
|
|
5
|
+
import { count as tally, Metrics } from "../telemetry/metrics.js";
|
|
6
|
+
import { SpanNames } from "../telemetry/spans.js";
|
|
7
|
+
import { databaseTime } from "../turn/admission.js";
|
|
8
|
+
import { TurnHooks } from "../turn/hooks.js";
|
|
9
|
+
import { CallerJson } from "../turn/outbox.js";
|
|
10
|
+
/** The job rows of `group`, as the outbox row aliased `o`. */
|
|
11
|
+
export const groupRow = ({ sql, group, }) => sql `o.routing_key = ${BigInt(group.routing_key)} AND o.tenant_id = ${group.tenant_id}
|
|
12
|
+
AND o.actor_type = ${group.actor_type} AND o.actor_id = ${group.actor_id}
|
|
13
|
+
AND o.command = ${group.command} AND o.kind = 'job'`;
|
|
14
|
+
/**
|
|
15
|
+
* The actor's shard-local generation row serializes claims and wakes of its
|
|
16
|
+
* capped jobs, and conflicts with an actor turn's own lock on it. The lock
|
|
17
|
+
* is `NO KEY UPDATE` so it does not block the key-share lock a settling
|
|
18
|
+
* attempt's dead-letter insert takes on the row while it holds the job row
|
|
19
|
+
* this claim then waits for; a stronger lock would deadlock the two.
|
|
20
|
+
*/
|
|
21
|
+
export const groupLock = ({ sql, group, }) => sql `SELECT 1 FROM actor_generations
|
|
22
|
+
WHERE routing_key = ${BigInt(group.routing_key)} AND tenant_id = ${group.tenant_id}
|
|
23
|
+
AND actor_type = ${group.actor_type} AND actor_id = ${group.actor_id}
|
|
24
|
+
FOR NO KEY UPDATE`;
|
|
25
|
+
/**
|
|
26
|
+
* Makes the oldest waiting row of `group` due now, after one of its attempts
|
|
27
|
+
* settled. It takes the group's lock like a claim, so it never overlaps one:
|
|
28
|
+
* a claim's `SKIP LOCKED` would pass over the row this update holds and start
|
|
29
|
+
* a younger row ahead of it, breaking enqueue order. The lock also means no
|
|
30
|
+
* claim is taking the row while the update reads it. The outer guard refuses
|
|
31
|
+
* a row that is running by the time the update reaches it, so a wake never
|
|
32
|
+
* moves a claimed attempt's lease end to now, which would stop the cap
|
|
33
|
+
* counting an attempt that still runs.
|
|
34
|
+
*/
|
|
35
|
+
export const wakeWaiting = ({ sql, group, at, }) => sql.withTransaction(Effect.andThen(groupLock({ sql, group }), sql `UPDATE actor_outbox SET due_at_ms = least(due_at_ms, ${at}), waiting = false
|
|
36
|
+
WHERE waiting AND NOT running AND cancelled_at_ms IS NULL
|
|
37
|
+
AND (routing_key, intent_id) IN (
|
|
38
|
+
SELECT o.routing_key, o.intent_id FROM actor_outbox o
|
|
39
|
+
WHERE ${groupRow({ sql, group })} AND o.waiting AND NOT o.running
|
|
40
|
+
AND o.cancelled_at_ms IS NULL
|
|
41
|
+
ORDER BY o.ready_at_ms, o.intent_id LIMIT 1
|
|
42
|
+
FOR UPDATE OF o SKIP LOCKED
|
|
43
|
+
) RETURNING 1`));
|
|
44
|
+
/** Constructors and matchers for `Reported`. */
|
|
45
|
+
export const Reported = Data.taggedEnum();
|
|
46
|
+
/** What a cancelled job without a result reports: `Failed` only when no attempt can have applied the call. */
|
|
47
|
+
const known = (ambiguous, maybeApplied) => ambiguous || maybeApplied ? "Unknown" : "Failed";
|
|
48
|
+
const cancelledCause = (attempts) => `Cancelled while attempt ${attempts} was running; the provider may have applied it`;
|
|
49
|
+
/**
|
|
50
|
+
* The job attempts of one runner's relay. `run` executes one claimed row and
|
|
51
|
+
* settles it; the returned effect reports whether the row reached a terminal
|
|
52
|
+
* settle, which closes the job's progress.
|
|
53
|
+
*
|
|
54
|
+
* An attempt renews its claim every `renewEveryMs` while it runs, which also
|
|
55
|
+
* picks up a cancellation committed on another runner; `signal` is the local
|
|
56
|
+
* cancellation check. The lease is measured on this runner from when the last
|
|
57
|
+
* claim or renewal was sent, so the database's lease can only end later, and
|
|
58
|
+
* an attempt that outlives it is interrupted, or never started, since another
|
|
59
|
+
* runner may hold the row and a started call can't be undone. A failed
|
|
60
|
+
* renewal retries at the next interval, and a renewal never shortens a
|
|
61
|
+
* deadline. The attempt is raced against its renewals, which are stopped and
|
|
62
|
+
* awaited before any settling write, so a late renewal can't overwrite a
|
|
63
|
+
* failure's backoff with a fresh lease.
|
|
64
|
+
*
|
|
65
|
+
* Settling first classifies the exit as `Reported`, then applies guarded
|
|
66
|
+
* writes in a fixed order until one takes: a success tries the uncancelled
|
|
67
|
+
* row, then the cancelled one, and otherwise is late; a failure is recorded
|
|
68
|
+
* at its attempt, then ends the row when it was final, the last, or
|
|
69
|
+
* cancelled. A failure is recorded before its dead letter, so a failed
|
|
70
|
+
* dead-letter transaction is retried with this attempt's cause and never
|
|
71
|
+
* reruns the provider. A late success marks the dead letter ambiguous, or
|
|
72
|
+
* records an ambiguous one when its cancellation already settled; it never
|
|
73
|
+
* routes a second outcome. A dead letter that loses to a cancellation settles
|
|
74
|
+
* the row as cancelled instead, and an attempt that never started keeps the
|
|
75
|
+
* row as ambiguous as earlier attempts left it (`maybe_applied`).
|
|
76
|
+
*/
|
|
77
|
+
export const jobAttempts = Effect.fnUntraced(function* (options) {
|
|
78
|
+
const sql = yield* SqlClient.SqlClient;
|
|
79
|
+
const hooks = yield* TurnHooks;
|
|
80
|
+
const { progress, leaseMs, renewEveryMs } = options;
|
|
81
|
+
const requestOf = (row) => Schema.decodeEffect(CallerJson)(row.caller).pipe(Effect.flatMap((caller) => Schema.decodeEffect(Request)({
|
|
82
|
+
ref: { tenant: row.tenant_id, actor: row.actor_type, id: row.actor_id },
|
|
83
|
+
caller,
|
|
84
|
+
command: row.command,
|
|
85
|
+
commandId: row.intent_id,
|
|
86
|
+
payload: row.payload,
|
|
87
|
+
})));
|
|
88
|
+
const run = Effect.fnUntraced(function* (row, registered, claim) {
|
|
89
|
+
const routingKey = BigInt(row.routing_key);
|
|
90
|
+
const annotate = Effect.annotateLogs({
|
|
91
|
+
actor: row.actor_type,
|
|
92
|
+
id: row.actor_id,
|
|
93
|
+
tenant: row.tenant_id,
|
|
94
|
+
job: row.command,
|
|
95
|
+
jobId: row.intent_id,
|
|
96
|
+
});
|
|
97
|
+
const jobRow = sql `routing_key = ${routingKey} AND intent_id = ${row.intent_id}
|
|
98
|
+
AND kind = 'job'`;
|
|
99
|
+
const guardOf = (attempt, cancelled) => sql `${jobRow} ${attempt === undefined ? sql.literal("") : sql `AND attempts = ${attempt}`}
|
|
100
|
+
AND cancelled_at_ms IS ${sql.literal(cancelled ? "NOT NULL" : "NULL")}`;
|
|
101
|
+
const write = (route, guard) => Effect.gen(function* () {
|
|
102
|
+
const at = yield* databaseTime;
|
|
103
|
+
const settled = route === undefined
|
|
104
|
+
? yield* sql `DELETE FROM actor_outbox WHERE ${guard} RETURNING 1`
|
|
105
|
+
: yield* sql `UPDATE actor_outbox SET kind = 'intent', command = ${route.command},
|
|
106
|
+
payload = ${route.payload}, payload_version = 0, due_at_ms = ${at},
|
|
107
|
+
scheduled_at_ms = ${at}, attempts = 0, last_error = NULL, ambiguous = false,
|
|
108
|
+
running = false, timer_key = NULL
|
|
109
|
+
WHERE ${guard} RETURNING 1`;
|
|
110
|
+
return settled.length > 0;
|
|
111
|
+
});
|
|
112
|
+
/** A capped success retries while a newer attempt's lease is live and the row is still there. */
|
|
113
|
+
const writeSuccess = (route, guard, after) => Effect.gen(function* () {
|
|
114
|
+
while (true) {
|
|
115
|
+
const newer = (at) => sql `(attempts > ${after} AND running AND due_at_ms > ${at})`;
|
|
116
|
+
if (yield* write(route, sql `${guard} AND NOT ${newer(yield* databaseTime)}`))
|
|
117
|
+
return true;
|
|
118
|
+
const held = yield* sql `SELECT ${newer(yield* databaseTime)} AS live FROM actor_outbox WHERE ${guard}`;
|
|
119
|
+
if (held.length === 0)
|
|
120
|
+
return false;
|
|
121
|
+
if (held[0].live)
|
|
122
|
+
yield* Effect.sleep(renewEveryMs);
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
const apply = (terminal, after = row.attempts) => Effect.gen(function* () {
|
|
126
|
+
const guard = guardOf(terminal.attempt, terminal.cancelled);
|
|
127
|
+
if (terminal.letter === undefined)
|
|
128
|
+
return terminal.attempt === undefined && registered.perActor !== undefined
|
|
129
|
+
? yield* writeSuccess(terminal.route, guard, after)
|
|
130
|
+
: yield* write(terminal.route, guard);
|
|
131
|
+
const letter = terminal.letter;
|
|
132
|
+
return yield* sql.withTransaction(Effect.gen(function* () {
|
|
133
|
+
if (!(yield* write(terminal.route, guard)))
|
|
134
|
+
return false;
|
|
135
|
+
yield* Effect.logWarning("Job dead-lettered after its last attempt", letter.cause).pipe(annotate);
|
|
136
|
+
yield* tally(Metrics.deadLetters, { actor_type: row.actor_type, job: row.command }, 1);
|
|
137
|
+
yield* sql `INSERT INTO actor_dead_letters (routing_key, job_id, tenant_id, actor_type,
|
|
138
|
+
actor_id, job, payload, payload_version, attempts, cause, ambiguous, dead_at_ms)
|
|
139
|
+
VALUES (${routingKey}, ${row.intent_id}, ${row.tenant_id}, ${row.actor_type},
|
|
140
|
+
${row.actor_id}, ${row.command}, ${row.payload}, ${row.payload_version},
|
|
141
|
+
${letter.attempts}, ${letter.cause}, ${letter.ambiguous}, ${yield* databaseTime})`;
|
|
142
|
+
const request = yield* requestOf(row).pipe(Effect.option);
|
|
143
|
+
if (Option.isSome(request))
|
|
144
|
+
yield* hooks.at("beforeDeadLetterCommit", request.value);
|
|
145
|
+
return true;
|
|
146
|
+
}));
|
|
147
|
+
}).pipe(Effect.tap((settled) => settled && terminal.route !== undefined ? options.wake : Effect.void));
|
|
148
|
+
const deadLetter = (attempts, cause, ambiguous, cancelled) => Effect.gen(function* () {
|
|
149
|
+
const letter = { jobId: row.intent_id, attempts, cause, ambiguous };
|
|
150
|
+
return yield* apply({
|
|
151
|
+
route: yield* registered.deadLetter(row.payload, row.payload_version, letter),
|
|
152
|
+
attempt: attempts,
|
|
153
|
+
cancelled,
|
|
154
|
+
letter,
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
/**
|
|
158
|
+
* Settles a cancelled job that has no result. Without an `onCancelled`
|
|
159
|
+
* route, an unknown outcome is dead-lettered as ambiguous and a failed
|
|
160
|
+
* one is dropped with a log line.
|
|
161
|
+
*/
|
|
162
|
+
const settleCancelled = (attempts, outcome, cause) => Effect.gen(function* () {
|
|
163
|
+
const ambiguous = outcome === "Unknown";
|
|
164
|
+
if (registered.routesCancelled) {
|
|
165
|
+
const route = yield* registered.cancelled(row.payload, row.payload_version, {
|
|
166
|
+
jobId: row.intent_id,
|
|
167
|
+
attempts,
|
|
168
|
+
outcome: { _tag: outcome, cause },
|
|
169
|
+
ambiguous,
|
|
170
|
+
});
|
|
171
|
+
if (route !== undefined)
|
|
172
|
+
return yield* apply({ route, attempt: attempts, cancelled: true });
|
|
173
|
+
}
|
|
174
|
+
if (ambiguous)
|
|
175
|
+
return yield* deadLetter(attempts, cause, true, true);
|
|
176
|
+
const dropped = yield* apply({ route: undefined, attempt: attempts, cancelled: true });
|
|
177
|
+
if (dropped)
|
|
178
|
+
yield* Effect.logInfo("Cancelled job dropped after a failed attempt", cause).pipe(Effect.annotateLogs({ attempt: attempts }), annotate);
|
|
179
|
+
return dropped;
|
|
180
|
+
});
|
|
181
|
+
/** Dead-letters the row at `attempts` unless a cancellation took it first, which then settles it. */
|
|
182
|
+
const exhaust = (attempts, cause, ambiguous) => Effect.gen(function* () {
|
|
183
|
+
if (yield* deadLetter(attempts, cause, ambiguous, false))
|
|
184
|
+
return true;
|
|
185
|
+
const [cancelled] = yield* sql `SELECT maybe_applied
|
|
186
|
+
FROM actor_outbox WHERE ${guardOf(attempts, true)}`;
|
|
187
|
+
return cancelled === undefined
|
|
188
|
+
? false
|
|
189
|
+
: yield* settleCancelled(attempts, known(ambiguous, cancelled.maybe_applied), cause);
|
|
190
|
+
});
|
|
191
|
+
const warnAttempt = (message) => Effect.logWarning(message).pipe(Effect.annotateLogs({ attempt: row.attempts }), annotate);
|
|
192
|
+
/**
|
|
193
|
+
* A success no settle matched: the row already ended. It marks the dead
|
|
194
|
+
* letter ambiguous, or records an ambiguous one when the cancellation's
|
|
195
|
+
* route already committed; it never routes a second outcome.
|
|
196
|
+
*/
|
|
197
|
+
const late = (cancelledRoute) => Effect.gen(function* () {
|
|
198
|
+
const marked = yield* sql `UPDATE actor_dead_letters SET ambiguous = true
|
|
199
|
+
WHERE routing_key = ${routingKey} AND job_id = ${row.intent_id} RETURNING 1`;
|
|
200
|
+
if (marked.length > 0)
|
|
201
|
+
return yield* warnAttempt("Job succeeded after it was dead-lettered");
|
|
202
|
+
const reported = cancelledRoute?.command;
|
|
203
|
+
if (!registered.routesCancelled || reported === undefined)
|
|
204
|
+
return;
|
|
205
|
+
const recorded = yield* sql `INSERT INTO actor_dead_letters (routing_key, job_id,
|
|
206
|
+
tenant_id, actor_type, actor_id, job, payload, payload_version, attempts, cause,
|
|
207
|
+
ambiguous, dead_at_ms)
|
|
208
|
+
SELECT ${routingKey}, ${row.intent_id}, ${row.tenant_id}, ${row.actor_type},
|
|
209
|
+
${row.actor_id}, ${row.command}, ${row.payload}, ${row.payload_version}, ${row.attempts},
|
|
210
|
+
'Succeeded after it was cancelled', true, ${yield* databaseTime}
|
|
211
|
+
WHERE EXISTS (
|
|
212
|
+
SELECT 1 FROM actor_outbox WHERE routing_key = ${routingKey}
|
|
213
|
+
AND intent_id = ${row.intent_id} AND kind = 'intent' AND command = ${reported}
|
|
214
|
+
UNION ALL
|
|
215
|
+
SELECT 1 FROM actor_receipts WHERE routing_key = ${routingKey}
|
|
216
|
+
AND tenant_id = ${row.tenant_id} AND actor_type = ${row.actor_type}
|
|
217
|
+
AND actor_id = ${row.actor_id} AND command_id = ${row.intent_id}
|
|
218
|
+
AND command = ${reported}
|
|
219
|
+
)
|
|
220
|
+
ON CONFLICT (routing_key, job_id) DO UPDATE SET ambiguous = true
|
|
221
|
+
RETURNING 1`;
|
|
222
|
+
if (recorded.length > 0)
|
|
223
|
+
yield* warnAttempt("Job succeeded after its cancellation settled");
|
|
224
|
+
});
|
|
225
|
+
/** Records a failure at its attempt; undefined when a newer attempt or a settle took the row. */
|
|
226
|
+
const record = (failure) => Effect.gen(function* () {
|
|
227
|
+
const attempt = row.attempts;
|
|
228
|
+
const { baseMs, maxMs } = registered.backoff;
|
|
229
|
+
const [recorded] = yield* sql `UPDATE actor_outbox
|
|
230
|
+
SET last_error = ${failure.cause},
|
|
231
|
+
ambiguous = ${failure.notStarted === true ? sql `maybe_applied` : sql `${failure.ambiguous}`},
|
|
232
|
+
running = false, final_failure = ${failure.final === true},
|
|
233
|
+
due_at_ms = ${(yield* databaseTime) + Math.min(baseMs * 2 ** (attempt - 1), maxMs)}
|
|
234
|
+
WHERE ${jobRow} AND attempts = ${attempt}
|
|
235
|
+
RETURNING cancelled_at_ms IS NOT NULL AS cancelled, maybe_applied, ambiguous`;
|
|
236
|
+
return recorded;
|
|
237
|
+
});
|
|
238
|
+
/**
|
|
239
|
+
* Records a failure, then ends the row when it was cancelled, final, or the
|
|
240
|
+
* last attempt. A `rejected` result succeeded at the provider, so it goes to
|
|
241
|
+
* `onCancelled` when the row was cancelled, and is late when no row took it.
|
|
242
|
+
*/
|
|
243
|
+
const failed = (failure, cancelledRoute, rejected) => Effect.gen(function* () {
|
|
244
|
+
const attempt = row.attempts;
|
|
245
|
+
const routesResult = cancelledRoute !== undefined && registered.routesCancelled;
|
|
246
|
+
if (routesResult &&
|
|
247
|
+
(yield* apply({ route: cancelledRoute, attempt: undefined, cancelled: true })))
|
|
248
|
+
return true;
|
|
249
|
+
const recorded = yield* record(failure);
|
|
250
|
+
if (recorded === undefined) {
|
|
251
|
+
if (rejected)
|
|
252
|
+
yield* late(cancelledRoute);
|
|
253
|
+
else
|
|
254
|
+
yield* warnAttempt("Job attempt failed after a newer attempt or a settle took its row");
|
|
255
|
+
return false;
|
|
256
|
+
}
|
|
257
|
+
if (recorded.cancelled) {
|
|
258
|
+
if (routesResult && (yield* apply({ route: cancelledRoute, attempt, cancelled: true })))
|
|
259
|
+
return true;
|
|
260
|
+
return yield* settleCancelled(attempt, known(recorded.ambiguous, recorded.maybe_applied), failure.cause);
|
|
261
|
+
}
|
|
262
|
+
if (failure.final === true || attempt >= registered.attempts)
|
|
263
|
+
return yield* exhaust(attempt, failure.cause, recorded.ambiguous);
|
|
264
|
+
yield* Effect.logWarning("Job attempt failed; retrying with backoff", failure.cause).pipe(Effect.annotateLogs({ attempt, ambiguous: recorded.ambiguous }), annotate);
|
|
265
|
+
yield* tally(Metrics.relayRetried, { kind: "job" }, 1);
|
|
266
|
+
return false;
|
|
267
|
+
});
|
|
268
|
+
const settle = Reported.$match({
|
|
269
|
+
Unattempted: () => {
|
|
270
|
+
const attempt = row.attempts;
|
|
271
|
+
if (row.cancelled && attempt === 0)
|
|
272
|
+
return apply({ route: undefined, attempt: 0, cancelled: true });
|
|
273
|
+
if (row.cancelled)
|
|
274
|
+
return settleCancelled(attempt, known(row.ambiguous, row.maybe_applied), row.last_error ??
|
|
275
|
+
(row.ambiguous || row.maybe_applied
|
|
276
|
+
? cancelledCause(attempt)
|
|
277
|
+
: "Failed before it was cancelled"));
|
|
278
|
+
return exhaust(attempt, row.last_error ?? "No attempt reported", row.ambiguous);
|
|
279
|
+
},
|
|
280
|
+
Interrupted: () => Effect.logInfo("Job attempt interrupted by its cancellation").pipe(Effect.annotateLogs({ attempt: row.attempts }), annotate, Effect.andThen(settleCancelled(row.attempts, "Unknown", cancelledCause(row.attempts)))),
|
|
281
|
+
Succeeded: ({ success, cancelled }) => Effect.gen(function* () {
|
|
282
|
+
if (yield* apply({ route: success, attempt: undefined, cancelled: false })) {
|
|
283
|
+
yield* tally(Metrics.relayDelivered, { kind: "job" }, 1);
|
|
284
|
+
return true;
|
|
285
|
+
}
|
|
286
|
+
const route = registered.routesCancelled ? cancelled : success;
|
|
287
|
+
if (yield* apply({ route, attempt: undefined, cancelled: true }))
|
|
288
|
+
return true;
|
|
289
|
+
yield* late(cancelled);
|
|
290
|
+
return false;
|
|
291
|
+
}),
|
|
292
|
+
Rejected: ({ failure, cancelled }) => failed(failure, cancelled, true),
|
|
293
|
+
Failed: ({ failure }) => failed(failure, undefined, false),
|
|
294
|
+
});
|
|
295
|
+
if (row.cancelled || row.exhausted)
|
|
296
|
+
return yield* settle(Reported.Unattempted());
|
|
297
|
+
const attempt = row.attempts;
|
|
298
|
+
const request = yield* requestOf(row).pipe(Effect.orDie);
|
|
299
|
+
const ref = ActorRef.make(request.ref);
|
|
300
|
+
const leaseNanos = BigInt(leaseMs) * 1000000n;
|
|
301
|
+
let confirmed = claim.at;
|
|
302
|
+
yield* hooks.at("afterClaim", request);
|
|
303
|
+
yield* hooks.at("beforeExecute", request);
|
|
304
|
+
if ((yield* Clock.currentTimeNanos) - confirmed >= leaseNanos) {
|
|
305
|
+
yield* warnAttempt("Job attempt outlived its lease before it started");
|
|
306
|
+
return false;
|
|
307
|
+
}
|
|
308
|
+
let signal = claim.signal;
|
|
309
|
+
const renewals = Effect.gen(function* () {
|
|
310
|
+
while (true) {
|
|
311
|
+
yield* Deferred.await(signal).pipe(Effect.timeoutOrElse({ duration: renewEveryMs, orElse: () => Effect.void }));
|
|
312
|
+
signal = claim.next();
|
|
313
|
+
const sent = yield* Clock.currentTimeNanos;
|
|
314
|
+
const renewed = yield* Effect.gen(function* () {
|
|
315
|
+
yield* hooks.at("beforeRenew", request);
|
|
316
|
+
return yield* sql `UPDATE actor_outbox
|
|
317
|
+
SET due_at_ms = greatest(due_at_ms, ${(yield* databaseTime) + leaseMs})
|
|
318
|
+
WHERE ${jobRow} AND attempts = ${attempt}
|
|
319
|
+
RETURNING cancelled_at_ms IS NOT NULL AS cancelled, due_at_ms::text AS due_at_ms`.pipe(Effect.uninterruptible);
|
|
320
|
+
}).pipe(Effect.catchCause((cause) => Cause.hasInterruptsOnly(cause)
|
|
321
|
+
? Effect.interrupt
|
|
322
|
+
: Effect.logWarning("Job lease renewal failed", cause).pipe(annotate, Effect.as(undefined))));
|
|
323
|
+
if (renewed === undefined)
|
|
324
|
+
continue;
|
|
325
|
+
if (renewed.length === 0)
|
|
326
|
+
return "lost";
|
|
327
|
+
confirmed = sent;
|
|
328
|
+
claim.lease.until = Number(renewed[0].due_at_ms);
|
|
329
|
+
if (renewed[0].cancelled)
|
|
330
|
+
return "cancelled";
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
const deadline = Effect.gen(function* () {
|
|
334
|
+
while (true) {
|
|
335
|
+
const left = confirmed + leaseNanos - (yield* Clock.currentTimeNanos);
|
|
336
|
+
if (left <= 0n)
|
|
337
|
+
return "deadline";
|
|
338
|
+
yield* Effect.sleep(Number(left / 1000000n) + 1);
|
|
339
|
+
}
|
|
340
|
+
});
|
|
341
|
+
const slot = yield* progress.open({
|
|
342
|
+
ref,
|
|
343
|
+
jobId: row.intent_id,
|
|
344
|
+
job: row.command,
|
|
345
|
+
attempt,
|
|
346
|
+
everyMs: registered.progressEveryMs,
|
|
347
|
+
leaseUntil: () => claim.lease.until,
|
|
348
|
+
});
|
|
349
|
+
return yield* Effect.gen(function* () {
|
|
350
|
+
const outcome = yield* registered
|
|
351
|
+
.execute(row.payload, row.payload_version, {
|
|
352
|
+
jobId: row.intent_id,
|
|
353
|
+
attempt,
|
|
354
|
+
principal: principal(request.caller),
|
|
355
|
+
ref,
|
|
356
|
+
reporting: slot.active,
|
|
357
|
+
report: slot.offer,
|
|
358
|
+
})
|
|
359
|
+
.pipe(Effect.withSpan(SpanNames.job(row.actor_type, row.command), {
|
|
360
|
+
kind: "client",
|
|
361
|
+
attributes: {
|
|
362
|
+
"actor.type": row.actor_type,
|
|
363
|
+
"actor.tenant": row.tenant_id,
|
|
364
|
+
"actor.id": row.actor_id,
|
|
365
|
+
"job.name": row.command,
|
|
366
|
+
"job.id": row.intent_id,
|
|
367
|
+
"job.attempt": attempt,
|
|
368
|
+
},
|
|
369
|
+
}, { captureStackTrace: false }), Effect.result, Effect.raceFirst(renewals), Effect.raceFirst(deadline), Effect.ensuring(slot.close));
|
|
370
|
+
if (outcome === "lost") {
|
|
371
|
+
yield* warnAttempt("Job attempt lost its lease");
|
|
372
|
+
return false;
|
|
373
|
+
}
|
|
374
|
+
if (outcome === "deadline") {
|
|
375
|
+
yield* warnAttempt("Job attempt outlived its lease; interrupted");
|
|
376
|
+
return false;
|
|
377
|
+
}
|
|
378
|
+
if (outcome === "cancelled")
|
|
379
|
+
return yield* settle(Reported.Interrupted());
|
|
380
|
+
if (Result.isFailure(outcome))
|
|
381
|
+
return yield* settle(Reported.Failed({ failure: outcome.failure }));
|
|
382
|
+
const { success, cancelled, rejected } = outcome.success;
|
|
383
|
+
if (rejected === undefined || registered.routesCancelled)
|
|
384
|
+
yield* hooks.at("afterExecute", request);
|
|
385
|
+
return yield* settle(rejected === undefined
|
|
386
|
+
? Reported.Succeeded({ success, cancelled })
|
|
387
|
+
: Reported.Rejected({ failure: rejected, cancelled }));
|
|
388
|
+
}).pipe(Effect.ensuring(progress.forget(row.intent_id)));
|
|
389
|
+
});
|
|
390
|
+
/**
|
|
391
|
+
* Runs one claimed row and settles it. A terminal settle closes the job's
|
|
392
|
+
* progress; a retryable one leaves it open. A settled attempt of a capped
|
|
393
|
+
* job wakes the oldest waiting row of its actor.
|
|
394
|
+
*/
|
|
395
|
+
return (row, registered, claim) => {
|
|
396
|
+
const attempt = run(row, registered, claim).pipe(Effect.tap((terminal) => terminal
|
|
397
|
+
? requestOf(row).pipe(Effect.flatMap((request) => progress.closed({
|
|
398
|
+
ref: ActorRef.make(request.ref),
|
|
399
|
+
jobId: row.intent_id,
|
|
400
|
+
job: row.command,
|
|
401
|
+
attempt: row.attempts,
|
|
402
|
+
everyMs: registered.progressEveryMs,
|
|
403
|
+
})), Effect.ignore)
|
|
404
|
+
: Effect.void));
|
|
405
|
+
return registered.perActor === undefined
|
|
406
|
+
? attempt
|
|
407
|
+
: attempt.pipe(Effect.ensuring(Effect.gen(function* () {
|
|
408
|
+
const woke = yield* wakeWaiting({ sql, group: row, at: yield* databaseTime });
|
|
409
|
+
if (woke.length > 0)
|
|
410
|
+
yield* options.wake;
|
|
411
|
+
}).pipe(Effect.ignore)));
|
|
412
|
+
};
|
|
413
|
+
});
|