@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,175 @@
|
|
|
1
|
+
import * as NodeSocket from "@effect/platform-node-shared/NodeSocket";
|
|
2
|
+
import * as NodeSocketServer from "@effect/platform-node-shared/NodeSocketServer";
|
|
3
|
+
import { constants, createPrivateKey, X509Certificate } from "node:crypto";
|
|
4
|
+
import { connect, createSecureContext } from "node:tls";
|
|
5
|
+
import { Clock, Context, Duration, Effect, Layer, Option, Redacted, Scope } from "effect";
|
|
6
|
+
import { Runners, ShardingConfig } from "effect/cluster";
|
|
7
|
+
import { RpcClient, RpcSerialization } from "effect/rpc";
|
|
8
|
+
import { Socket, SocketServer } from "effect/socket";
|
|
9
|
+
import { identity } from "./credentials.js";
|
|
10
|
+
/**
|
|
11
|
+
* Whether a verified peer certificate belongs to the deployment `expected`
|
|
12
|
+
* names: its subject alternative names are exactly that one URI, so no
|
|
13
|
+
* extra name, Akter identity or otherwise, rides along.
|
|
14
|
+
*/
|
|
15
|
+
const belongs = (peer, expected) => peer?.subjectaltname === `URI:${expected}`;
|
|
16
|
+
const certificates = (pem) => (pem.match(/-----BEGIN CERTIFICATE-----[\s\S]+?-----END CERTIFICATE-----/gu) ?? []).map((block) => new X509Certificate(block));
|
|
17
|
+
const issued = (certificate, by) => certificate.checkIssued(by) && certificate.verify(by.publicKey);
|
|
18
|
+
/**
|
|
19
|
+
* Checks credentials before any peer sees them and builds the TLS context
|
|
20
|
+
* that presents them, so a runner refuses to start, or keeps its previous
|
|
21
|
+
* credentials, rather than present a certificate its peers would refuse:
|
|
22
|
+
* one for another deployment, one outside its validity window, one its key
|
|
23
|
+
* does not match, or one no trusted authority issued. Session tickets are
|
|
24
|
+
* off, so every connection runs a full handshake and its peer's chain and
|
|
25
|
+
* validity are checked again rather than resumed from an earlier session.
|
|
26
|
+
*/
|
|
27
|
+
const prepare = (credentials, expected, now) => {
|
|
28
|
+
const authorities = certificates(credentials.ca);
|
|
29
|
+
const chain = certificates(credentials.certificate);
|
|
30
|
+
const leaf = chain[0];
|
|
31
|
+
if (authorities.length === 0 || authorities.some((authority) => !authority.ca))
|
|
32
|
+
throw new Error("Runner credentials need at least one certificate authority in ca");
|
|
33
|
+
if (leaf === undefined)
|
|
34
|
+
throw new Error("Runner credentials need a certificate");
|
|
35
|
+
if (!belongs({ subjectaltname: leaf.subjectAltName }, expected))
|
|
36
|
+
throw new Error(`Runner certificate must name only the identity ${expected}`);
|
|
37
|
+
if (now < Date.parse(leaf.validFrom) || now > Date.parse(leaf.validTo))
|
|
38
|
+
throw new Error(`Runner certificate is valid only from ${leaf.validFrom} to ${leaf.validTo}`);
|
|
39
|
+
if (!leaf.checkPrivateKey(createPrivateKey(Redacted.value(credentials.key))))
|
|
40
|
+
throw new Error("Runner key does not match its certificate");
|
|
41
|
+
for (const [index, certificate] of chain.entries()) {
|
|
42
|
+
const next = chain[index + 1];
|
|
43
|
+
if (next === undefined
|
|
44
|
+
? !authorities.some((authority) => issued(certificate, authority))
|
|
45
|
+
: !issued(certificate, next))
|
|
46
|
+
throw new Error("Runner certificate is not issued by a certificate authority in ca");
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
context: createSecureContext({
|
|
50
|
+
ca: credentials.ca,
|
|
51
|
+
cert: credentials.certificate,
|
|
52
|
+
key: Redacted.value(credentials.key),
|
|
53
|
+
minVersion: "TLSv1.3",
|
|
54
|
+
secureOptions: constants.SSL_OP_NO_TICKET,
|
|
55
|
+
}),
|
|
56
|
+
expires: Date.parse(leaf.validTo),
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Whether this runner can still peer: false once its current certificate has
|
|
61
|
+
* expired, or once no credential load has succeeded for longer than the
|
|
62
|
+
* transport's `unhealthyAfter`. Readiness reports `peering` while it is false.
|
|
63
|
+
*/
|
|
64
|
+
export class PeerHealth extends Context.Service()("@rikalabs/akter/runtime/peering/transport/PeerHealth") {
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Every client names the same server, so the listener picks the current
|
|
68
|
+
* credentials through its SNI callback whatever address the peer dialled.
|
|
69
|
+
*/
|
|
70
|
+
const SERVER_NAME = "runner.akter.internal";
|
|
71
|
+
/**
|
|
72
|
+
* Runner-to-runner TCP with mutual TLS 1.3. Each side presents its
|
|
73
|
+
* deployment's certificate and accepts a peer only when the peer's chain
|
|
74
|
+
* reaches a trusted authority, is within its validity window, and carries
|
|
75
|
+
* exactly this deployment's identity; a plaintext peer, a peer without a
|
|
76
|
+
* certificate, and a peer of another deployment never reach the runner's RPC
|
|
77
|
+
* handler. Credentials are reloaded every `refreshEvery`: new connections use
|
|
78
|
+
* the latest valid ones, established connections keep the session they
|
|
79
|
+
* authenticated, and credentials that fail validation are logged and
|
|
80
|
+
* ignored while the previous ones stay in use. A runner whose certificate has
|
|
81
|
+
* expired, or whose loads have failed for `unhealthyAfter`, stops reporting
|
|
82
|
+
* ready.
|
|
83
|
+
*/
|
|
84
|
+
export const mtls = (options) => {
|
|
85
|
+
const expected = identity(options.deployment);
|
|
86
|
+
const duration = (value, name) => {
|
|
87
|
+
const result = Duration.fromInputUnsafe(value);
|
|
88
|
+
if (!Number.isFinite(Duration.toMillis(result)) || Duration.toMillis(result) < 1)
|
|
89
|
+
throw new Error(`${name} must be finite and at least 1 millisecond`);
|
|
90
|
+
return result;
|
|
91
|
+
};
|
|
92
|
+
const refreshEvery = duration(options.refreshEvery ?? "1 minute", "refreshEvery");
|
|
93
|
+
const refreshTimeout = duration(options.refreshTimeout ?? "10 seconds", "refreshTimeout");
|
|
94
|
+
const unhealthyAfter = duration(options.unhealthyAfter ?? "5 minutes", "unhealthyAfter");
|
|
95
|
+
return Layer.effectContext(Effect.gen(function* () {
|
|
96
|
+
const load = Effect.flatMap(options.credentials, (credentials) => Effect.flatMap(Clock.currentTimeMillis, (now) => Effect.sync(() => ({ ...prepare(credentials, expected, now), loaded: now })))).pipe(Effect.timeoutOrElse({
|
|
97
|
+
duration: refreshTimeout,
|
|
98
|
+
orElse: () => Effect.die(new Error(`Runner peer credentials took longer than ${Duration.toMillis(refreshTimeout)} ms`)),
|
|
99
|
+
}));
|
|
100
|
+
let current = yield* load.pipe(Effect.orDie);
|
|
101
|
+
yield* load.pipe(Effect.tap((next) => Effect.sync(() => {
|
|
102
|
+
current = next;
|
|
103
|
+
})), Effect.catchCause((cause) => Effect.logWarning("Runner peer credentials were not reloaded; keeping the current ones", cause)), Effect.delay(refreshEvery), Effect.forever, Effect.forkScoped);
|
|
104
|
+
const health = PeerHealth.of({
|
|
105
|
+
healthy: Effect.map(Clock.currentTimeMillis, (now) => now <= current.expires && now - current.loaded <= Duration.toMillis(unhealthyAfter)),
|
|
106
|
+
});
|
|
107
|
+
const config = yield* ShardingConfig.ShardingConfig;
|
|
108
|
+
const listen = Option.orElse(config.runnerListenAddress, () => config.runnerAddress);
|
|
109
|
+
if (Option.isNone(listen))
|
|
110
|
+
return yield* Effect.die(new Error("Runner.mtls needs a runner listen address"));
|
|
111
|
+
const server = yield* NodeSocketServer.makeTls({
|
|
112
|
+
host: listen.value.host,
|
|
113
|
+
port: listen.value.port,
|
|
114
|
+
minVersion: "TLSv1.3",
|
|
115
|
+
requestCert: true,
|
|
116
|
+
rejectUnauthorized: true,
|
|
117
|
+
secureOptions: constants.SSL_OP_NO_TICKET,
|
|
118
|
+
SNICallback: (_name, done) => done(null, current.context),
|
|
119
|
+
});
|
|
120
|
+
const accepted = (socket) => socket.authorized &&
|
|
121
|
+
!socket.isSessionReused() &&
|
|
122
|
+
belongs(socket.getPeerCertificate(), expected);
|
|
123
|
+
/**
|
|
124
|
+
* Opens one connection with the credentials current at that moment.
|
|
125
|
+
* The handshake stays interruptible, so the reader's open timeout
|
|
126
|
+
* abandons a listener that never answers it, such as a plaintext peer.
|
|
127
|
+
*/
|
|
128
|
+
const open = (address) => Effect.gen(function* () {
|
|
129
|
+
let socket;
|
|
130
|
+
let secured = false;
|
|
131
|
+
yield* Scope.addFinalizer(yield* Effect.scope, Effect.sync(() => (secured ? socket?.destroySoon() : socket?.destroy())));
|
|
132
|
+
return yield* Effect.callback((resume) => {
|
|
133
|
+
socket = connect({
|
|
134
|
+
host: address.host,
|
|
135
|
+
port: address.port,
|
|
136
|
+
servername: SERVER_NAME,
|
|
137
|
+
secureContext: current.context,
|
|
138
|
+
rejectUnauthorized: true,
|
|
139
|
+
checkServerIdentity: (_host, peer) => belongs(peer, expected)
|
|
140
|
+
? undefined
|
|
141
|
+
: new Error(`Peer at ${address.host}:${address.port} is not a runner of ${expected}`),
|
|
142
|
+
});
|
|
143
|
+
const opened = socket;
|
|
144
|
+
const refuse = (cause) => resume(Effect.fail(Socket.SocketError.make({
|
|
145
|
+
reason: Socket.SocketOpenError.make({ kind: "Unknown", cause }),
|
|
146
|
+
})));
|
|
147
|
+
opened.once("secureConnect", () => {
|
|
148
|
+
if (!accepted(opened)) {
|
|
149
|
+
opened.destroy();
|
|
150
|
+
return refuse(new Error(`Peer at ${address.host}:${address.port} is not a runner of ${expected}`));
|
|
151
|
+
}
|
|
152
|
+
secured = true;
|
|
153
|
+
resume(Effect.succeed(opened));
|
|
154
|
+
});
|
|
155
|
+
opened.once("error", refuse);
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
const serialization = yield* RpcSerialization.RpcSerialization;
|
|
159
|
+
return Context.make(SocketServer.SocketServer, SocketServer.SocketServer.of({
|
|
160
|
+
address: server.address,
|
|
161
|
+
run: (handler) => server.run((socket) => Effect.gen(function* () {
|
|
162
|
+
const connection = Option.getOrUndefined(yield* Effect.serviceOption(NodeSocket.NetSocket));
|
|
163
|
+
if (connection !== undefined && accepted(connection))
|
|
164
|
+
return yield* handler(socket);
|
|
165
|
+
connection?.destroy();
|
|
166
|
+
})),
|
|
167
|
+
})).pipe(Context.add(Runners.RpcClientProtocol, Runners.RpcClientProtocol.of({
|
|
168
|
+
codecFor: serialization.codecFor,
|
|
169
|
+
make: Effect.fnUntraced(function* (address) {
|
|
170
|
+
const socket = yield* NodeSocket.fromDuplex(open(address), { openTimeout: 1000 });
|
|
171
|
+
return yield* RpcClient.makeProtocolSocket().pipe(Effect.provideService(Socket.Socket, socket), Effect.provideService(RpcSerialization.RpcSerialization, serialization));
|
|
172
|
+
}, Effect.orDie),
|
|
173
|
+
})), Context.add(PeerHealth, health));
|
|
174
|
+
}));
|
|
175
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Context, type Crypto, Effect } from "effect";
|
|
2
|
+
import { Sharding } from "effect/cluster";
|
|
3
|
+
import { SqlClient } from "effect/sql";
|
|
4
|
+
import { ActorError } from "../errors/actor.ts";
|
|
5
|
+
import { type InternalActors } from "./actors.ts";
|
|
6
|
+
import { type Request } from "./request.ts";
|
|
7
|
+
import { type QueryRegistration, type Registration } from "./members.ts";
|
|
8
|
+
import type { Holder } from "./connections/holder.ts";
|
|
9
|
+
export declare const committedReads: ({ registrations, queryRegistrations, services, allow, primary, replica, holder, }: {
|
|
10
|
+
readonly registrations: ReadonlyMap<string, Registration>;
|
|
11
|
+
readonly queryRegistrations: ReadonlyMap<string, QueryRegistration>;
|
|
12
|
+
readonly services: Context.Context<SqlClient.SqlClient | Crypto.Crypto | Sharding.Sharding>;
|
|
13
|
+
readonly allow: (request: Request, kind?: "command" | "query" | "stream") => Effect.Effect<void, ActorError>;
|
|
14
|
+
readonly primary: SqlClient.SqlClient;
|
|
15
|
+
readonly replica: SqlClient.SqlClient | undefined;
|
|
16
|
+
/** This runner's connection holder, where a watch parks. */
|
|
17
|
+
readonly holder: Holder;
|
|
18
|
+
}) => Pick<InternalActors["Service"], "exists" | "query" | "watch" | "pollWorkflow">;
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { Context, Effect, Semaphore } from "effect";
|
|
2
|
+
import { Sharding } from "effect/cluster";
|
|
3
|
+
import { SqlClient, SqlError } from "effect/sql";
|
|
4
|
+
import { ActorError, ActorUnavailable, InvalidInput, NotCreated, Timeout } from "../errors/actor.js";
|
|
5
|
+
import {} from "./actors.js";
|
|
6
|
+
import { Outcome } from "./request.js";
|
|
7
|
+
import {} from "./members.js";
|
|
8
|
+
import { watchStream } from "./connections/watch.js";
|
|
9
|
+
import { caughtUp, QueryPool } from "./database/replica.js";
|
|
10
|
+
import { withTenant } from "./database/tenancy.js";
|
|
11
|
+
import { replayEvents } from "./events/replay.js";
|
|
12
|
+
import { decompress, routingKey } from "./storage/codec.js";
|
|
13
|
+
import { accountsUsage, UsageAccounting } from "./telemetry/usage.js";
|
|
14
|
+
import { decodeResult } from "./workflows/engine.js";
|
|
15
|
+
/**
|
|
16
|
+
* The runtime's reads of committed rows outside any turn: whether an actor
|
|
17
|
+
* exists, a query member's answer, and a workflow execution's status. Each
|
|
18
|
+
* read runs on the caller's node without an activation, generation fence,
|
|
19
|
+
* receipt, or command id, rechecks access after it reads, and fails an
|
|
20
|
+
* unreachable database as `ActorUnavailable`.
|
|
21
|
+
*/
|
|
22
|
+
/** Watch reruns one runner runs at once; another waits for a place. */
|
|
23
|
+
const WATCH_RERUNS = 64;
|
|
24
|
+
export const committedReads = ({ registrations, queryRegistrations, services, allow, primary, replica, holder, }) => {
|
|
25
|
+
const reruns = Semaphore.makeUnsafe(WATCH_RERUNS);
|
|
26
|
+
const queryPool = Context.get(services, QueryPool);
|
|
27
|
+
const usage = Context.getUnsafe(services, UsageAccounting);
|
|
28
|
+
const accounting = accountsUsage(usage) ? usage : undefined;
|
|
29
|
+
const exists = Effect.fnUntraced(function* (ref) {
|
|
30
|
+
const registration = registrations.get(ref.actor);
|
|
31
|
+
if (registration === undefined)
|
|
32
|
+
return yield* ActorError.make({
|
|
33
|
+
reason: ActorUnavailable.make({ cause: new Error("Actor not registered") }),
|
|
34
|
+
});
|
|
35
|
+
const sql = yield* SqlClient.SqlClient;
|
|
36
|
+
const rows = yield* sql `
|
|
37
|
+
SELECT 1 FROM actor_generations
|
|
38
|
+
WHERE routing_key = ${routingKey({ ref, placement: registration.placement })}
|
|
39
|
+
AND tenant_id = ${ref.tenant} AND actor_type = ${ref.actor} AND actor_id = ${ref.id}`.pipe(withTenant(ref.tenant));
|
|
40
|
+
return rows.length > 0;
|
|
41
|
+
}, Effect.provideContext(services), Effect.catchIf(SqlError.isSqlError, (cause) => Effect.fail(ActorError.make({ reason: ActorUnavailable.make({ cause }) }))));
|
|
42
|
+
/**
|
|
43
|
+
* A query's answer. A watch's rerun passes `reads` and skips both access
|
|
44
|
+
* checks, because its session was authorized at open and is reauthorized
|
|
45
|
+
* on its bound; the recorder fills `reads`.
|
|
46
|
+
*/
|
|
47
|
+
const query = Effect.fnUntraced(function* (request, minVersion, reads) {
|
|
48
|
+
const registration = queryRegistrations.get(request.ref.actor);
|
|
49
|
+
const query = registration?.queries.get(request.command);
|
|
50
|
+
if (registration === undefined || query === undefined)
|
|
51
|
+
return yield* ActorError.make({
|
|
52
|
+
reason: ActorUnavailable.make({ cause: new Error("Query not registered") }),
|
|
53
|
+
});
|
|
54
|
+
if (reads === undefined)
|
|
55
|
+
yield* allow(request, "query");
|
|
56
|
+
const key = routingKey({ ref: request.ref, placement: registration.placement });
|
|
57
|
+
const read = (client) => Effect.gen(function* () {
|
|
58
|
+
const rows = yield* client `
|
|
59
|
+
SELECT event_sequence::text AS head, NULL AS key, NULL::bytea AS value
|
|
60
|
+
FROM actor_generations
|
|
61
|
+
WHERE routing_key = ${key} AND tenant_id = ${request.ref.tenant}
|
|
62
|
+
AND actor_type = ${request.ref.actor} AND actor_id = ${request.ref.id}
|
|
63
|
+
UNION ALL
|
|
64
|
+
SELECT NULL, key, value
|
|
65
|
+
FROM actor_state
|
|
66
|
+
WHERE routing_key = ${key} AND tenant_id = ${request.ref.tenant}
|
|
67
|
+
AND actor_type = ${request.ref.actor} AND actor_id = ${request.ref.id}`;
|
|
68
|
+
let head;
|
|
69
|
+
const state = [];
|
|
70
|
+
for (const row of rows)
|
|
71
|
+
if (row.head !== null)
|
|
72
|
+
head = row.head;
|
|
73
|
+
else
|
|
74
|
+
state.push([row.key, decompress(row.value)]);
|
|
75
|
+
if (head === undefined)
|
|
76
|
+
state.length = 0;
|
|
77
|
+
const cursor = head ?? "0";
|
|
78
|
+
const outcome = yield* query.run(request, state, cursor, (tag, after, limit) => replayEvents(request.ref, key, [tag], after, BigInt(cursor), limit).pipe(Effect.catchIf(SqlError.isSqlError, Effect.die), Effect.provideService(SqlClient.SqlClient, client), Effect.provideContext(services)), reads);
|
|
79
|
+
if (Outcome.guards.Defect(outcome) && SqlError.isSqlError(outcome.cause))
|
|
80
|
+
return yield* outcome.cause;
|
|
81
|
+
return outcome;
|
|
82
|
+
}).pipe(withTenant(request.ref.tenant), Effect.provideService(SqlClient.SqlClient, client));
|
|
83
|
+
const owned = registration.tables.length > 0 || registration.blobs.length > 0;
|
|
84
|
+
const local = owned ? primary : (queryPool ?? primary);
|
|
85
|
+
const outcome = yield* Effect.gen(function* () {
|
|
86
|
+
if (owned || replica === undefined)
|
|
87
|
+
return yield* read(local);
|
|
88
|
+
if (minVersion !== undefined) {
|
|
89
|
+
const ready = yield* caughtUp(replica, minVersion).pipe(Effect.catchIf(SqlError.isSqlError, () => Effect.succeed(false)));
|
|
90
|
+
if (!ready)
|
|
91
|
+
return yield* read(local);
|
|
92
|
+
}
|
|
93
|
+
return yield* read(replica).pipe(Effect.catchIf(SqlError.isSqlError, () => read(local)));
|
|
94
|
+
}).pipe(Effect.timeoutOrElse({
|
|
95
|
+
duration: registration.timeoutMs,
|
|
96
|
+
orElse: () => Effect.fail(ActorError.make({ reason: Timeout.make({ commandId: request.commandId }) })),
|
|
97
|
+
}));
|
|
98
|
+
if (reads === undefined) {
|
|
99
|
+
yield* allow(request, "query");
|
|
100
|
+
if (accounting !== undefined && !Outcome.guards.Defect(outcome))
|
|
101
|
+
yield* accounting.read({
|
|
102
|
+
ref: request.ref,
|
|
103
|
+
requestToken: request.usageToken,
|
|
104
|
+
watch: false,
|
|
105
|
+
sql: primary,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
return outcome;
|
|
109
|
+
}, Effect.provideContext(services), Effect.catchIf(SqlError.isSqlError, (cause) => Effect.fail(ActorError.make({ reason: ActorUnavailable.make({ cause }) }))));
|
|
110
|
+
return {
|
|
111
|
+
exists,
|
|
112
|
+
query: (request, minVersion) => query(request, minVersion),
|
|
113
|
+
watch: (request, { minVersion, expiresAt }) => Effect.gen(function* () {
|
|
114
|
+
const registration = registrations.get(request.ref.actor);
|
|
115
|
+
const watched = queryRegistrations.get(request.ref.actor)?.queries.get(request.command);
|
|
116
|
+
if (registration === undefined || watched === undefined)
|
|
117
|
+
return yield* ActorError.make({
|
|
118
|
+
reason: ActorUnavailable.make({ cause: new Error("Query not registered") }),
|
|
119
|
+
});
|
|
120
|
+
if (!watched.watch)
|
|
121
|
+
return yield* ActorError.make({ reason: InvalidInput.make({ code: "not_watchable" }) });
|
|
122
|
+
if (!(yield* exists(request.ref)))
|
|
123
|
+
return yield* ActorError.make({ reason: NotCreated.make({}) });
|
|
124
|
+
const rerun = (version, reads) => reruns.withPermit(Effect.suspend(() => query(request, version(), reads)));
|
|
125
|
+
const { usageToken } = request;
|
|
126
|
+
let counted = false;
|
|
127
|
+
return yield* watchStream({
|
|
128
|
+
holder,
|
|
129
|
+
request,
|
|
130
|
+
minIntervalMs: registration.policy.watch.minIntervalMs,
|
|
131
|
+
reconcileMs: registration.policy.watch.reconcileMs,
|
|
132
|
+
minVersion,
|
|
133
|
+
expiresAt,
|
|
134
|
+
rerun: accounting === undefined || usageToken === undefined
|
|
135
|
+
? rerun
|
|
136
|
+
: (version, reads) => rerun(version, reads).pipe(Effect.tap((outcome) => counted || Outcome.guards.Defect(outcome)
|
|
137
|
+
? Effect.void
|
|
138
|
+
: allow(request, "query").pipe(Effect.andThen(accounting.read({
|
|
139
|
+
ref: request.ref,
|
|
140
|
+
requestToken: usageToken,
|
|
141
|
+
watch: true,
|
|
142
|
+
sql: primary,
|
|
143
|
+
})), Effect.tap(() => Effect.sync(() => void (counted = true))), Effect.catchIf(SqlError.isSqlError, (cause) => Effect.fail(ActorError.make({ reason: ActorUnavailable.make({ cause }) })))))),
|
|
144
|
+
});
|
|
145
|
+
}),
|
|
146
|
+
pollWorkflow: Effect.fnUntraced(function* (request) {
|
|
147
|
+
const registration = registrations.get(request.ref.actor) ?? queryRegistrations.get(request.ref.actor);
|
|
148
|
+
if (registration === undefined)
|
|
149
|
+
return yield* ActorError.make({
|
|
150
|
+
reason: ActorUnavailable.make({ cause: new Error("Actor not registered") }),
|
|
151
|
+
});
|
|
152
|
+
yield* allow(request);
|
|
153
|
+
const sql = yield* SqlClient.SqlClient;
|
|
154
|
+
const [row] = yield* sql `
|
|
155
|
+
SELECT status, result FROM actor_workflow_executions
|
|
156
|
+
WHERE routing_key = ${routingKey({ ref: request.ref, placement: registration.placement })}
|
|
157
|
+
AND execution_id = ${request.payload} AND tenant_id = ${request.ref.tenant}
|
|
158
|
+
AND actor_type = ${request.ref.actor} AND actor_id = ${request.ref.id}
|
|
159
|
+
AND workflow = ${request.command}`.pipe(withTenant(request.ref.tenant));
|
|
160
|
+
yield* allow(request);
|
|
161
|
+
if (row === undefined)
|
|
162
|
+
return undefined;
|
|
163
|
+
return {
|
|
164
|
+
finished: row.status === "finished",
|
|
165
|
+
result: row.result === null ? undefined : yield* decodeResult(row.result),
|
|
166
|
+
};
|
|
167
|
+
}, Effect.provideContext(services), Effect.catchIf(SqlError.isSqlError, (cause) => Effect.fail(ActorError.make({ reason: ActorUnavailable.make({ cause }) })))),
|
|
168
|
+
};
|
|
169
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Context, Crypto, Effect } from "effect";
|
|
2
|
+
import { Sharding } from "effect/cluster";
|
|
3
|
+
import { SqlClient } from "effect/sql";
|
|
4
|
+
/**
|
|
5
|
+
* Builds the runtime's readiness answer, returned as `serving`: not ready
|
|
6
|
+
* while routing is shut down, assigned shards are not acquired, a mutual TLS
|
|
7
|
+
* transport can no longer peer, or nothing is registered, otherwise ready
|
|
8
|
+
* when storage answers. PGlite always answers from the layer's own lifetime, since
|
|
9
|
+
* a single connection held by a turn would make a probe report unready;
|
|
10
|
+
* Postgres storage answers are reused for at most a second; public runner
|
|
11
|
+
* registration snapshots are checked on each probe.
|
|
12
|
+
*/
|
|
13
|
+
export declare const servingReadiness: (args_0: {
|
|
14
|
+
readonly sharding: Sharding.Sharding["Service"];
|
|
15
|
+
readonly services: Context.Context<SqlClient.SqlClient | Crypto.Crypto | Sharding.Sharding>;
|
|
16
|
+
readonly registrations: ReadonlyMap<string, unknown>;
|
|
17
|
+
readonly queryRegistrations: ReadonlyMap<string, unknown>;
|
|
18
|
+
readonly jobRegistrations: ReadonlyMap<string, unknown>;
|
|
19
|
+
}) => Effect.Effect<{
|
|
20
|
+
serving: Effect.Effect<{
|
|
21
|
+
readonly ready: false;
|
|
22
|
+
readonly reason: "routing";
|
|
23
|
+
} | {
|
|
24
|
+
readonly ready: false;
|
|
25
|
+
readonly reason: "unregistered";
|
|
26
|
+
} | {
|
|
27
|
+
readonly ready: false;
|
|
28
|
+
readonly reason: "storage";
|
|
29
|
+
} | {
|
|
30
|
+
readonly ready: false;
|
|
31
|
+
readonly reason: "peering";
|
|
32
|
+
} | {
|
|
33
|
+
readonly reason?: undefined;
|
|
34
|
+
readonly ready: true;
|
|
35
|
+
}, never, never>;
|
|
36
|
+
}, never, never>;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Context, Crypto, Effect, Option } from "effect";
|
|
2
|
+
import { PgliteClient } from "@effect/sql-pglite";
|
|
3
|
+
import { Sharding } from "effect/cluster";
|
|
4
|
+
import { SqlClient } from "effect/sql";
|
|
5
|
+
import { PeerHealth } from "./peering/transport.js";
|
|
6
|
+
import { RunnerReadiness } from "./runner.js";
|
|
7
|
+
/** How long readiness waits for the database before it reports storage unavailable. */
|
|
8
|
+
const READINESS_STORAGE_TIMEOUT = "2 seconds";
|
|
9
|
+
/** How long readiness reuses its last storage answer. */
|
|
10
|
+
const READINESS_CACHE = "1 second";
|
|
11
|
+
/**
|
|
12
|
+
* Builds the runtime's readiness answer, returned as `serving`: not ready
|
|
13
|
+
* while routing is shut down, assigned shards are not acquired, a mutual TLS
|
|
14
|
+
* transport can no longer peer, or nothing is registered, otherwise ready
|
|
15
|
+
* when storage answers. PGlite always answers from the layer's own lifetime, since
|
|
16
|
+
* a single connection held by a turn would make a probe report unready;
|
|
17
|
+
* Postgres storage answers are reused for at most a second; public runner
|
|
18
|
+
* registration snapshots are checked on each probe.
|
|
19
|
+
*/
|
|
20
|
+
export const servingReadiness = Effect.fnUntraced(function* ({ sharding, services, registrations, queryRegistrations, jobRegistrations, }) {
|
|
21
|
+
const embedded = Option.isSome(yield* Effect.serviceOption(PgliteClient.PgliteClient));
|
|
22
|
+
const runner = yield* Effect.serviceOption(RunnerReadiness);
|
|
23
|
+
const peering = yield* Effect.serviceOption(PeerHealth);
|
|
24
|
+
const storage = embedded
|
|
25
|
+
? Effect.succeed(true)
|
|
26
|
+
: yield* Effect.gen(function* () {
|
|
27
|
+
const sql = yield* SqlClient.SqlClient;
|
|
28
|
+
return yield* sql `SELECT 1`.pipe(Effect.timeoutOption(READINESS_STORAGE_TIMEOUT), Effect.map(Option.isSome), Effect.orElseSucceed(() => false));
|
|
29
|
+
}).pipe(Effect.provideContext(services), Effect.cachedWithTTL(READINESS_CACHE));
|
|
30
|
+
const serving = Effect.gen(function* () {
|
|
31
|
+
if (yield* sharding.isShutdown)
|
|
32
|
+
return { ready: false, reason: "routing" };
|
|
33
|
+
if (registrations.size + queryRegistrations.size + jobRegistrations.size === 0)
|
|
34
|
+
return { ready: false, reason: "unregistered" };
|
|
35
|
+
if (!(yield* storage))
|
|
36
|
+
return { ready: false, reason: "storage" };
|
|
37
|
+
if (Option.isSome(peering) && !(yield* peering.value.healthy))
|
|
38
|
+
return { ready: false, reason: "peering" };
|
|
39
|
+
if (Option.isSome(runner) && !(yield* runner.value.acquired(sharding)))
|
|
40
|
+
return { ready: false, reason: "routing" };
|
|
41
|
+
return { ready: true };
|
|
42
|
+
});
|
|
43
|
+
return { serving };
|
|
44
|
+
});
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { Context, Crypto, Effect } from "effect";
|
|
2
|
+
import { Sharding } from "effect/cluster";
|
|
3
|
+
import { SqlClient, SqlError } from "effect/sql";
|
|
4
|
+
import type { ActorError } from "../errors/actor.ts";
|
|
5
|
+
import type { JobRegistration, QueryRegistration, Registration } from "./members.ts";
|
|
6
|
+
import type { InternalActors } from "./actors.ts";
|
|
7
|
+
import type { PayloadDeclaration } from "../members/payload.ts";
|
|
8
|
+
import type { AnyOwnedTable } from "../tables/owned.ts";
|
|
9
|
+
import type { HeldActorType } from "./connections/holder.ts";
|
|
10
|
+
import type { Owner } from "./connections/owner.ts";
|
|
11
|
+
import type { Authorize } from "./connections/streams.ts";
|
|
12
|
+
import type { Transport } from "./connections/transport.ts";
|
|
13
|
+
import type { tenantContent } from "./content/store.ts";
|
|
14
|
+
import type { TurnGate } from "./drain.ts";
|
|
15
|
+
import { registerActor } from "./entity/register.ts";
|
|
16
|
+
import type { SubscriptionRelay } from "./subscriptions/relay.ts";
|
|
17
|
+
import { DefectLog } from "./telemetry/defects.ts";
|
|
18
|
+
import { FrameworkClock } from "./turn/admission.ts";
|
|
19
|
+
import { OutboxRuntime } from "./turn/outbox.ts";
|
|
20
|
+
/**
|
|
21
|
+
* Registers actor, query, and job layers with the runtime. Each
|
|
22
|
+
* registration is refused unless its placement, tables, content, workflows,
|
|
23
|
+
* payload versions, and routed subscriptions agree with the database and the
|
|
24
|
+
* runtime's configuration; an accepted one is recorded for the relay, the
|
|
25
|
+
* connection holder, and the sweeps, and forgotten when its layer's scope
|
|
26
|
+
* closes.
|
|
27
|
+
*/
|
|
28
|
+
export declare const actorRegistration: ({ registrations, queryRegistrations, jobRegistrations, residency, diagnostics, owners, heldTypes, heldType, sweepsWorkflows, checked, services, frameworkClock, content, retryWindowMs, tableRole, adoptionRole, enforcedTypes, writerDeclarations, refreshPayloadWriters, subscriptions, transport, authorize, gate, writable, defectLog, outbox, }: {
|
|
29
|
+
readonly registrations: Map<string, Registration>;
|
|
30
|
+
readonly queryRegistrations: Map<string, QueryRegistration>;
|
|
31
|
+
readonly jobRegistrations: Map<string, JobRegistration>;
|
|
32
|
+
readonly residency: Map<string, (entityId: string) => boolean>;
|
|
33
|
+
/** Each actor type's view of its activations, for a delivery that timed out. */
|
|
34
|
+
readonly diagnostics: Map<string, Pick<Effect.Success<ReturnType<typeof registerActor>>, "diagnose" | "restarting">>;
|
|
35
|
+
readonly owners: Map<string, Owner>;
|
|
36
|
+
readonly heldTypes: Map<string, HeldActorType>;
|
|
37
|
+
readonly heldType: (registration: Registration) => HeldActorType;
|
|
38
|
+
readonly sweepsWorkflows: Set<string>;
|
|
39
|
+
readonly checked: Set<AnyOwnedTable>;
|
|
40
|
+
readonly services: Context.Context<SqlClient.SqlClient | Crypto.Crypto | Sharding.Sharding>;
|
|
41
|
+
readonly frameworkClock: (typeof FrameworkClock)["Service"];
|
|
42
|
+
readonly content: ReturnType<typeof tenantContent> | undefined;
|
|
43
|
+
readonly retryWindowMs: number;
|
|
44
|
+
readonly tableRole: string | undefined;
|
|
45
|
+
/** The writer role of enforced adopted tables, when the runtime has one. */
|
|
46
|
+
readonly adoptionRole: string | undefined;
|
|
47
|
+
/** Actor types whose turns take the writer role; filled as each type registers. */
|
|
48
|
+
readonly enforcedTypes: Set<string>;
|
|
49
|
+
readonly writerDeclarations: Array<PayloadDeclaration>;
|
|
50
|
+
readonly refreshPayloadWriters: Effect.Effect<void, SqlError.SqlError>;
|
|
51
|
+
readonly subscriptions: SubscriptionRelay;
|
|
52
|
+
readonly transport: Transport;
|
|
53
|
+
readonly authorize: Authorize;
|
|
54
|
+
readonly gate: TurnGate;
|
|
55
|
+
readonly writable: Effect.Effect<void, ActorError>;
|
|
56
|
+
readonly defectLog: DefectLog["Service"];
|
|
57
|
+
readonly outbox: (typeof OutboxRuntime)["Service"];
|
|
58
|
+
}) => Pick<InternalActors["Service"], "register" | "registerQueries" | "registerJobs">;
|