@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,122 @@
|
|
|
1
|
+
import { Context, Duration, Effect, HashRing, Layer, Option, PrimaryKey } from "effect";
|
|
2
|
+
import { MessageStorage, RunnerAddress, RunnerHealth, Runners, RunnerServer, RunnerStorage, Sharding, ShardingConfig, ShardId, } from "effect/cluster";
|
|
3
|
+
import { RpcSerialization, RpcServer } from "effect/rpc";
|
|
4
|
+
import { SocketServer } from "effect/socket";
|
|
5
|
+
import { SqlClient } from "effect/sql";
|
|
6
|
+
import { identity } from "./peering/credentials.js";
|
|
7
|
+
import { mtls } from "./peering/transport.js";
|
|
8
|
+
import { admissionSharding, MailboxRefusals } from "./topology/admission.js";
|
|
9
|
+
/**
|
|
10
|
+
* Whether a command to an entity on this runner is encoded and decoded the
|
|
11
|
+
* way a remote delivery is. Off by default: a local hop hands the owner the
|
|
12
|
+
* request the runtime built and validated, and only a remote hop needs the
|
|
13
|
+
* bytes. Test runtimes turn it on so every delivery still checks the request
|
|
14
|
+
* schema.
|
|
15
|
+
*/
|
|
16
|
+
export const LocalRequestSerialization = Context.Reference("@rikalabs/akter/runtime/runner/LocalRequestSerialization", { defaultValue: () => false });
|
|
17
|
+
/** Package-internal wiring shared by production runners and fault-injecting test runners. */
|
|
18
|
+
export class RunnerWiring extends Context.Service()("@rikalabs/akter/runtime/runner/RunnerWiring") {
|
|
19
|
+
}
|
|
20
|
+
/** The public runner's readiness checks acquired shards, not just a reachable database. */
|
|
21
|
+
export class RunnerReadiness extends Context.Service()("@rikalabs/akter/runtime/runner/RunnerReadiness") {
|
|
22
|
+
}
|
|
23
|
+
/** Builds assignment expectations independently of the runner's local acquisition state. */
|
|
24
|
+
export const acquiredShards = Effect.gen(function* () {
|
|
25
|
+
const config = yield* ShardingConfig.ShardingConfig;
|
|
26
|
+
const storage = yield* RunnerStorage.RunnerStorage;
|
|
27
|
+
const self = Option.getOrThrow(config.runnerAddress);
|
|
28
|
+
const key = PrimaryKey.value(self);
|
|
29
|
+
return RunnerReadiness.of({
|
|
30
|
+
acquired: (sharding) => Effect.gen(function* () {
|
|
31
|
+
const runners = yield* storage.getRunners;
|
|
32
|
+
if (!runners.some(([runner, healthy]) => healthy && PrimaryKey.value(runner.address) === key))
|
|
33
|
+
return false;
|
|
34
|
+
for (const group of config.assignedShardGroups) {
|
|
35
|
+
const ring = HashRing.make();
|
|
36
|
+
for (const [runner, healthy] of runners)
|
|
37
|
+
if (healthy && runner.groups.includes(group))
|
|
38
|
+
HashRing.add(ring, runner.address, { weight: runner.weight });
|
|
39
|
+
const expected = HashRing.getShards(ring, config.shardsPerGroup);
|
|
40
|
+
if (expected === undefined)
|
|
41
|
+
return false;
|
|
42
|
+
for (const [index, address] of expected.entries())
|
|
43
|
+
if (PrimaryKey.value(address) === key &&
|
|
44
|
+
!sharding.hasShardId(ShardId.make(group, index + 1)))
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
return true;
|
|
48
|
+
}).pipe(Effect.timeoutOption("2 seconds"), Effect.map(Option.getOrElse(() => false)), Effect.orElseSucceed(() => false)),
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
const address = (value, advertise) => {
|
|
52
|
+
if (value.host.trim().length === 0 ||
|
|
53
|
+
(advertise && ["0.0.0.0", "::", "*"].includes(value.host)) ||
|
|
54
|
+
!Number.isInteger(value.port) ||
|
|
55
|
+
value.port < 1 ||
|
|
56
|
+
value.port > 65535)
|
|
57
|
+
throw new Error("Runner address needs a host and a port between 1 and 65535; advertise a reachable host, not a wildcard");
|
|
58
|
+
return RunnerAddress.RunnerAddress.make(value);
|
|
59
|
+
};
|
|
60
|
+
const duration = (value, name, minimum = 1) => {
|
|
61
|
+
const result = Duration.fromInputUnsafe(value);
|
|
62
|
+
if (!Number.isFinite(Duration.toMillis(result)) || Duration.toMillis(result) < minimum)
|
|
63
|
+
throw new Error(`${name} must be finite and at least ${minimum} milliseconds`);
|
|
64
|
+
return result;
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Joins separate processes over TCP sockets. Provide this layer to
|
|
68
|
+
* `Actors.layer`; the framework keeps direct commands, SQL ownership, receipts,
|
|
69
|
+
* and outbox recovery, rather than enabling Cluster's persisted message store.
|
|
70
|
+
* A peer can deliver any runner message, so use `Runner.mtls` as the
|
|
71
|
+
* transport unless the network is isolated to this deployment's runners. The
|
|
72
|
+
* transport's own services stay in the runtime, so readiness sees whether a
|
|
73
|
+
* mutual TLS transport can still peer.
|
|
74
|
+
*/
|
|
75
|
+
export const socket = (options) => {
|
|
76
|
+
const shardsPerGroup = options.shardsPerGroup ?? 256;
|
|
77
|
+
if (!Number.isSafeInteger(shardsPerGroup) || shardsPerGroup < 1 || shardsPerGroup > 65536)
|
|
78
|
+
throw new Error("shardsPerGroup must be an integer between 1 and 65536");
|
|
79
|
+
const config = {
|
|
80
|
+
runnerAddress: Option.some(address(options.address, true)),
|
|
81
|
+
runnerListenAddress: Option.some(address(options.listenAddress ?? options.address, false)),
|
|
82
|
+
shardsPerGroup,
|
|
83
|
+
shardLockDisableAdvisory: true,
|
|
84
|
+
shardLockExpiration: duration(options.shardLockExpiration ?? "35 seconds", "shardLockExpiration", 3000),
|
|
85
|
+
shardLockRefreshInterval: duration(options.shardLockRefreshInterval ?? "10 seconds", "shardLockRefreshInterval"),
|
|
86
|
+
refreshAssignmentsInterval: duration(options.refreshAssignmentsInterval ?? "1 second", "refreshAssignmentsInterval"),
|
|
87
|
+
entityMessagePollInterval: "1 second",
|
|
88
|
+
entityTerminationTimeout: duration(options.entityTerminationTimeout ?? "15 seconds", "entityTerminationTimeout"),
|
|
89
|
+
};
|
|
90
|
+
const sharding = RunnerServer.layer.pipe(Layer.provideMerge(admissionSharding), Layer.provideMerge(Runners.layerRpc), Layer.provide(RpcServer.layerProtocolSocketServer), Layer.provideMerge(options.transport), Layer.provide(RpcSerialization.layerNdjson), Layer.orDie);
|
|
91
|
+
return Layer.succeed(RunnerWiring, {
|
|
92
|
+
config,
|
|
93
|
+
sharding,
|
|
94
|
+
storage: (storage) => storage,
|
|
95
|
+
production: true,
|
|
96
|
+
});
|
|
97
|
+
};
|
|
98
|
+
/**
|
|
99
|
+
* Runner-to-runner transport and ownership configuration, provided to
|
|
100
|
+
* `Actors.layer`: `socket` wires a runner, `mtls` is its authenticated
|
|
101
|
+
* transport, and `identity` is the URI subject alternative name a
|
|
102
|
+
* deployment's runner certificates carry.
|
|
103
|
+
*/
|
|
104
|
+
export const Runner = { socket, mtls, identity };
|
|
105
|
+
/** Refuses a routing layout mismatch before any runner registers or takes shards. */
|
|
106
|
+
export const checkRunnerConfiguration = Effect.fnUntraced(function* (wiring) {
|
|
107
|
+
const sql = yield* SqlClient.SqlClient;
|
|
108
|
+
if (wiring?.production === true) {
|
|
109
|
+
const shards = wiring.config.shardsPerGroup;
|
|
110
|
+
const expiration = Duration.toMillis(Duration.fromInputUnsafe(wiring.config.shardLockExpiration));
|
|
111
|
+
yield* sql `UPDATE actor_deployment SET runner_shards = ${shards}, runner_lock_expiration_ms = ${expiration}
|
|
112
|
+
WHERE runner_shards IS NULL`;
|
|
113
|
+
const [row] = yield* sql `SELECT runner_shards, runner_lock_expiration_ms::text FROM actor_deployment`;
|
|
114
|
+
if (row.runner_shards !== shards || Number(row.runner_lock_expiration_ms) !== expiration)
|
|
115
|
+
return yield* Effect.die(new Error("Runner shard count or lock expiration differs from the deployment; stop all runners and migrate explicitly"));
|
|
116
|
+
}
|
|
117
|
+
else if (wiring === undefined) {
|
|
118
|
+
const [row] = yield* sql `SELECT runner_shards FROM actor_deployment`;
|
|
119
|
+
if (row.runner_shards !== null)
|
|
120
|
+
return yield* Effect.die(new Error("This database requires Runner.socket configuration; a single embedded runner cannot join it"));
|
|
121
|
+
}
|
|
122
|
+
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { ActorRef } from "../../identity/caller.ts";
|
|
2
|
+
/** Increment only with a migration: every stored `routing_key` depends on this encoding. */
|
|
3
|
+
export declare const PLACEMENT_ENCODING = 1;
|
|
4
|
+
/**
|
|
5
|
+
* An actor type's placement. A parent-placed type names its parent type and
|
|
6
|
+
* that type's own placement, down to an actor-placed root.
|
|
7
|
+
*/
|
|
8
|
+
export type Placement = "tenant" | "actor" | {
|
|
9
|
+
readonly parent: string;
|
|
10
|
+
readonly placement: Placement;
|
|
11
|
+
};
|
|
12
|
+
/** A parent-placed type's parent and the parent's placement; `undefined` for any other. */
|
|
13
|
+
export declare const parentPlacement: (placement: Placement) => {
|
|
14
|
+
readonly parent: string;
|
|
15
|
+
readonly placement: Placement;
|
|
16
|
+
} | undefined;
|
|
17
|
+
/** The value `actor_placements.placement` records for `placement`. */
|
|
18
|
+
export declare const placementKind: (placement: Placement) => "actor" | "parent" | "tenant";
|
|
19
|
+
/**
|
|
20
|
+
* The 64-bit shard key shared by every row an actor owns. Tenant
|
|
21
|
+
* placement colocates a tenant's actors; actor placement spreads them; a
|
|
22
|
+
* parent-placed actor takes its root's key, read from the parent id its own
|
|
23
|
+
* id carries, so a family shares one shard. A parent-placed id without a
|
|
24
|
+
* parent id throws: ids are decoded against their actor's key before any
|
|
25
|
+
* routing, so that is a defect, not an input error.
|
|
26
|
+
*/
|
|
27
|
+
export declare const routingKey: ({ ref, placement, }: {
|
|
28
|
+
readonly ref: ActorRef;
|
|
29
|
+
readonly placement: Placement;
|
|
30
|
+
}) => bigint;
|
|
31
|
+
/** The shard key of a tenant: its tenant-placed actors and its shared content live there. */
|
|
32
|
+
export declare const tenantRoutingKey: (tenant: string) => bigint;
|
|
33
|
+
/**
|
|
34
|
+
* Stored state values are opaque zstd-compressed JSON: SQL never reads state,
|
|
35
|
+
* and anything worth querying belongs in an actor table.
|
|
36
|
+
*/
|
|
37
|
+
export declare const compress: (json: string) => Uint8Array;
|
|
38
|
+
/** Inverse of `compress`; throws on bytes that are not zstd-compressed UTF-8. */
|
|
39
|
+
export declare const decompress: (bytes: Uint8Array) => string;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { parseChildId } from "../../identity/child.js";
|
|
2
|
+
import { compressBytes, decompressBytes, hash64 } from "./platform.js";
|
|
3
|
+
/** Increment only with a migration: every stored `routing_key` depends on this encoding. */
|
|
4
|
+
export const PLACEMENT_ENCODING = 1;
|
|
5
|
+
/** A parent-placed type's parent and the parent's placement; `undefined` for any other. */
|
|
6
|
+
export const parentPlacement = (placement) => placement === "tenant" || placement === "actor" ? undefined : placement;
|
|
7
|
+
/** The value `actor_placements.placement` records for `placement`. */
|
|
8
|
+
export const placementKind = (placement) => placement === "tenant" || placement === "actor" ? placement : "parent";
|
|
9
|
+
/**
|
|
10
|
+
* The 64-bit shard key shared by every row an actor owns. Tenant
|
|
11
|
+
* placement colocates a tenant's actors; actor placement spreads them; a
|
|
12
|
+
* parent-placed actor takes its root's key, read from the parent id its own
|
|
13
|
+
* id carries, so a family shares one shard. A parent-placed id without a
|
|
14
|
+
* parent id throws: ids are decoded against their actor's key before any
|
|
15
|
+
* routing, so that is a defect, not an input error.
|
|
16
|
+
*/
|
|
17
|
+
export const routingKey = ({ ref, placement, }) => {
|
|
18
|
+
const above = parentPlacement(placement);
|
|
19
|
+
if (above !== undefined) {
|
|
20
|
+
const parent = parseChildId(ref.id)?.parent;
|
|
21
|
+
if (parent === undefined)
|
|
22
|
+
throw new Error(`Actor ${ref.actor} id ${ref.id} carries no ${above.parent} parent id`);
|
|
23
|
+
return routingKey({
|
|
24
|
+
ref: { tenant: ref.tenant, actor: above.parent, id: parent },
|
|
25
|
+
placement: above.placement,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
return placement === "tenant"
|
|
29
|
+
? tenantRoutingKey(ref.tenant)
|
|
30
|
+
: placementHash(["actor", ref.tenant, ref.actor, ref.id]);
|
|
31
|
+
};
|
|
32
|
+
/** The shard key of a tenant: its tenant-placed actors and its shared content live there. */
|
|
33
|
+
export const tenantRoutingKey = (tenant) => placementHash(["tenant", tenant]);
|
|
34
|
+
const placementHash = (parts) => BigInt.asIntN(64, hash64(JSON.stringify([PLACEMENT_ENCODING, ...parts])));
|
|
35
|
+
/**
|
|
36
|
+
* Stored state values are opaque zstd-compressed JSON: SQL never reads state,
|
|
37
|
+
* and anything worth querying belongs in an actor table.
|
|
38
|
+
*/
|
|
39
|
+
export const compress = (json) => compressBytes(new TextEncoder().encode(json));
|
|
40
|
+
/** Inverse of `compress`; throws on bytes that are not zstd-compressed UTF-8. */
|
|
41
|
+
export const decompress = (bytes) => new TextDecoder().decode(decompressBytes(bytes));
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { SqlClient } from "effect/sql";
|
|
3
|
+
import type { ActorRef } from "../../identity/caller.ts";
|
|
4
|
+
/**
|
|
5
|
+
* What one activation remembers of its authority between writes. `generation`
|
|
6
|
+
* is the fenced epoch it acquired and `state` the committed state it last read
|
|
7
|
+
* or wrote. Memory is never authority: every durable writer proves in its own
|
|
8
|
+
* transaction that the stored generation still equals `generation`, and only
|
|
9
|
+
* that proof lets a turn skip reading state again. Command turns, connection
|
|
10
|
+
* sessions and workflow runs of one activation share this one object.
|
|
11
|
+
*/
|
|
12
|
+
export interface ActivationCache {
|
|
13
|
+
generation: string | undefined;
|
|
14
|
+
state: ReadonlyMap<string, string> | undefined;
|
|
15
|
+
}
|
|
16
|
+
/** A fresh activation has acquired no generation and read no state. */
|
|
17
|
+
export declare const emptyActivationCache: () => ActivationCache;
|
|
18
|
+
/**
|
|
19
|
+
* Drops what an activation remembers once a writer found its generation stale,
|
|
20
|
+
* so no later writer trusts that generation or the state read under it; the
|
|
21
|
+
* next one acquires a new generation and reads state again.
|
|
22
|
+
*/
|
|
23
|
+
export declare const forget: (cache: ActivationCache) => void;
|
|
24
|
+
/** One actor's stored identity: the routing key its rows live under and its address. */
|
|
25
|
+
export interface OwnedActor {
|
|
26
|
+
readonly key: bigint;
|
|
27
|
+
readonly ref: ActorRef;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The predicate naming `actor`'s rows in any table keyed by actor identity,
|
|
31
|
+
* with columns qualified by `alias` when the statement joins another such table.
|
|
32
|
+
*/
|
|
33
|
+
export declare const actorRow: ({ sql, actor: { key, ref }, alias, }: {
|
|
34
|
+
readonly sql: SqlClient.SqlClient;
|
|
35
|
+
readonly actor: OwnedActor;
|
|
36
|
+
readonly alias?: string;
|
|
37
|
+
}) => import("effect/sql/Statement").Statement<import("effect/sql/SqlConnection").Row>;
|
|
38
|
+
/**
|
|
39
|
+
* How a writer outside the turn's own admission holds the generation row until
|
|
40
|
+
* it commits. `UPDATE` serializes the writer with command turns, which lock the
|
|
41
|
+
* row the same way, for a multi-statement write that reads actor data. `SHARE`
|
|
42
|
+
* only stops another activation advancing the generation until the writer
|
|
43
|
+
* commits, for one statement that writes rows of its own.
|
|
44
|
+
*/
|
|
45
|
+
export type GenerationLock = "UPDATE" | "SHARE";
|
|
46
|
+
/**
|
|
47
|
+
* The actor's generation row while it is still at `generation`, locked by
|
|
48
|
+
* `lock`, as a query or a derived table a single write statement joins. No row
|
|
49
|
+
* means another activation took over and the statement must write nothing. The
|
|
50
|
+
* lock waits out a concurrent takeover and then rechecks the generation, so a
|
|
51
|
+
* write that commits was ordered before any newer generation was acquired.
|
|
52
|
+
*/
|
|
53
|
+
export declare const heldGeneration: ({ sql, actor, generation, lock, }: {
|
|
54
|
+
readonly sql: SqlClient.SqlClient;
|
|
55
|
+
readonly actor: OwnedActor;
|
|
56
|
+
readonly generation: string;
|
|
57
|
+
readonly lock: GenerationLock;
|
|
58
|
+
}) => import("effect/sql/Statement").Statement<import("effect/sql/SqlConnection").Row>;
|
|
59
|
+
/**
|
|
60
|
+
* Proves inside the caller's transaction that `cache` still holds the actor's
|
|
61
|
+
* generation, and holds the row by `lock` until that transaction ends. A stale
|
|
62
|
+
* or never-fenced activation answers false and has forgotten its generation
|
|
63
|
+
* and state; each caller maps that answer to its own retryable failure.
|
|
64
|
+
*/
|
|
65
|
+
export declare const fence: (args_0: {
|
|
66
|
+
readonly actor: OwnedActor;
|
|
67
|
+
readonly cache: ActivationCache;
|
|
68
|
+
readonly lock: GenerationLock;
|
|
69
|
+
}) => Effect.Effect<boolean, import("effect/sql/SqlError").SqlError, SqlClient.SqlClient>;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { SqlClient } from "effect/sql";
|
|
3
|
+
/** A fresh activation has acquired no generation and read no state. */
|
|
4
|
+
export const emptyActivationCache = () => ({
|
|
5
|
+
generation: undefined,
|
|
6
|
+
state: undefined,
|
|
7
|
+
});
|
|
8
|
+
/**
|
|
9
|
+
* Drops what an activation remembers once a writer found its generation stale,
|
|
10
|
+
* so no later writer trusts that generation or the state read under it; the
|
|
11
|
+
* next one acquires a new generation and reads state again.
|
|
12
|
+
*/
|
|
13
|
+
export const forget = (cache) => {
|
|
14
|
+
cache.generation = undefined;
|
|
15
|
+
cache.state = undefined;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* The predicate naming `actor`'s rows in any table keyed by actor identity,
|
|
19
|
+
* with columns qualified by `alias` when the statement joins another such table.
|
|
20
|
+
*/
|
|
21
|
+
export const actorRow = ({ sql, actor: { key, ref }, alias, }) => {
|
|
22
|
+
const at = sql.literal(alias === undefined ? "" : `${alias}.`);
|
|
23
|
+
return sql `${at}routing_key = ${key} AND ${at}tenant_id = ${ref.tenant}
|
|
24
|
+
AND ${at}actor_type = ${ref.actor} AND ${at}actor_id = ${ref.id}`;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* The actor's generation row while it is still at `generation`, locked by
|
|
28
|
+
* `lock`, as a query or a derived table a single write statement joins. No row
|
|
29
|
+
* means another activation took over and the statement must write nothing. The
|
|
30
|
+
* lock waits out a concurrent takeover and then rechecks the generation, so a
|
|
31
|
+
* write that commits was ordered before any newer generation was acquired.
|
|
32
|
+
*/
|
|
33
|
+
export const heldGeneration = ({ sql, actor, generation, lock, }) => sql `SELECT routing_key, tenant_id, actor_type, actor_id FROM actor_generations
|
|
34
|
+
WHERE ${actorRow({ sql, actor })} AND generation = ${generation} FOR ${sql.literal(lock)}`;
|
|
35
|
+
/**
|
|
36
|
+
* Proves inside the caller's transaction that `cache` still holds the actor's
|
|
37
|
+
* generation, and holds the row by `lock` until that transaction ends. A stale
|
|
38
|
+
* or never-fenced activation answers false and has forgotten its generation
|
|
39
|
+
* and state; each caller maps that answer to its own retryable failure.
|
|
40
|
+
*/
|
|
41
|
+
export const fence = Effect.fnUntraced(function* ({ actor, cache, lock, }) {
|
|
42
|
+
if (cache.generation === undefined)
|
|
43
|
+
return false;
|
|
44
|
+
const sql = yield* SqlClient.SqlClient;
|
|
45
|
+
const held = yield* heldGeneration({ sql, actor, generation: cache.generation, lock });
|
|
46
|
+
if (held.length === 0)
|
|
47
|
+
forget(cache);
|
|
48
|
+
return held.length > 0;
|
|
49
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { SqlClient, type SqlError } from "effect/sql";
|
|
3
|
+
import { type Placement } from "./codec.ts";
|
|
4
|
+
/**
|
|
5
|
+
* Records `name`'s placement on first registration and refuses one that
|
|
6
|
+
* differs from the record, for the type and every ancestor it routes through:
|
|
7
|
+
* a changed placement, encoding, or parent would read and write under
|
|
8
|
+
* different routing keys.
|
|
9
|
+
*/
|
|
10
|
+
export declare const checkPlacement: ({ name, placement, }: {
|
|
11
|
+
readonly name: string;
|
|
12
|
+
readonly placement: Placement;
|
|
13
|
+
}) => Effect.Effect<void, SqlError.SqlError, SqlClient.SqlClient>;
|
|
14
|
+
/** The placement recorded for `actorType`, resolved through its parents, or `undefined` if none is. */
|
|
15
|
+
export declare const recordedPlacement: (actorType: string) => Effect.Effect<Placement | undefined, SqlError.SqlError, SqlClient.SqlClient>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { SqlClient } from "effect/sql";
|
|
3
|
+
import { parentPlacement, PLACEMENT_ENCODING, placementKind } from "./codec.js";
|
|
4
|
+
/**
|
|
5
|
+
* Records `name`'s placement on first registration and refuses one that
|
|
6
|
+
* differs from the record, for the type and every ancestor it routes through:
|
|
7
|
+
* a changed placement, encoding, or parent would read and write under
|
|
8
|
+
* different routing keys.
|
|
9
|
+
*/
|
|
10
|
+
export const checkPlacement = ({ name, placement, }) => Effect.gen(function* () {
|
|
11
|
+
const sql = yield* SqlClient.SqlClient;
|
|
12
|
+
const kind = placementKind(placement);
|
|
13
|
+
const above = parentPlacement(placement);
|
|
14
|
+
const parent = above?.parent ?? null;
|
|
15
|
+
yield* sql `INSERT INTO actor_placements (actor_type, placement, encoding, parent_type)
|
|
16
|
+
VALUES (${name}, ${kind}, ${PLACEMENT_ENCODING}, ${parent})
|
|
17
|
+
ON CONFLICT DO NOTHING`;
|
|
18
|
+
const [recorded] = yield* sql `SELECT placement, encoding, parent_type FROM actor_placements WHERE actor_type = ${name}`;
|
|
19
|
+
if (recorded?.placement !== kind ||
|
|
20
|
+
recorded.encoding !== PLACEMENT_ENCODING ||
|
|
21
|
+
recorded.parent_type !== parent)
|
|
22
|
+
return yield* Effect.die(new Error(`Actor ${name} placement differs from the deployment; migrate explicitly`));
|
|
23
|
+
if (above !== undefined)
|
|
24
|
+
yield* checkPlacement({ name: above.parent, placement: above.placement });
|
|
25
|
+
});
|
|
26
|
+
/** The placement recorded for `actorType`, resolved through its parents, or `undefined` if none is. */
|
|
27
|
+
export const recordedPlacement = (actorType) => Effect.gen(function* () {
|
|
28
|
+
const sql = yield* SqlClient.SqlClient;
|
|
29
|
+
const [recorded] = yield* sql `SELECT placement, parent_type FROM actor_placements WHERE actor_type = ${actorType}`;
|
|
30
|
+
if (recorded === undefined)
|
|
31
|
+
return undefined;
|
|
32
|
+
if (recorded.placement !== "parent")
|
|
33
|
+
return recorded.placement;
|
|
34
|
+
const parent = yield* recordedPlacement(recorded.parent_type);
|
|
35
|
+
if (parent === undefined)
|
|
36
|
+
return yield* Effect.die(new Error(`Actor ${actorType}'s parent ${recorded.parent_type} has no recorded placement`));
|
|
37
|
+
return { parent: recorded.parent_type, placement: parent };
|
|
38
|
+
});
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Preserves persisted xxHash3 routing keys on both supported runtimes. */
|
|
2
|
+
export declare const hash64: (text: string) => bigint;
|
|
3
|
+
/** Uses each runtime's native zstd implementation without changing the stored format. */
|
|
4
|
+
export declare const compressBytes: (bytes: Uint8Array) => Uint8Array;
|
|
5
|
+
/** Reads zstd frames written by either runtime. */
|
|
6
|
+
export declare const decompressBytes: (bytes: Uint8Array) => Uint8Array;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { zstdCompressSync, zstdDecompressSync } from "node:zlib";
|
|
2
|
+
const bun = globalThis.Bun;
|
|
3
|
+
const xxhash = bun === undefined ? (await import("@node-rs/xxhash")).xxh3.xxh64 : bun.hash.xxHash3;
|
|
4
|
+
/** Preserves persisted xxHash3 routing keys on both supported runtimes. */
|
|
5
|
+
export const hash64 = (text) => xxhash(text);
|
|
6
|
+
/** Uses each runtime's native zstd implementation without changing the stored format. */
|
|
7
|
+
export const compressBytes = (bytes) => bun === undefined ? zstdCompressSync(bytes) : bun.zstdCompressSync(bytes);
|
|
8
|
+
/** Reads zstd frames written by either runtime. */
|
|
9
|
+
export const decompressBytes = (bytes) => bun === undefined ? zstdDecompressSync(bytes) : bun.zstdDecompressSync(bytes);
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { SqlClient, type SqlError } from "effect/sql";
|
|
3
|
+
/** One actor type's retention horizons, in milliseconds on the framework clock, and whether it has workflows to sweep. */
|
|
4
|
+
interface RetentionPolicy {
|
|
5
|
+
readonly actorType: string;
|
|
6
|
+
readonly keepReceiptsMs: number;
|
|
7
|
+
readonly keepEventsMs: number;
|
|
8
|
+
/** How long past `keepEventsMs` subscriptions may hold an event back. */
|
|
9
|
+
readonly holdEventsMs: number;
|
|
10
|
+
readonly deliveryMs: number;
|
|
11
|
+
readonly keepWorkflowsMs: number;
|
|
12
|
+
readonly workflows: boolean;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* How long after its id expires a receipt stays. An id expires one retry
|
|
16
|
+
* window after it is issued (a timer's after its due time), so this keeps
|
|
17
|
+
* receipts `keepReceipts` from issue; equivalently, it retains an expired id
|
|
18
|
+
* for `max(keepReceipts, retryWindow + deliveryTimeout)` after issue, so a
|
|
19
|
+
* command admitted just before expiry can still run and find the receipt of an
|
|
20
|
+
* attempt that committed meanwhile.
|
|
21
|
+
*/
|
|
22
|
+
export declare const receiptMarginMs: (horizon: {
|
|
23
|
+
readonly keepReceiptsMs: number;
|
|
24
|
+
readonly deliveryMs: number;
|
|
25
|
+
readonly retryWindowMs: number;
|
|
26
|
+
}) => number;
|
|
27
|
+
/** Rows deleted by a sweep, by kind. */
|
|
28
|
+
export interface Swept {
|
|
29
|
+
readonly receipts: number;
|
|
30
|
+
readonly events: number;
|
|
31
|
+
readonly workflows: number;
|
|
32
|
+
/** Unreferenced content rows deleted after their grant horizon. */
|
|
33
|
+
readonly contents: number;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Deletes receipts and events past each actor type's horizon, in batches that
|
|
37
|
+
* each commit in their own transaction, so an interrupted sweep leaves only whole batches
|
|
38
|
+
* behind and the next sweep continues from there.
|
|
39
|
+
*
|
|
40
|
+
* A receipt goes only once its command id has expired, so external admission
|
|
41
|
+
* already rejects the id without it, and only while no outbox row carries its
|
|
42
|
+
* id, so a redelivered intent or effect route still finds it. A receipt can
|
|
43
|
+
* only gain such a row before it exists, never after.
|
|
44
|
+
*
|
|
45
|
+
* Events go as a prefix: each batch removes, per actor, every event up to the
|
|
46
|
+
* newest one it picked, so a retained event always has every later one after
|
|
47
|
+
* it. `event_sequence` lives on the generation row and is never touched, so
|
|
48
|
+
* no cursor is reissued. The prefix stops at the oldest cursor or pending
|
|
49
|
+
* wait of an open workflow execution of that actor, which still reads past it,
|
|
50
|
+
* and at the lowest position an active subscription to that actor has
|
|
51
|
+
* settled through, unless the events are older than `keepEvents` plus
|
|
52
|
+
* `holdEventsForSubscribers`.
|
|
53
|
+
*
|
|
54
|
+
* A finished workflow execution goes `keepWorkflows` after it finished; its
|
|
55
|
+
* steps went when it finished. A workflow manifest goes once it is neither
|
|
56
|
+
* the most recently accepted one for its workflow nor the start manifest of
|
|
57
|
+
* an open execution.
|
|
58
|
+
*
|
|
59
|
+
* Sweeps of one actor type take turns on an authoritative row lock, so two runners, or
|
|
60
|
+
* a sweep and `ActorTest.cleanup`, never lock overlapping event prefixes in
|
|
61
|
+
* opposite orders. Each batch starts at the newest age the previous one took,
|
|
62
|
+
* so it never walks index entries of rows earlier batches deleted and vacuum
|
|
63
|
+
* has not yet removed.
|
|
64
|
+
*
|
|
65
|
+
* The sweep yields after each batch, so a turn waiting for PGlite's one
|
|
66
|
+
* connection runs between batches instead of after the whole sweep.
|
|
67
|
+
*/
|
|
68
|
+
export declare const sweep: (policies: Iterable<RetentionPolicy>, retryWindowMs: number) => Effect.Effect<{
|
|
69
|
+
receipts: number;
|
|
70
|
+
events: number;
|
|
71
|
+
workflows: number;
|
|
72
|
+
}, SqlError.SqlError, SqlClient.SqlClient>;
|
|
73
|
+
export {};
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { SqlClient } from "effect/sql";
|
|
3
|
+
import { databaseTime } from "../turn/admission.js";
|
|
4
|
+
import { CleanupHooks } from "../turn/hooks.js";
|
|
5
|
+
import { count, Metrics } from "../telemetry/metrics.js";
|
|
6
|
+
import { coordinated } from "../database/coordination.js";
|
|
7
|
+
/**
|
|
8
|
+
* How long after its id expires a receipt stays. An id expires one retry
|
|
9
|
+
* window after it is issued (a timer's after its due time), so this keeps
|
|
10
|
+
* receipts `keepReceipts` from issue; equivalently, it retains an expired id
|
|
11
|
+
* for `max(keepReceipts, retryWindow + deliveryTimeout)` after issue, so a
|
|
12
|
+
* command admitted just before expiry can still run and find the receipt of an
|
|
13
|
+
* attempt that committed meanwhile.
|
|
14
|
+
*/
|
|
15
|
+
export const receiptMarginMs = (horizon) => Math.max(horizon.keepReceiptsMs - horizon.retryWindowMs, horizon.deliveryMs);
|
|
16
|
+
/**
|
|
17
|
+
* Deletes receipts and events past each actor type's horizon, in batches that
|
|
18
|
+
* each commit in their own transaction, so an interrupted sweep leaves only whole batches
|
|
19
|
+
* behind and the next sweep continues from there.
|
|
20
|
+
*
|
|
21
|
+
* A receipt goes only once its command id has expired, so external admission
|
|
22
|
+
* already rejects the id without it, and only while no outbox row carries its
|
|
23
|
+
* id, so a redelivered intent or effect route still finds it. A receipt can
|
|
24
|
+
* only gain such a row before it exists, never after.
|
|
25
|
+
*
|
|
26
|
+
* Events go as a prefix: each batch removes, per actor, every event up to the
|
|
27
|
+
* newest one it picked, so a retained event always has every later one after
|
|
28
|
+
* it. `event_sequence` lives on the generation row and is never touched, so
|
|
29
|
+
* no cursor is reissued. The prefix stops at the oldest cursor or pending
|
|
30
|
+
* wait of an open workflow execution of that actor, which still reads past it,
|
|
31
|
+
* and at the lowest position an active subscription to that actor has
|
|
32
|
+
* settled through, unless the events are older than `keepEvents` plus
|
|
33
|
+
* `holdEventsForSubscribers`.
|
|
34
|
+
*
|
|
35
|
+
* A finished workflow execution goes `keepWorkflows` after it finished; its
|
|
36
|
+
* steps went when it finished. A workflow manifest goes once it is neither
|
|
37
|
+
* the most recently accepted one for its workflow nor the start manifest of
|
|
38
|
+
* an open execution.
|
|
39
|
+
*
|
|
40
|
+
* Sweeps of one actor type take turns on an authoritative row lock, so two runners, or
|
|
41
|
+
* a sweep and `ActorTest.cleanup`, never lock overlapping event prefixes in
|
|
42
|
+
* opposite orders. Each batch starts at the newest age the previous one took,
|
|
43
|
+
* so it never walks index entries of rows earlier batches deleted and vacuum
|
|
44
|
+
* has not yet removed.
|
|
45
|
+
*
|
|
46
|
+
* The sweep yields after each batch, so a turn waiting for PGlite's one
|
|
47
|
+
* connection runs between batches instead of after the whole sweep.
|
|
48
|
+
*/
|
|
49
|
+
export const sweep = Effect.fnUntraced(function* (policies, retryWindowMs) {
|
|
50
|
+
const sql = yield* SqlClient.SqlClient;
|
|
51
|
+
const hooks = yield* CleanupHooks;
|
|
52
|
+
let receipts = 0;
|
|
53
|
+
let events = 0;
|
|
54
|
+
let workflows = 0;
|
|
55
|
+
for (const policy of policies) {
|
|
56
|
+
const now = yield* databaseTime;
|
|
57
|
+
const receiptCutoff = now - receiptMarginMs({ ...policy, retryWindowMs });
|
|
58
|
+
const eventCutoff = now - policy.keepEventsMs;
|
|
59
|
+
const holdCutoff = eventCutoff - policy.holdEventsMs;
|
|
60
|
+
const batch = (statement) => coordinated({ resource: `akter/retention/${policy.actorType}`, work: statement });
|
|
61
|
+
/** Runs `prune` in batches, each from the age the previous one reached, until one deletes nothing. */
|
|
62
|
+
const pruneAll = Effect.fnUntraced(function* (prune, metric) {
|
|
63
|
+
let from = "0";
|
|
64
|
+
let total = 0;
|
|
65
|
+
for (;;) {
|
|
66
|
+
const [pruned] = yield* batch(prune(from));
|
|
67
|
+
total += pruned.count;
|
|
68
|
+
if (metric !== undefined)
|
|
69
|
+
yield* count(metric, { actor_type: policy.actorType }, pruned.count);
|
|
70
|
+
if (pruned.count === 0)
|
|
71
|
+
return total;
|
|
72
|
+
from = pruned.last ?? from;
|
|
73
|
+
yield* hooks.afterBatch;
|
|
74
|
+
yield* Effect.yieldNow;
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
receipts += yield* pruneAll((from) => sql `
|
|
78
|
+
WITH doomed AS (
|
|
79
|
+
SELECT r.routing_key, r.tenant_id, r.actor_type, r.actor_id, r.command_id, r.expires_at_ms
|
|
80
|
+
FROM actor_receipts r
|
|
81
|
+
WHERE r.actor_type = ${policy.actorType} AND r.expires_at_ms >= ${from}::bigint
|
|
82
|
+
AND r.expires_at_ms <= ${receiptCutoff}
|
|
83
|
+
AND NOT EXISTS (
|
|
84
|
+
SELECT 1 FROM actor_outbox o
|
|
85
|
+
WHERE o.intent_id = r.command_id AND o.tenant_id = r.tenant_id
|
|
86
|
+
AND o.target_type = r.actor_type AND o.target_id = r.actor_id
|
|
87
|
+
)
|
|
88
|
+
ORDER BY r.expires_at_ms
|
|
89
|
+
LIMIT ${hooks.batchSize}
|
|
90
|
+
FOR UPDATE SKIP LOCKED),
|
|
91
|
+
gone AS (
|
|
92
|
+
DELETE FROM actor_receipts r USING doomed d
|
|
93
|
+
WHERE r.routing_key = d.routing_key AND r.tenant_id = d.tenant_id
|
|
94
|
+
AND r.actor_type = d.actor_type AND r.actor_id = d.actor_id AND r.command_id = d.command_id
|
|
95
|
+
RETURNING 1)
|
|
96
|
+
SELECT count(*)::integer AS count, (SELECT max(expires_at_ms)::text FROM doomed) AS last
|
|
97
|
+
FROM gone`, Metrics.receiptsPruned);
|
|
98
|
+
events += yield* pruneAll((from) => sql `
|
|
99
|
+
WITH picked AS (
|
|
100
|
+
SELECT routing_key, tenant_id, actor_type, actor_id, sequence, emitted_at_ms FROM actor_events
|
|
101
|
+
WHERE actor_type = ${policy.actorType} AND emitted_at_ms >= ${from}::bigint
|
|
102
|
+
AND emitted_at_ms <= ${eventCutoff}
|
|
103
|
+
ORDER BY emitted_at_ms
|
|
104
|
+
LIMIT ${hooks.batchSize}),
|
|
105
|
+
upto AS (
|
|
106
|
+
SELECT p.routing_key, p.tenant_id, p.actor_type, p.actor_id,
|
|
107
|
+
LEAST(max(p.sequence),
|
|
108
|
+
-- Active subscriptions hold what they haven't settled, until
|
|
109
|
+
-- the hold ends; then their subscribers get a RetentionGap.
|
|
110
|
+
GREATEST(
|
|
111
|
+
COALESCE((SELECT min(s.delivered) FROM actor_subscriptions s
|
|
112
|
+
WHERE s.routing_key = p.routing_key AND s.tenant_id = p.tenant_id
|
|
113
|
+
AND s.source_type = p.actor_type AND s.source_id = p.actor_id AND s.active),
|
|
114
|
+
max(p.sequence)),
|
|
115
|
+
COALESCE(max(p.sequence) FILTER (WHERE p.emitted_at_ms <= ${holdCutoff}), 0)),
|
|
116
|
+
COALESCE((
|
|
117
|
+
SELECT min(LEAST(x.event_cursor, COALESCE(w.wait_after, x.event_cursor)))
|
|
118
|
+
FROM actor_workflow_executions x
|
|
119
|
+
LEFT JOIN actor_workflow_step w ON w.routing_key = x.routing_key
|
|
120
|
+
AND w.execution_id = x.execution_id AND w.kind = 'wait' AND w.exit IS NULL
|
|
121
|
+
WHERE x.routing_key = p.routing_key AND x.tenant_id = p.tenant_id
|
|
122
|
+
AND x.actor_type = p.actor_type AND x.actor_id = p.actor_id AND x.status <> 'finished'
|
|
123
|
+
), max(p.sequence))) AS last
|
|
124
|
+
FROM picked p GROUP BY p.routing_key, p.tenant_id, p.actor_type, p.actor_id),
|
|
125
|
+
gone AS (
|
|
126
|
+
DELETE FROM actor_events e USING upto u
|
|
127
|
+
WHERE e.routing_key = u.routing_key AND e.tenant_id = u.tenant_id
|
|
128
|
+
AND e.actor_type = u.actor_type AND e.actor_id = u.actor_id AND e.sequence <= u.last
|
|
129
|
+
RETURNING 1)
|
|
130
|
+
SELECT count(*)::integer AS count, (SELECT max(emitted_at_ms)::text FROM picked) AS last
|
|
131
|
+
FROM gone`, Metrics.eventsPruned);
|
|
132
|
+
if (policy.workflows) {
|
|
133
|
+
const workflowCutoff = now - policy.keepWorkflowsMs;
|
|
134
|
+
workflows += yield* pruneAll(() => sql `
|
|
135
|
+
WITH doomed AS (
|
|
136
|
+
SELECT routing_key, execution_id FROM actor_workflow_executions
|
|
137
|
+
WHERE actor_type = ${policy.actorType} AND status = 'finished'
|
|
138
|
+
AND finished_at_ms <= ${workflowCutoff}
|
|
139
|
+
ORDER BY finished_at_ms
|
|
140
|
+
LIMIT ${hooks.batchSize}
|
|
141
|
+
FOR UPDATE SKIP LOCKED),
|
|
142
|
+
gone AS (
|
|
143
|
+
DELETE FROM actor_workflow_executions x USING doomed d
|
|
144
|
+
WHERE x.routing_key = d.routing_key AND x.execution_id = d.execution_id
|
|
145
|
+
RETURNING 1)
|
|
146
|
+
SELECT count(*)::integer AS count FROM gone`);
|
|
147
|
+
yield* batch(sql `
|
|
148
|
+
DELETE FROM actor_workflow_manifests m
|
|
149
|
+
WHERE m.actor_type = ${policy.actorType}
|
|
150
|
+
AND m.accepted_at_ms < (SELECT max(l.accepted_at_ms) FROM actor_workflow_manifests l
|
|
151
|
+
WHERE l.actor_type = m.actor_type AND l.workflow = m.workflow)
|
|
152
|
+
AND NOT EXISTS (SELECT 1 FROM actor_workflow_executions x
|
|
153
|
+
WHERE x.actor_type = m.actor_type AND x.workflow = m.workflow
|
|
154
|
+
AND x.manifest_hash = m.manifest_hash AND x.status <> 'finished')`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return { receipts, events, workflows };
|
|
158
|
+
});
|