@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,876 @@
|
|
|
1
|
+
import { PgClient, PgTypes } from "@effect/sql-pg";
|
|
2
|
+
import { PgliteClient } from "@effect/sql-pglite";
|
|
3
|
+
import { Cause, Clock, Semaphore, Context, Crypto, Duration, Deferred, Effect, Fiber, Layer, Option, Result, Schedule, Schema, Stream, } from "effect";
|
|
4
|
+
import { ClusterError, Entity, EntityId, RunnerHealth, Runners, RunnerStorage, Sharding, ShardingConfig, } from "effect/cluster";
|
|
5
|
+
import { SqlClient, SqlError } from "effect/sql";
|
|
6
|
+
import { ActorError, ActorUnavailable, InvalidInput, Unauthorized, Timeout, MailboxFull, RunnerAtCapacity, } from "../errors/actor.js";
|
|
7
|
+
import { Actors } from "../handles/actors.js";
|
|
8
|
+
import {} from "./members.js";
|
|
9
|
+
import { DeliveryFailed } from "./request.js";
|
|
10
|
+
import { InternalActors } from "./actors.js";
|
|
11
|
+
import { System } from "../identity/caller.js";
|
|
12
|
+
import { deriveMintId } from "../identity/mint.js";
|
|
13
|
+
import { migrate } from "./database/migrations.js";
|
|
14
|
+
import { NekiTurnSessions } from "./database/neki/session.js";
|
|
15
|
+
import { queryPoolLayer, ReadReplica, replicaLayer } from "./database/replica.js";
|
|
16
|
+
import { Coordination, coordinationLayer } from "./database/coordination.js";
|
|
17
|
+
import { withKeepalives } from "./database/keepalive.js";
|
|
18
|
+
import { checkRowLevelSecurity, TenantScope } from "./database/tenancy.js";
|
|
19
|
+
import { retryDelay } from "./retry.js";
|
|
20
|
+
import { withoutDatabase } from "./jobs/isolation.js";
|
|
21
|
+
import { pglite } from "./database/pglite.js";
|
|
22
|
+
import { commandEntity, connectionEntity, encodeEntityId } from "./entity/register.js";
|
|
23
|
+
import { connectionHolder } from "./connections/holder.js";
|
|
24
|
+
import { holderShardGroups, holderTransport } from "./connections/transport.js";
|
|
25
|
+
import { ProgressSink, ProgressTap } from "./jobs/progress.js";
|
|
26
|
+
import { FEED_MEMBER, isWatchMember, watchedQuery } from "./connections/protocol.js";
|
|
27
|
+
import { checkIdentity, databaseTime, FrameworkClock } from "./turn/admission.js";
|
|
28
|
+
import { routingKey } from "./storage/codec.js";
|
|
29
|
+
import { recordedPlacement } from "./storage/placements.js";
|
|
30
|
+
import { TurnHooks } from "./turn/hooks.js";
|
|
31
|
+
import { requestAttributes, SpanNames } from "./telemetry/spans.js";
|
|
32
|
+
import { DefectLog, boundedDefectLog } from "./telemetry/defects.js";
|
|
33
|
+
import { OperatorRuntime, operatorRuntime } from "./operators/repair.js";
|
|
34
|
+
import { seedRuntime } from "./operators/seed.js";
|
|
35
|
+
import { TelemetrySampler } from "./telemetry/sampler.js";
|
|
36
|
+
import { turnGroups } from "./turn/group.js";
|
|
37
|
+
import { TurnConnections, turnConnections } from "./turn/pipeline.js";
|
|
38
|
+
import { outboxRelay } from "./turn/relay.js";
|
|
39
|
+
import { subscriptionRelay, } from "./subscriptions/relay.js";
|
|
40
|
+
import { DEFAULT_WRITER_WINDOW_MS, refreshWriters } from "./payloads/versions.js";
|
|
41
|
+
import { ExecutionTarget, INTERRUPT } from "../handles/workflow.js";
|
|
42
|
+
import { decodeExecutionId } from "../identity/execution.js";
|
|
43
|
+
import { coordinatedRunnerStorage, keepAcquiredShards, ShardLease, tableShardLease, } from "./topology/locks.js";
|
|
44
|
+
import { directMessages } from "./topology/messages.js";
|
|
45
|
+
import { MailboxRefusals, mailboxRefusals } from "./topology/admission.js";
|
|
46
|
+
import { bindBlobs } from "./turn/blobs.js";
|
|
47
|
+
import { ContentStore } from "../handles/content.js";
|
|
48
|
+
import { isContent } from "../members/blob.js";
|
|
49
|
+
import { grantKeys } from "./content/grant.js";
|
|
50
|
+
import { MAX_CONTENT_BYTES, tenantContent } from "./content/store.js";
|
|
51
|
+
import { ContentHooks } from "./turn/hooks.js";
|
|
52
|
+
import { bindTables, rowsDatabase } from "./turn/rows.js";
|
|
53
|
+
import { admissionLimit, isOverloaded, overloaded } from "./admission.js";
|
|
54
|
+
import { boundedLayer, isPoolRefusal } from "./database/bounded.js";
|
|
55
|
+
import { RuntimeControl, runtimeControl, turnGate } from "./drain.js";
|
|
56
|
+
import { eventFeeds } from "./feeds.js";
|
|
57
|
+
import { committedReads } from "./queries.js";
|
|
58
|
+
import { servingReadiness } from "./readiness.js";
|
|
59
|
+
import { acquiredShards, checkRunnerConfiguration, RunnerReadiness, LocalRequestSerialization, RunnerWiring, } from "./runner.js";
|
|
60
|
+
import { actorRegistration } from "./registration.js";
|
|
61
|
+
import { startSweeps } from "./sweeps.js";
|
|
62
|
+
import { checkFleet } from "./fleet/checks.js";
|
|
63
|
+
import { maintain } from "./fleet/maintainer.js";
|
|
64
|
+
import { fleetSubscriptions } from "./fleet/subscribe.js";
|
|
65
|
+
const Count = Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 1_000_000 }));
|
|
66
|
+
const Millis = Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 2_147_483_647 }));
|
|
67
|
+
const millis = (duration) => Millis.make(Math.floor(Duration.toMillis(Duration.fromInputUnsafe(duration))));
|
|
68
|
+
const decodeTarget = Schema.decodeEffect(ExecutionTarget);
|
|
69
|
+
/** How often a fleet subscription is authorized again when its source's actor type is not registered here. */
|
|
70
|
+
const DEFAULT_REAUTHORIZE_MS = 60_000;
|
|
71
|
+
/** Added to the longest turn a claimed intent's receiver may take. */
|
|
72
|
+
const CLAIM_MARGIN_MS = 5000;
|
|
73
|
+
/** The claim lease when no actor type is registered: default policies' 30 s + 2 s + margin. */
|
|
74
|
+
const DEFAULT_CLAIM_LEASE_MS = 37_000;
|
|
75
|
+
/** How long a progress send may take before it is given up as a lost frame. */
|
|
76
|
+
const PROGRESS_SEND_TIMEOUT = "5 seconds";
|
|
77
|
+
/**
|
|
78
|
+
* An entity type with no messages, registered before any actor. The cluster's
|
|
79
|
+
* idle sweep takes its interval from the first entity type registered and
|
|
80
|
+
* sleeps that long before it reads any later one, so an actor type with a
|
|
81
|
+
* 60-second `hibernateAfter` registering first held every activation for up to
|
|
82
|
+
* 30 seconds past its own `hibernateAfter`. This type's 5-second idle time, the
|
|
83
|
+
* sweep's shortest interval, makes every sweep 5 seconds apart from the start.
|
|
84
|
+
*/
|
|
85
|
+
const IdleSweep = Entity.make("akter/IdleSweep", []);
|
|
86
|
+
/**
|
|
87
|
+
* Builds the runtime: migrates and checks the database, registers every actor,
|
|
88
|
+
* effect, query, and subscription layer, and starts the relay and background
|
|
89
|
+
* sweeps. The returned layer provides `RuntimeControl`, and fails to build when
|
|
90
|
+
* the schema or declared payloads are incompatible.
|
|
91
|
+
*
|
|
92
|
+
* Constraints the wiring keeps:
|
|
93
|
+
* - Turns run through the drain gate, so a drain refuses new turns and
|
|
94
|
+
* interrupts the rest. The runtime scope, not the caller, owns an in-flight
|
|
95
|
+
* turn: interrupting a waiter never cancels it.
|
|
96
|
+
* - Commands are direct, so Cluster keeps no messages and the receipt is the
|
|
97
|
+
* only admission record; a restarted activation or lost runner drops the
|
|
98
|
+
* uncommitted attempt, the handle retries with the same command id, and the
|
|
99
|
+
* receipt replays anything that committed. Durable intents use the
|
|
100
|
+
* actor-shard outbox. Retries wait from the error's own `retryAfter`, bounded
|
|
101
|
+
* in total by the delivery timeout.
|
|
102
|
+
* - Intents are admitted by their sending turn, so internal delivery skips the
|
|
103
|
+
* external access and expiry checks: revocation stops new commands, not
|
|
104
|
+
* committed obligations. A draining runner admits no new external work. Only
|
|
105
|
+
* the relay presents a mint proof or delivers a subscription envelope.
|
|
106
|
+
* - A turn runs only in a resident activation. After a capacity rejection with
|
|
107
|
+
* none resident, the latest attempt was not admitted, though an earlier one
|
|
108
|
+
* may have committed.
|
|
109
|
+
* - Queries and feeds read committed rows on the caller's node without an
|
|
110
|
+
* activation, generation fence, receipt, or command id. State and events are
|
|
111
|
+
* read against one event head so they describe one moment; a replica answers
|
|
112
|
+
* only once it has replayed the caller's commit version, else the primary
|
|
113
|
+
* does. Types with owned tables or blobs read their state on the primary,
|
|
114
|
+
* one server per query. No `statement_timeout` bounds query reads;
|
|
115
|
+
* interrupting one past `commandTimeout` cancels its statement on the server.
|
|
116
|
+
* Access is rechecked after the handler, so a result is released only to a
|
|
117
|
+
* caller still allowed. A failed replay read is unavailability, not a defect.
|
|
118
|
+
* - Effect progress is fire-and-forget to the performing actor's connection
|
|
119
|
+
* entity: no retry, no acknowledgment, and a lost message is a lost frame.
|
|
120
|
+
* Each effect's last frame is awaited so its close never overtakes it.
|
|
121
|
+
* - Payload versions this runtime writes are recorded and heartbeat before a
|
|
122
|
+
* type takes any shard, refreshed one at a time with the time taken before
|
|
123
|
+
* the statement is sent, so the gate's window can only end early.
|
|
124
|
+
* - Content grants are bound to the database's deployment id. The content
|
|
125
|
+
* sweep waits out the longest turn that may attach content across every
|
|
126
|
+
* runner, and each tenant is swept at most once an hour.
|
|
127
|
+
* - Exactly one runner of the deployment runs the telemetry sampler; runtimes
|
|
128
|
+
* sharing one Sharding in a process share its one sampler.
|
|
129
|
+
* - Readiness on PGlite always answers from the layer's own lifetime, since a
|
|
130
|
+
* single connection held by a turn would make a probe report unready; on
|
|
131
|
+
* Postgres the database answers at most once a second.
|
|
132
|
+
* - PGlite keeps runner bookkeeping in memory because SqlRunnerStorage would
|
|
133
|
+
* reserve its single connection for the layer's lifetime. Postgres uses
|
|
134
|
+
* advisory locks, held by a live session, so no second runner can take a
|
|
135
|
+
* shard while its holder runs.
|
|
136
|
+
* - An unreachable database fails a read as `ActorUnavailable`, which callers
|
|
137
|
+
* retry like any delivery failure; it is not a defect.
|
|
138
|
+
*/
|
|
139
|
+
export const layer = (options = {}) => {
|
|
140
|
+
const enforcedTypes = new Set();
|
|
141
|
+
const retryWindowMs = Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 2_592_000_000 })).make(options.retryWindowMs ?? 86_400_000);
|
|
142
|
+
const maxResidentActors = Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 2_147_483_647 })).make(options.maxResidentActors ?? 10_000);
|
|
143
|
+
const admissionSettings = {
|
|
144
|
+
concurrency: Count.make(options.admission?.concurrency ?? 64),
|
|
145
|
+
wait: Duration.millis(millis(options.admission?.wait ?? "100 millis")),
|
|
146
|
+
requests: Count.make(options.admission?.requests ?? 64),
|
|
147
|
+
};
|
|
148
|
+
const executorLeaseMs = millis(options.executors?.lease ?? "60 seconds");
|
|
149
|
+
if (executorLeaseMs < 3000)
|
|
150
|
+
throw new Error("executors.lease must be at least 3 seconds");
|
|
151
|
+
const cancelCheckMs = Math.min(options.executors?.cancelCheck === undefined
|
|
152
|
+
? executorLeaseMs / 3
|
|
153
|
+
: millis(options.executors.cancelCheck), executorLeaseMs / 3);
|
|
154
|
+
if (cancelCheckMs < 1000)
|
|
155
|
+
throw new Error("executors.cancelCheck must be at least 1 second");
|
|
156
|
+
const claimLeaseMs = options.relay?.claimLease === undefined ? undefined : millis(options.relay.claimLease);
|
|
157
|
+
const relaySettings = {
|
|
158
|
+
pollMs: millis(options.relay?.poll ?? "1 second"),
|
|
159
|
+
passLimit: Count.make(options.relay?.passLimit ?? 256),
|
|
160
|
+
deliveryConcurrency: Count.make(options.relay?.deliveryConcurrency ?? 16),
|
|
161
|
+
maxBackoffMs: millis(options.relay?.maxBackoff ?? "256 seconds"),
|
|
162
|
+
executorConcurrency: Count.make(options.executors?.concurrency ?? 64),
|
|
163
|
+
executorLeaseMs,
|
|
164
|
+
retryWindowMs,
|
|
165
|
+
cancelCheckMs,
|
|
166
|
+
};
|
|
167
|
+
const defectCapacity = Count.make(options.observability?.defects ?? 1000);
|
|
168
|
+
const sampleEveryMs = millis(options.observability?.sampleEvery ?? "15 seconds");
|
|
169
|
+
const contentGraceMs = Duration.toMillis(Duration.fromInputUnsafe(options.content?.grace ?? "24 hours"));
|
|
170
|
+
const contentSkewMs = Duration.toMillis(Duration.fromInputUnsafe(options.content?.skew ?? "60 seconds"));
|
|
171
|
+
if (!Number.isSafeInteger(contentGraceMs) ||
|
|
172
|
+
contentGraceMs < 0 ||
|
|
173
|
+
!Number.isSafeInteger(contentSkewMs) ||
|
|
174
|
+
contentSkewMs < 0)
|
|
175
|
+
throw new Error("content.grace and content.skew must be finite, non-negative whole milliseconds");
|
|
176
|
+
const subscriptionConcurrency = Count.make(options.relay?.subscriptionConcurrency ?? 16);
|
|
177
|
+
const writerWindowMs = options.payloadWriterWindow === undefined
|
|
178
|
+
? DEFAULT_WRITER_WINDOW_MS
|
|
179
|
+
: millis(options.payloadWriterWindow);
|
|
180
|
+
if (writerWindowMs < 1000)
|
|
181
|
+
throw new Error("payloadWriterWindow must be at least 1 second");
|
|
182
|
+
const subscriptionBatch = Count.make(options.relay?.subscriptionBatch ?? 16);
|
|
183
|
+
const runtime = Layer.effectContext(Effect.gen(function* () {
|
|
184
|
+
const crypto = yield* Crypto.Crypto;
|
|
185
|
+
const scope = yield* Effect.scope;
|
|
186
|
+
const sharding = yield* Sharding.Sharding;
|
|
187
|
+
yield* sharding.registerEntity(IdleSweep, Effect.succeed(IdleSweep.of({})), {
|
|
188
|
+
maxIdleTime: "5 seconds",
|
|
189
|
+
});
|
|
190
|
+
const registrations = new Map();
|
|
191
|
+
const residency = new Map();
|
|
192
|
+
const refusals = yield* MailboxRefusals;
|
|
193
|
+
refusals.refuse = (address) => {
|
|
194
|
+
const registration = registrations.get(address.entityType);
|
|
195
|
+
if (registration === undefined ||
|
|
196
|
+
residency.get(address.entityType)?.(address.entityId) !== true)
|
|
197
|
+
return undefined;
|
|
198
|
+
return registration.policy.mailboxCapacity === "unbounded"
|
|
199
|
+
? overloaded("activation")
|
|
200
|
+
: ActorError.make({ reason: MailboxFull.make({}) });
|
|
201
|
+
};
|
|
202
|
+
const diagnostics = new Map();
|
|
203
|
+
const owners = new Map();
|
|
204
|
+
const sweepsWorkflows = new Set();
|
|
205
|
+
const queryRegistrations = new Map();
|
|
206
|
+
const jobRegistrations = new Map();
|
|
207
|
+
const runtimeId = yield* crypto.randomUUIDv4.pipe(Effect.orDie);
|
|
208
|
+
const frameworkClock = yield* FrameworkClock;
|
|
209
|
+
const writerDeclarations = [];
|
|
210
|
+
let refreshedAt;
|
|
211
|
+
const services = yield* Effect.context();
|
|
212
|
+
const defectLog = boundedDefectLog(defectCapacity);
|
|
213
|
+
const database = yield* rowsDatabase;
|
|
214
|
+
const clockOffset = yield* FrameworkClock;
|
|
215
|
+
const content = options.content === undefined
|
|
216
|
+
? undefined
|
|
217
|
+
: tenantContent({
|
|
218
|
+
grants: yield* grantKeys(options.content.keys, (yield* (yield* SqlClient.SqlClient) `
|
|
219
|
+
SELECT deployment_id FROM actor_deployment`.pipe(Effect.orDie))[0].deployment_id),
|
|
220
|
+
graceMs: contentGraceMs,
|
|
221
|
+
skewMs: contentSkewMs,
|
|
222
|
+
singleConnection: Option.isSome(yield* Effect.serviceOption(PgliteClient.PgliteClient)),
|
|
223
|
+
offset: () => clockOffset.offsetMillis(),
|
|
224
|
+
hooks: yield* ContentHooks,
|
|
225
|
+
});
|
|
226
|
+
const contentBinding = content === undefined
|
|
227
|
+
? undefined
|
|
228
|
+
: { store: content, skewMs: contentSkewMs, offset: () => clockOffset.offsetMillis() };
|
|
229
|
+
const primary = Context.get(services, SqlClient.SqlClient);
|
|
230
|
+
const replica = yield* ReadReplica;
|
|
231
|
+
let observed;
|
|
232
|
+
const observe = (executed) => Effect.sync(() => {
|
|
233
|
+
const version = executed.version;
|
|
234
|
+
if (version !== undefined &&
|
|
235
|
+
(observed === undefined || BigInt(version) > BigInt(observed)))
|
|
236
|
+
observed = version;
|
|
237
|
+
});
|
|
238
|
+
const gate = turnGate();
|
|
239
|
+
const admission = admissionLimit({
|
|
240
|
+
limit: admissionSettings.concurrency,
|
|
241
|
+
wait: admissionSettings.wait,
|
|
242
|
+
});
|
|
243
|
+
const requests = admissionLimit({ limit: admissionSettings.requests, wait: Duration.zero });
|
|
244
|
+
let holder;
|
|
245
|
+
const transport = yield* holderTransport((message) => Effect.suspend(() => holder.deliver(message)));
|
|
246
|
+
const connectionCall = (effect) => Effect.suspend(() => effect.pipe(Effect.forkIn(scope))).pipe(Effect.flatMap(Fiber.join), Effect.catchCause((cause) => {
|
|
247
|
+
const failure = Cause.findErrorOption(cause);
|
|
248
|
+
if (Option.isSome(failure) && Schema.is(ActorError)(failure.value))
|
|
249
|
+
return Effect.fail(failure.value);
|
|
250
|
+
return Effect.fail(ActorError.make({ reason: ActorUnavailable.make({ cause: Cause.squash(cause) }) }));
|
|
251
|
+
}));
|
|
252
|
+
const heldTypes = new Map();
|
|
253
|
+
const shardLockMs = Duration.toMillis(Option.match(yield* Effect.serviceOption(ShardingConfig.ShardingConfig), {
|
|
254
|
+
onNone: () => ShardingConfig.defaults.shardLockExpiration,
|
|
255
|
+
onSome: (config) => config.shardLockExpiration,
|
|
256
|
+
}));
|
|
257
|
+
const heldType = (registration) => {
|
|
258
|
+
const entity = connectionEntity(registration.name);
|
|
259
|
+
const client = (ref) => Effect.gen(function* () {
|
|
260
|
+
const make = yield* sharding.makeClient(entity);
|
|
261
|
+
return make(yield* entityId(ref));
|
|
262
|
+
});
|
|
263
|
+
return {
|
|
264
|
+
deliveryMs: registration.policy.deliveryMs,
|
|
265
|
+
takeoverMs: shardLockMs + registration.policy.deliveryMs,
|
|
266
|
+
reauthorizeMs: registration.policy.reauthorizeMs,
|
|
267
|
+
retryWindowMs,
|
|
268
|
+
placement: registration.placement,
|
|
269
|
+
routingKey: (ref) => routingKey({ ref, placement: registration.placement }),
|
|
270
|
+
hasResync: (member) => member === FEED_MEMBER ||
|
|
271
|
+
isWatchMember(member) ||
|
|
272
|
+
(registration.connections.get(member)?.hasResync ?? false),
|
|
273
|
+
hasMember: (member) => member === FEED_MEMBER
|
|
274
|
+
? registration.feeds.size > 0
|
|
275
|
+
: isWatchMember(member)
|
|
276
|
+
? registration.watches.has(watchedQuery(member))
|
|
277
|
+
: registration.connections.has(member),
|
|
278
|
+
channel: {
|
|
279
|
+
open: (request) => connectionCall(Effect.flatMap(client(request.ref), (c) => c.Open(request))),
|
|
280
|
+
frame: (request) => connectionCall(Effect.flatMap(client(request.ref), (c) => c.Frame(request))),
|
|
281
|
+
close: (request) => connectionCall(Effect.flatMap(client(request.ref), (c) => c.Close(request))),
|
|
282
|
+
resync: (request) => connectionCall(Effect.flatMap(client(request.ref), (c) => c.Resync(request))),
|
|
283
|
+
},
|
|
284
|
+
};
|
|
285
|
+
};
|
|
286
|
+
/**
|
|
287
|
+
* Whether the request is allowed: the global `authorize` and the
|
|
288
|
+
* actor's `access` both when both exist, either alone when only one
|
|
289
|
+
* does, and with neither, a `System` caller. A registration the runner
|
|
290
|
+
* does not hold has no `access`, so only the global hook or the default
|
|
291
|
+
* applies.
|
|
292
|
+
*/
|
|
293
|
+
const permitted = Effect.fnUntraced(function* (request) {
|
|
294
|
+
const access = (registrations.get(request.ref.actor) ?? queryRegistrations.get(request.ref.actor))?.access;
|
|
295
|
+
if (options.authorize === undefined && access === undefined)
|
|
296
|
+
return Schema.is(System)(request.caller);
|
|
297
|
+
if (options.authorize !== undefined && !(yield* options.authorize(request)))
|
|
298
|
+
return false;
|
|
299
|
+
if (access === undefined)
|
|
300
|
+
return true;
|
|
301
|
+
const allowed = access(request);
|
|
302
|
+
return Effect.isEffect(allowed) ? yield* allowed : allowed;
|
|
303
|
+
});
|
|
304
|
+
holder = yield* connectionHolder({
|
|
305
|
+
transport: () => transport,
|
|
306
|
+
actorType: (name) => heldTypes.get(name),
|
|
307
|
+
authorize: permitted,
|
|
308
|
+
});
|
|
309
|
+
const checked = new Set();
|
|
310
|
+
const authorizedAs = (request) => request.command !== INTERRUPT
|
|
311
|
+
? Effect.succeed(request)
|
|
312
|
+
: decodeTarget(request.payload).pipe(Effect.flatMap(({ executionId }) => decodeExecutionId(executionId)), Effect.map(({ workflow }) => ({ ...request, command: workflow })), Effect.orElseSucceed(() => request));
|
|
313
|
+
const allow = Effect.fnUntraced(function* (request, kind = "command") {
|
|
314
|
+
const { caller, ref, command } = yield* authorizedAs(request);
|
|
315
|
+
if (!(yield* permitted({ caller, ref, command, kind })))
|
|
316
|
+
return yield* ActorError.make({ reason: Unauthorized.make({ code: "access_denied" }) });
|
|
317
|
+
});
|
|
318
|
+
/**
|
|
319
|
+
* Rechecks access and expiry before an external caller gets its outcome.
|
|
320
|
+
* `endedAtMs` is the clock the turn read after its transaction ended;
|
|
321
|
+
* an outcome without one, a defect, reads the clock again. A reply may
|
|
322
|
+
* already have committed, so a full clock-read pool must wait, never
|
|
323
|
+
* report pre-turn refusal.
|
|
324
|
+
*/
|
|
325
|
+
const authorize = Effect.fnUntraced(function* (request, endedAtMs) {
|
|
326
|
+
yield* allow(request, "command");
|
|
327
|
+
yield* checkIdentity(request.commandId, retryWindowMs, endedAtMs === undefined
|
|
328
|
+
? yield* databaseTime.pipe(Effect.retry({
|
|
329
|
+
while: isPoolRefusal,
|
|
330
|
+
schedule: Schedule.spaced("10 millis"),
|
|
331
|
+
}))
|
|
332
|
+
: endedAtMs + frameworkClock.offsetMillis());
|
|
333
|
+
});
|
|
334
|
+
const refreshing = Semaphore.makeUnsafe(1);
|
|
335
|
+
const refreshPayloadWriters = Effect.gen(function* () {
|
|
336
|
+
if (writerDeclarations.length === 0)
|
|
337
|
+
return;
|
|
338
|
+
const sentAt = yield* Clock.currentTimeMillis;
|
|
339
|
+
yield* refreshWriters(runtimeId, writerWindowMs, writerDeclarations);
|
|
340
|
+
refreshedAt = sentAt;
|
|
341
|
+
}).pipe(refreshing.withPermits(1), Effect.provideContext(services), Effect.provideService(FrameworkClock, frameworkClock));
|
|
342
|
+
/**
|
|
343
|
+
* A runtime that could not refresh its writer rows within the window
|
|
344
|
+
* may already count as gone to `durable payloads clear`, so it starts
|
|
345
|
+
* no turn until a refresh succeeds. The check is local.
|
|
346
|
+
*/
|
|
347
|
+
const writable = Effect.gen(function* () {
|
|
348
|
+
if (refreshedAt === undefined)
|
|
349
|
+
return;
|
|
350
|
+
if ((yield* Clock.currentTimeMillis) - refreshedAt > writerWindowMs)
|
|
351
|
+
return yield* ActorError.make({
|
|
352
|
+
reason: ActorUnavailable.make({
|
|
353
|
+
cause: new Error("This runtime's payload writer rows are older than its window; turns wait for a refresh"),
|
|
354
|
+
}),
|
|
355
|
+
});
|
|
356
|
+
});
|
|
357
|
+
const entityId = (ref) => encodeEntityId([ref.tenant, ref.id]).pipe(Effect.orDie);
|
|
358
|
+
const databaseNow = databaseTime.pipe(Effect.provideContext(services), Effect.catchIf(SqlError.isSqlError, (cause) => Effect.fail(ActorError.make({ reason: ActorUnavailable.make({ cause }) }))));
|
|
359
|
+
const mintCommandId = Effect.gen(function* () {
|
|
360
|
+
const now = yield* databaseNow;
|
|
361
|
+
const uuid = yield* crypto.randomUUIDv4.pipe(Effect.orDie);
|
|
362
|
+
return `v1.${now}.${now + retryWindowMs}.${uuid}`;
|
|
363
|
+
});
|
|
364
|
+
const publicActors = Actors.of({ mintCommandId });
|
|
365
|
+
/**
|
|
366
|
+
* Logs what this runner knows of a delivery's target when the delivery
|
|
367
|
+
* waits out `deliveryTimeout`: the target activation's handlers, worker
|
|
368
|
+
* phase, mailbox and batch, the turn pool's leased and waiting sessions,
|
|
369
|
+
* and any other activation on the runner being rebuilt or restarted, so
|
|
370
|
+
* a stall names its cause from one log line.
|
|
371
|
+
*/
|
|
372
|
+
const deliveryTimedOut = (request, address) => Effect.gen(function* () {
|
|
373
|
+
const target = diagnostics.get(request.ref.actor);
|
|
374
|
+
const turns = Option.getOrUndefined(yield* Effect.serviceOption(TurnConnections));
|
|
375
|
+
yield* Effect.logWarning("Delivery timed out").pipe(Effect.annotateLogs({
|
|
376
|
+
actor: request.ref.actor,
|
|
377
|
+
id: request.ref.id,
|
|
378
|
+
tenant: request.ref.tenant,
|
|
379
|
+
command: request.command,
|
|
380
|
+
commandId: request.commandId,
|
|
381
|
+
activation: target?.diagnose(address),
|
|
382
|
+
turnSessions: turns?.sessions(),
|
|
383
|
+
restarting: [...diagnostics].flatMap(([actor, { restarting }]) => restarting()
|
|
384
|
+
.filter((entityId) => actor !== request.ref.actor || entityId !== address)
|
|
385
|
+
.map((entityId) => `${actor}:${entityId}`)),
|
|
386
|
+
}));
|
|
387
|
+
});
|
|
388
|
+
const makeCommandClient = (actor) => sharding.makeClient(commandEntity(actor));
|
|
389
|
+
const commandClients = new Map();
|
|
390
|
+
/** Cluster keeps one client per entity for the runtime's life, so its lookup is done once per actor type. */
|
|
391
|
+
const commandClient = (actor) => {
|
|
392
|
+
const cached = commandClients.get(actor);
|
|
393
|
+
if (cached !== undefined)
|
|
394
|
+
return Effect.succeed(cached);
|
|
395
|
+
return Effect.tap(makeCommandClient(actor), (make) => Effect.sync(() => {
|
|
396
|
+
commandClients.set(actor, make);
|
|
397
|
+
}));
|
|
398
|
+
};
|
|
399
|
+
const dispatch = Effect.fnUntraced(function* (request, external, pending) {
|
|
400
|
+
const registration = registrations.get(request.ref.actor);
|
|
401
|
+
if (registration === undefined)
|
|
402
|
+
return yield* ActorError.make({
|
|
403
|
+
reason: ActorUnavailable.make({ cause: new Error("Actor not registered") }),
|
|
404
|
+
});
|
|
405
|
+
if (external && !gate.open)
|
|
406
|
+
return yield* ActorError.make({
|
|
407
|
+
reason: ActorUnavailable.make({ cause: new Error("Runner is draining") }),
|
|
408
|
+
});
|
|
409
|
+
const address = yield* entityId(request.ref);
|
|
410
|
+
const isResident = () => residency.get(request.ref.actor)?.(address) === true;
|
|
411
|
+
let rejectedAtCapacity = false;
|
|
412
|
+
return yield* Effect.gen(function* () {
|
|
413
|
+
if (external &&
|
|
414
|
+
(request.intent !== undefined ||
|
|
415
|
+
request.delivery !== undefined ||
|
|
416
|
+
request.redelivered !== undefined ||
|
|
417
|
+
request.clockOffset !== undefined ||
|
|
418
|
+
(Schema.is(System)(request.caller) &&
|
|
419
|
+
(request.caller.mint !== undefined || request.caller.source === "subscription"))))
|
|
420
|
+
return yield* ActorError.make({
|
|
421
|
+
reason: Unauthorized.make({ code: "access_denied" }),
|
|
422
|
+
});
|
|
423
|
+
if (external) {
|
|
424
|
+
yield* allow(request, "command");
|
|
425
|
+
yield* checkIdentity(request.commandId, retryWindowMs);
|
|
426
|
+
}
|
|
427
|
+
const client = (yield* commandClient(request.ref.actor))(address);
|
|
428
|
+
yield* (yield* TurnHooks).at("beforeDelivery", request);
|
|
429
|
+
let admitted = false;
|
|
430
|
+
const deliver = Clock.currentTimeMillis.pipe(Effect.flatMap((queuedAtMs) => client
|
|
431
|
+
.Execute(!external
|
|
432
|
+
? { ...request, queuedAtMs }
|
|
433
|
+
: !admitted
|
|
434
|
+
? {
|
|
435
|
+
...request,
|
|
436
|
+
external,
|
|
437
|
+
clockOffset: frameworkClock.offsetMillis(),
|
|
438
|
+
queuedAtMs,
|
|
439
|
+
}
|
|
440
|
+
: {
|
|
441
|
+
...request,
|
|
442
|
+
external,
|
|
443
|
+
redelivered: true,
|
|
444
|
+
clockOffset: frameworkClock.offsetMillis(),
|
|
445
|
+
queuedAtMs,
|
|
446
|
+
})
|
|
447
|
+
.pipe(Effect.interruptible, Effect.forkIn(scope), Effect.tap((fiber) => Effect.sync(() => {
|
|
448
|
+
pending?.add(fiber);
|
|
449
|
+
})), Effect.uninterruptible)), Effect.flatMap(Fiber.join), Effect.catchCause((cause) => {
|
|
450
|
+
const failure = Cause.findErrorOption(cause);
|
|
451
|
+
if (Option.isSome(failure) && Schema.is(DeliveryFailed)(failure.value)) {
|
|
452
|
+
admitted ||= failure.value.admitted;
|
|
453
|
+
return Effect.fail(failure.value.error);
|
|
454
|
+
}
|
|
455
|
+
if (Option.isSome(failure) && Schema.is(ActorError)(failure.value))
|
|
456
|
+
return Effect.fail(failure.value);
|
|
457
|
+
if (Option.isSome(failure) && Schema.is(ClusterError.MailboxFull)(failure.value)) {
|
|
458
|
+
if (isResident())
|
|
459
|
+
return Effect.fail(registration.policy.mailboxCapacity === "unbounded"
|
|
460
|
+
? overloaded("activation")
|
|
461
|
+
: ActorError.make({ reason: MailboxFull.make({}) }));
|
|
462
|
+
rejectedAtCapacity = true;
|
|
463
|
+
return Effect.fail(ActorError.make({ reason: RunnerAtCapacity.make({}) }));
|
|
464
|
+
}
|
|
465
|
+
return Effect.fail(ActorError.make({
|
|
466
|
+
reason: ActorUnavailable.make({ cause: Cause.squash(cause) }),
|
|
467
|
+
}));
|
|
468
|
+
}));
|
|
469
|
+
const retrying = (attempt) => deliver.pipe(Effect.catchIf((error) => (Schema.is(ActorUnavailable)(error.reason) && !isOverloaded(error)) ||
|
|
470
|
+
Schema.is(RunnerAtCapacity)(error.reason), (error) => Effect.sleep(retryDelay(attempt)(error)).pipe(Effect.andThen(Effect.suspend(() => retrying(attempt + 1))))));
|
|
471
|
+
const executed = yield* retrying(0);
|
|
472
|
+
if (external)
|
|
473
|
+
yield* authorize(request, executed.endedAtMs);
|
|
474
|
+
return executed;
|
|
475
|
+
}).pipe(Effect.timeoutOrElse({
|
|
476
|
+
duration: registration.policy.deliveryMs,
|
|
477
|
+
orElse: () => rejectedAtCapacity && !isResident()
|
|
478
|
+
? Effect.fail(ActorError.make({ reason: RunnerAtCapacity.make({}) }))
|
|
479
|
+
: deliveryTimedOut(request, address).pipe(Effect.andThen(Effect.fail(ActorError.make({
|
|
480
|
+
reason: Timeout.make({ commandId: request.commandId }),
|
|
481
|
+
})))),
|
|
482
|
+
}));
|
|
483
|
+
}, Effect.provideContext(services), Effect.catchIf(SqlError.isSqlError, (cause) => Effect.fail(ActorError.make({ reason: ActorUnavailable.make({ cause }) }))), (effect, ...[request, external]) => effect.pipe(Effect.withSpan(SpanNames.admission, { attributes: { ...requestAttributes(request), "admission.external": external } }, { captureStackTrace: false })));
|
|
484
|
+
const leaseForTurns = () => {
|
|
485
|
+
let longest = 0;
|
|
486
|
+
for (const { policy } of registrations.values())
|
|
487
|
+
longest = Math.max(longest, policy.executionMs + policy.lockWaitMs);
|
|
488
|
+
return longest === 0 ? DEFAULT_CLAIM_LEASE_MS : longest + CLAIM_MARGIN_MS;
|
|
489
|
+
};
|
|
490
|
+
const progressTap = yield* ProgressTap;
|
|
491
|
+
const utf8Decoder = new TextDecoder();
|
|
492
|
+
const ownerOf = (ref) => Effect.gen(function* () {
|
|
493
|
+
const make = yield* sharding.makeClient(connectionEntity(ref.actor));
|
|
494
|
+
return make(yield* entityId(ref));
|
|
495
|
+
});
|
|
496
|
+
const fireAndForget = (send) => send.pipe(Effect.timeout(PROGRESS_SEND_TIMEOUT), Effect.ignoreCause, Effect.forkIn(scope));
|
|
497
|
+
const inflight = new Map();
|
|
498
|
+
const deliverProgress = (message) => Effect.flatMap(ownerOf(message.ref), (client) => client.Progress({ ...message, frame: utf8Decoder.decode(message.frame) }, { discard: true }));
|
|
499
|
+
const progressSink = ProgressSink.of({
|
|
500
|
+
wants: (actor, job) => jobRegistrations.get(actor)?.progress.has(job) === true,
|
|
501
|
+
send: (message) => Effect.flatMap(progressTap.send(message), (deliver) => deliver
|
|
502
|
+
? fireAndForget(deliverProgress(message)).pipe(Effect.flatMap((fiber) => Effect.sync(() => {
|
|
503
|
+
inflight.set(message.jobId, fiber);
|
|
504
|
+
fiber.addObserver(() => {
|
|
505
|
+
if (inflight.get(message.jobId) === fiber)
|
|
506
|
+
inflight.delete(message.jobId);
|
|
507
|
+
});
|
|
508
|
+
})))
|
|
509
|
+
: Effect.void),
|
|
510
|
+
closed: (message) => Effect.flatMap(progressTap.closed(message), (deliver) => deliver
|
|
511
|
+
? fireAndForget(Effect.suspend(() => {
|
|
512
|
+
const last = inflight.get(message.jobId);
|
|
513
|
+
return last === undefined ? Effect.void : Fiber.await(last);
|
|
514
|
+
}).pipe(Effect.andThen(ownerOf(message.ref)), Effect.flatMap((client) => client.ProgressClosed(message, { discard: true })))).pipe(Effect.asVoid)
|
|
515
|
+
: Effect.void),
|
|
516
|
+
});
|
|
517
|
+
const localSubscriptions = () => [...registrations.values()].flatMap((registration) => registration.subscriptions.map((subscription) => ({
|
|
518
|
+
subscriberType: registration.name,
|
|
519
|
+
subscription,
|
|
520
|
+
})));
|
|
521
|
+
const placements = new Map();
|
|
522
|
+
const placementOf = (actorType) => Effect.gen(function* () {
|
|
523
|
+
const known = registrations.get(actorType)?.placement ??
|
|
524
|
+
queryRegistrations.get(actorType)?.placement ??
|
|
525
|
+
placements.get(actorType);
|
|
526
|
+
if (known !== undefined)
|
|
527
|
+
return known;
|
|
528
|
+
const recorded = yield* recordedPlacement(actorType);
|
|
529
|
+
if (recorded !== undefined)
|
|
530
|
+
placements.set(actorType, recorded);
|
|
531
|
+
return recorded;
|
|
532
|
+
}).pipe(Effect.provideContext(services), Effect.orDie);
|
|
533
|
+
const relayDeliver = (request) => Effect.map(dispatch(request, false), (executed) => executed.outcome);
|
|
534
|
+
const subscriptions = yield* subscriptionRelay({
|
|
535
|
+
deliver: relayDeliver,
|
|
536
|
+
local: localSubscriptions,
|
|
537
|
+
placementOf,
|
|
538
|
+
wake: Effect.suspend(() => relay.wake),
|
|
539
|
+
settings: {
|
|
540
|
+
concurrency: subscriptionConcurrency,
|
|
541
|
+
batch: subscriptionBatch,
|
|
542
|
+
claimLeaseMs: () => claimLeaseMs ?? leaseForTurns(),
|
|
543
|
+
maxBackoffMs: relaySettings.maxBackoffMs,
|
|
544
|
+
retryWindowMs,
|
|
545
|
+
},
|
|
546
|
+
});
|
|
547
|
+
const relay = yield* outboxRelay(relayDeliver, () => [...jobRegistrations.values()].flatMap((registration) => [...registration.jobs].map(([job, registered]) => ({
|
|
548
|
+
actor: registration.name,
|
|
549
|
+
job,
|
|
550
|
+
registered: {
|
|
551
|
+
...registered,
|
|
552
|
+
execute: (payload, version, context) => registered
|
|
553
|
+
.execute(payload, version, context)
|
|
554
|
+
.pipe(withoutDatabase(registration.services)),
|
|
555
|
+
},
|
|
556
|
+
}))), { ...relaySettings, claimLeaseMs: () => claimLeaseMs ?? leaseForTurns() }, {
|
|
557
|
+
concurrency: subscriptionConcurrency,
|
|
558
|
+
claim: subscriptions.claim,
|
|
559
|
+
decode: subscriptions.decode,
|
|
560
|
+
run: (work, handoff) => subscriptions.run(work, handoff).pipe(Effect.provideContext(services)),
|
|
561
|
+
}, () => new Map(Array.from(registrations.values(), ({ name, cron, policy }) => [
|
|
562
|
+
name,
|
|
563
|
+
{ entries: cron, skipMs: policy.cronSkipMs },
|
|
564
|
+
]))).pipe(Effect.provideService(ProgressSink, progressSink));
|
|
565
|
+
yield* relay.run.pipe(Effect.forkIn(scope));
|
|
566
|
+
let fleetSubscribe;
|
|
567
|
+
if (options.fleet !== undefined && options.fleet.length > 0) {
|
|
568
|
+
if (Option.isSome(yield* Effect.serviceOption(PgliteClient.PgliteClient)))
|
|
569
|
+
return yield* Effect.die(new Error("Fleet.view needs Postgres with wal_level=logical; PGlite has no logical replication"));
|
|
570
|
+
const views = yield* checkFleet(options.fleet, options.rowLevelSecurity?.role).pipe(Effect.provideContext(services), Effect.orDie);
|
|
571
|
+
yield* maintain(views).pipe(Effect.provideContext(services), Effect.forkIn(scope));
|
|
572
|
+
fleetSubscribe = yield* fleetSubscriptions({
|
|
573
|
+
views,
|
|
574
|
+
role: options.rowLevelSecurity?.role,
|
|
575
|
+
permitted,
|
|
576
|
+
reauthorizeMs: (actorType) => registrations.get(actorType)?.policy.reauthorizeMs ?? DEFAULT_REAUTHORIZE_MS,
|
|
577
|
+
}).pipe(Effect.provideContext(services));
|
|
578
|
+
}
|
|
579
|
+
const { cleanup, sweeping, sample } = yield* startSweeps({
|
|
580
|
+
registrations,
|
|
581
|
+
sweepsWorkflows,
|
|
582
|
+
retryWindowMs,
|
|
583
|
+
subscriptions,
|
|
584
|
+
content,
|
|
585
|
+
services,
|
|
586
|
+
frameworkClock,
|
|
587
|
+
refreshPayloadWriters,
|
|
588
|
+
writerWindowMs,
|
|
589
|
+
runtimeId,
|
|
590
|
+
sampleEveryMs,
|
|
591
|
+
sharding,
|
|
592
|
+
scope,
|
|
593
|
+
});
|
|
594
|
+
const routed = (sourceType) => localSubscriptions().flatMap(({ subscriberType, subscription }) => subscription.routed !== undefined && subscription.sourceType === sourceType
|
|
595
|
+
? [{ ...subscription, subscriberType }]
|
|
596
|
+
: []);
|
|
597
|
+
const outbox = { retryWindowMs, wake: relay.wake, cancelled: relay.cancelled, routed };
|
|
598
|
+
const tenantScope = yield* TenantScope;
|
|
599
|
+
const operators = operatorRuntime({
|
|
600
|
+
services,
|
|
601
|
+
clock: frameworkClock,
|
|
602
|
+
outbox,
|
|
603
|
+
jobOf: (actorType, job) => jobRegistrations.get(actorType)?.jobs.get(job),
|
|
604
|
+
wake: relay.wake,
|
|
605
|
+
tenantScope,
|
|
606
|
+
});
|
|
607
|
+
const seeding = seedRuntime({
|
|
608
|
+
services,
|
|
609
|
+
clock: frameworkClock,
|
|
610
|
+
outbox,
|
|
611
|
+
jobOf: (actorType, job) => jobRegistrations.get(actorType)?.jobs.get(job),
|
|
612
|
+
createdBy: (actorType) => registrations.get(actorType)?.policy.createdBy !== undefined,
|
|
613
|
+
wake: relay.wake,
|
|
614
|
+
tenantScope,
|
|
615
|
+
});
|
|
616
|
+
const internalActors = InternalActors.of({
|
|
617
|
+
fleet: (request) => fleetSubscribe === undefined
|
|
618
|
+
? ActorError.make({ reason: InvalidInput.make({ code: "unknown_route" }) })
|
|
619
|
+
: fleetSubscribe(request),
|
|
620
|
+
fleetViews: new Set((options.fleet ?? []).map(({ name }) => name)),
|
|
621
|
+
seed: seeding,
|
|
622
|
+
mintActorId: crypto.randomUUIDv7.pipe(Effect.orDie),
|
|
623
|
+
mintChildId: (input) => deriveMintId(input).pipe(Effect.provideService(Crypto.Crypto, crypto)),
|
|
624
|
+
retryWindowMs,
|
|
625
|
+
databaseNow,
|
|
626
|
+
mintCommandId,
|
|
627
|
+
tables: (scope, write) => bindTables(database, scope, write, checked).pipe(Effect.provideService(SqlClient.SqlClient, primary), Effect.provideService(TenantScope, tenantScope)),
|
|
628
|
+
blobs: (scope, write) => bindBlobs(scope, write, contentBinding).pipe(Effect.provideService(SqlClient.SqlClient, primary), Effect.provideService(TenantScope, tenantScope)),
|
|
629
|
+
sweepContent: content === undefined
|
|
630
|
+
? Effect.succeed(0)
|
|
631
|
+
: content.sweep(true).pipe(Effect.provideContext(services), Effect.orDie),
|
|
632
|
+
registered: (actor) => ({
|
|
633
|
+
commands: registrations.has(actor),
|
|
634
|
+
queries: queryRegistrations.has(actor),
|
|
635
|
+
}),
|
|
636
|
+
declaredBlobs: (actor) => (registrations.get(actor) ?? queryRegistrations.get(actor))?.blobs.map((blob) => blob.name) ?? [],
|
|
637
|
+
...actorRegistration({
|
|
638
|
+
registrations,
|
|
639
|
+
queryRegistrations,
|
|
640
|
+
jobRegistrations,
|
|
641
|
+
residency,
|
|
642
|
+
diagnostics,
|
|
643
|
+
owners,
|
|
644
|
+
heldTypes,
|
|
645
|
+
heldType,
|
|
646
|
+
sweepsWorkflows,
|
|
647
|
+
checked,
|
|
648
|
+
services,
|
|
649
|
+
frameworkClock,
|
|
650
|
+
content,
|
|
651
|
+
retryWindowMs,
|
|
652
|
+
tableRole: options.rowLevelSecurity?.role,
|
|
653
|
+
adoptionRole: options.adoption?.role,
|
|
654
|
+
enforcedTypes,
|
|
655
|
+
writerDeclarations,
|
|
656
|
+
refreshPayloadWriters,
|
|
657
|
+
subscriptions,
|
|
658
|
+
transport,
|
|
659
|
+
authorize: permitted,
|
|
660
|
+
gate,
|
|
661
|
+
writable,
|
|
662
|
+
defectLog,
|
|
663
|
+
outbox,
|
|
664
|
+
}),
|
|
665
|
+
...committedReads({
|
|
666
|
+
registrations,
|
|
667
|
+
queryRegistrations,
|
|
668
|
+
services,
|
|
669
|
+
allow,
|
|
670
|
+
primary,
|
|
671
|
+
replica,
|
|
672
|
+
holder,
|
|
673
|
+
}),
|
|
674
|
+
...eventFeeds({
|
|
675
|
+
registrations,
|
|
676
|
+
services,
|
|
677
|
+
allow,
|
|
678
|
+
sharding,
|
|
679
|
+
entityId,
|
|
680
|
+
frameworkClock,
|
|
681
|
+
transport,
|
|
682
|
+
}),
|
|
683
|
+
deliverProgress: (message) => deliverProgress(message).pipe(Effect.ignoreCause, Effect.provideContext(services)),
|
|
684
|
+
transport,
|
|
685
|
+
holder,
|
|
686
|
+
hibernate: (ref) => Effect.flatMap(entityId(ref), (id) => owners.get(ref.actor)?.hibernate(id) ?? Effect.void).pipe(Effect.provideContext(services)),
|
|
687
|
+
execute: (request) => Effect.gen(function* () {
|
|
688
|
+
const reply = yield* Deferred.make();
|
|
689
|
+
const pending = new Set();
|
|
690
|
+
yield* admission
|
|
691
|
+
.admit(dispatch(request, true, pending).pipe(Effect.tap(observe), Effect.onExit((exit) => [...pending].some((fiber) => fiber.pollUnsafe() === undefined)
|
|
692
|
+
? Deferred.done(reply, exit)
|
|
693
|
+
: Effect.void), Effect.ensuring(Effect.suspend(() => Effect.forEach(pending, Fiber.await, { discard: true })))))
|
|
694
|
+
.pipe(Effect.onExit((exit) => Deferred.done(reply, exit)), Effect.ignoreCause, Effect.forkIn(scope));
|
|
695
|
+
return yield* Deferred.await(reply);
|
|
696
|
+
}),
|
|
697
|
+
overloaded: admission.full,
|
|
698
|
+
admitRequest: requests.admit,
|
|
699
|
+
deliver: (request) => dispatch(request, false).pipe(Effect.tap(observe), Effect.map((executed) => executed.outcome)),
|
|
700
|
+
observedVersion: () => observed,
|
|
701
|
+
drainOutbox: relay.drain,
|
|
702
|
+
cleanup: cleanup.pipe(Effect.orDie),
|
|
703
|
+
extendOutboxLeases: relay.extendLeases,
|
|
704
|
+
shardId: (ref) => entityId(ref).pipe(Effect.flatMap((id) => commandEntity(ref.actor).getShardId(EntityId.make(id))), Effect.map(String), Effect.provideService(Sharding.Sharding, sharding)),
|
|
705
|
+
});
|
|
706
|
+
const { serving } = yield* servingReadiness({
|
|
707
|
+
sharding,
|
|
708
|
+
services,
|
|
709
|
+
registrations,
|
|
710
|
+
queryRegistrations,
|
|
711
|
+
jobRegistrations,
|
|
712
|
+
});
|
|
713
|
+
const control = runtimeControl({
|
|
714
|
+
gate,
|
|
715
|
+
stopClaims: relay.stop,
|
|
716
|
+
attemptsIdle: relay.attemptsIdle,
|
|
717
|
+
interruptAttempts: relay.interruptAttempts,
|
|
718
|
+
stopBackground: sweeping === undefined ? Effect.void : Fiber.interrupt(sweeping),
|
|
719
|
+
serving,
|
|
720
|
+
scope,
|
|
721
|
+
});
|
|
722
|
+
const toUnavailable = (cause) => Effect.fail(ActorError.make({ reason: ActorUnavailable.make({ cause }) }));
|
|
723
|
+
const configured = Effect.suspend(() => content === undefined
|
|
724
|
+
? Effect.die(new Error("Content needs the runtime's content.keys"))
|
|
725
|
+
: Effect.succeed(content));
|
|
726
|
+
const contentEntry = Effect.fnUntraced(function* (ref, caller, blob, name, operation) {
|
|
727
|
+
const registration = registrations.get(ref.actor) ?? queryRegistrations.get(ref.actor);
|
|
728
|
+
if (registration === undefined)
|
|
729
|
+
return yield* ActorError.make({
|
|
730
|
+
reason: ActorUnavailable.make({ cause: new Error("Actor not registered") }),
|
|
731
|
+
});
|
|
732
|
+
if (!(yield* permitted({
|
|
733
|
+
caller,
|
|
734
|
+
ref,
|
|
735
|
+
command: `${blob}.${operation}`,
|
|
736
|
+
kind: "content",
|
|
737
|
+
})))
|
|
738
|
+
return yield* ActorError.make({ reason: Unauthorized.make({ code: "access_denied" }) });
|
|
739
|
+
if (!registration.blobs.some((declared) => declared.name === blob && isContent(declared)))
|
|
740
|
+
return Option.none();
|
|
741
|
+
const sql = yield* SqlClient.SqlClient;
|
|
742
|
+
const [found] = yield* sql `
|
|
743
|
+
SELECT hash, size::float8 AS size FROM actor_content_refs
|
|
744
|
+
WHERE routing_key = ${routingKey({ ref, placement: registration.placement })}
|
|
745
|
+
AND tenant_id = ${ref.tenant} AND actor_type = ${ref.actor} AND actor_id = ${ref.id}
|
|
746
|
+
AND blob = ${blob} AND name = ${name}`;
|
|
747
|
+
const timeoutMs = "policy" in registration ? registration.policy.executionMs : registration.timeoutMs;
|
|
748
|
+
return Option.map(Option.fromUndefinedOr(found), (row) => ({ ...row, timeoutMs }));
|
|
749
|
+
}, Effect.provideContext(services), Effect.catchTag("SqlError", toUnavailable));
|
|
750
|
+
const contentStore = ContentStore.of({
|
|
751
|
+
uploadBytes: (tenant, bytes) => Effect.flatMap(configured, (store) => store.uploadBytes(tenant, bytes)).pipe(Effect.provideContext(services), Effect.catchTag("SqlError", toUnavailable)),
|
|
752
|
+
upload: (tenant, body, limit) => Effect.flatMap(configured, (store) => store.uploadStream(tenant, body, Math.min(limit, MAX_CONTENT_BYTES))).pipe(Effect.provideContext(services), Effect.catchTag("SqlError", toUnavailable)),
|
|
753
|
+
grant: (ref, caller, blob, name) => Effect.gen(function* () {
|
|
754
|
+
const store = yield* configured;
|
|
755
|
+
const found = yield* contentEntry(ref, caller, blob, name, "grant");
|
|
756
|
+
if (Option.isNone(found))
|
|
757
|
+
return Option.none();
|
|
758
|
+
return yield* store
|
|
759
|
+
.grant(ref.tenant, found.value.hash, found.value.size)
|
|
760
|
+
.pipe(Effect.provideContext(services), Effect.catchTag("SqlError", toUnavailable));
|
|
761
|
+
}),
|
|
762
|
+
download: (ref, caller, blob, name) => Effect.gen(function* () {
|
|
763
|
+
const store = yield* configured;
|
|
764
|
+
const found = yield* contentEntry(ref, caller, blob, name, "get");
|
|
765
|
+
return Option.map(found, ({ hash, size, timeoutMs }) => ({
|
|
766
|
+
size,
|
|
767
|
+
bytes: store.stream(ref.tenant, hash, size, timeoutMs).pipe(Stream.provideContext(services), Stream.mapError((cause) => ActorError.make({ reason: ActorUnavailable.make({ cause }) }))),
|
|
768
|
+
}));
|
|
769
|
+
}),
|
|
770
|
+
});
|
|
771
|
+
return Context.make(Actors, publicActors).pipe(Context.add(ContentStore, contentStore), Context.add(InternalActors, internalActors), Context.add(RuntimeControl, control), Context.add(DefectLog, defectLog), Context.add(TelemetrySampler, TelemetrySampler.of({ sample })), Context.add(OperatorRuntime, operators));
|
|
772
|
+
}));
|
|
773
|
+
return Layer.unwrap(Effect.gen(function* () {
|
|
774
|
+
const sql = yield* SqlClient.SqlClient;
|
|
775
|
+
const coordination = (yield* Coordination) ?? sql;
|
|
776
|
+
const wiring = Option.getOrUndefined(yield* Effect.serviceOption(RunnerWiring));
|
|
777
|
+
yield* migrate;
|
|
778
|
+
if (options.rowLevelSecurity !== undefined &&
|
|
779
|
+
options.adoption !== undefined &&
|
|
780
|
+
options.rowLevelSecurity.role !== options.adoption.role)
|
|
781
|
+
return yield* Effect.die(new Error(`rowLevelSecurity.role ${options.rowLevelSecurity.role} and adoption.role ${options.adoption.role} must name the same role: a turn takes one role`));
|
|
782
|
+
if (options.rowLevelSecurity !== undefined)
|
|
783
|
+
yield* checkRowLevelSecurity(options.rowLevelSecurity.role);
|
|
784
|
+
yield* sql `INSERT INTO actor_deployment (protocol, retry_window_ms) VALUES (1, ${retryWindowMs}) ON CONFLICT DO NOTHING`;
|
|
785
|
+
const rows = yield* sql `SELECT protocol, retry_window_ms::text AS retry_window_ms FROM actor_deployment`;
|
|
786
|
+
if (rows[0].protocol !== 1 || Number(rows[0].retry_window_ms) !== retryWindowMs) {
|
|
787
|
+
return yield* Effect.die(new Error("Actor command protocol/retry window differs from the deployment; migrate explicitly"));
|
|
788
|
+
}
|
|
789
|
+
const runnerStorage = Option.isSome(yield* Effect.serviceOption(PgliteClient.PgliteClient))
|
|
790
|
+
? "memory"
|
|
791
|
+
: "sql";
|
|
792
|
+
if (wiring?.production === true && runnerStorage === "memory")
|
|
793
|
+
return yield* Effect.die(new Error("Runner.socket requires Postgres; PGlite cannot share ownership between processes"));
|
|
794
|
+
yield* checkRunnerConfiguration(wiring);
|
|
795
|
+
const sharding = (wiring?.sharding ?? Sharding.layer.pipe(Layer.provide(Runners.layerNoop))).pipe(Layer.merge(Layer.effect(RunnerReadiness, wiring?.production === true
|
|
796
|
+
? acquiredShards
|
|
797
|
+
: Effect.succeed({ acquired: () => Effect.succeed(true) }))), Layer.provideMerge(directMessages), Layer.provideMerge(mailboxRefusals), Layer.provide([
|
|
798
|
+
runnerStorage === "memory"
|
|
799
|
+
? Layer.effect(RunnerStorage.RunnerStorage, Effect.map(RunnerStorage.makeMemory, keepAcquiredShards))
|
|
800
|
+
: Layer.effect(RunnerStorage.RunnerStorage, coordinatedRunnerStorage.pipe(Effect.map(wiring?.storage ?? ((storage) => storage)), Effect.map(keepAcquiredShards))).pipe(Layer.orDie),
|
|
801
|
+
RunnerHealth.layerNoop,
|
|
802
|
+
]), Layer.provideMerge(ShardingConfig.layer({
|
|
803
|
+
shardsPerGroup: 1,
|
|
804
|
+
simulateRemoteSerialization: yield* LocalRequestSerialization,
|
|
805
|
+
maxResidentEntities: maxResidentActors,
|
|
806
|
+
...wiring?.config,
|
|
807
|
+
...holderShardGroups(wiring?.config ?? {}),
|
|
808
|
+
})));
|
|
809
|
+
const config = wiring?.config;
|
|
810
|
+
const address = config?.runnerAddress;
|
|
811
|
+
const lease = runnerStorage === "sql" &&
|
|
812
|
+
config?.shardLockDisableAdvisory === true &&
|
|
813
|
+
address !== undefined &&
|
|
814
|
+
Option.isSome(address)
|
|
815
|
+
? Layer.succeed(ShardLease, tableShardLease({
|
|
816
|
+
sql: coordination,
|
|
817
|
+
address: address.value,
|
|
818
|
+
expiration: Duration.fromInputUnsafe(config.shardLockExpiration ?? ShardingConfig.defaults.shardLockExpiration),
|
|
819
|
+
}))
|
|
820
|
+
: Layer.empty;
|
|
821
|
+
return runtime.pipe(Layer.provide(sharding), Layer.provide(lease), Layer.provide(Layer.succeed(TenantScope, {
|
|
822
|
+
role: options.rowLevelSecurity?.role,
|
|
823
|
+
adoption: options.adoption === undefined
|
|
824
|
+
? undefined
|
|
825
|
+
: { role: options.adoption.role, enforced: enforcedTypes },
|
|
826
|
+
})));
|
|
827
|
+
}));
|
|
828
|
+
};
|
|
829
|
+
/** Database layers for `Actors.layer`: `postgres` for real deployments, `pglite` for embedded and test use. */
|
|
830
|
+
export const Database = {
|
|
831
|
+
/**
|
|
832
|
+
* A runner holds three primary pools, plus optional replica and coordination
|
|
833
|
+
* pools. Turns lease sessions from the turn pool, `maxConnections` (default
|
|
834
|
+
* 50): a command holds one session until its transaction ends, so a pool
|
|
835
|
+
* smaller than the commands in flight queues callers behind
|
|
836
|
+
* it. Queries read from the query pool, `queryConnections` (default 10),
|
|
837
|
+
* except those of types with owned tables or blobs. Command admission,
|
|
838
|
+
* receipt replays, the relay, migrations, and cluster storage use the
|
|
839
|
+
* off-turn pool, `offTurnConnections` (default 10), unless `coordination`
|
|
840
|
+
* moves Cluster storage and deployment locks to an independent unsharded
|
|
841
|
+
* primary. All runners must designate the same authority. Every pool opens
|
|
842
|
+
* connections only as load needs them, refuses checkouts past its
|
|
843
|
+
* connections plus a bounded waiter allowance, and hands its connections out
|
|
844
|
+
* first come, first served. Keep the sum across runners below the server's
|
|
845
|
+
* `max_connections`.
|
|
846
|
+
*
|
|
847
|
+
* `replica` is this runner's nearest streaming replica of the same primary.
|
|
848
|
+
* Queries read there once it has replayed the commit version their caller
|
|
849
|
+
* last saw, and read the primary when it is behind or fails. Its pool
|
|
850
|
+
* (`maxConnections` default 10) opens connections only as queries need them.
|
|
851
|
+
* Every pool requests server TCP keepalives at 5 seconds idle, 2 seconds
|
|
852
|
+
* between probes, and 3 probes. `startupParameters` overrides these defaults
|
|
853
|
+
* independently on the primary and replica configurations.
|
|
854
|
+
*
|
|
855
|
+
* Registers a `regclass` codec because the pinned driver lacks one and the
|
|
856
|
+
* migrator needs it on restart; remove once Effect #8309 lands.
|
|
857
|
+
*/
|
|
858
|
+
postgres: (options) => {
|
|
859
|
+
const types = PgTypes.makeRegistry();
|
|
860
|
+
types.register(2205, {
|
|
861
|
+
encode: (value) => PgTypes.encode(value, PgTypes.OID.oid),
|
|
862
|
+
decode: (bytes) => bytes.length === 4
|
|
863
|
+
? Result.succeed(new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength).getUint32(0))
|
|
864
|
+
: Result.fail(new PgTypes.CodecError({ message: "Invalid regclass value" })),
|
|
865
|
+
});
|
|
866
|
+
const { offTurnConnections, queryConnections, replica, neki, coordination, ...configured } = options;
|
|
867
|
+
const pool = withKeepalives(configured);
|
|
868
|
+
const database = Layer.mergeAll(boundedLayer({ ...pool, maxConnections: offTurnConnections ?? 10, types }), neki === true
|
|
869
|
+
? turnConnections({ ...pool, maxConnections: pool.maxConnections ?? 50, types })
|
|
870
|
+
: turnGroups.pipe(Layer.provideMerge(turnConnections({ ...pool, maxConnections: pool.maxConnections ?? 50, types }))), queryPoolLayer({ ...pool, maxConnections: queryConnections ?? 10, types }), replicaLayer(replica === undefined ? undefined : { ...withKeepalives(replica), types }), coordinationLayer(coordination === undefined ? undefined : { ...withKeepalives(coordination), types }));
|
|
871
|
+
return neki === undefined
|
|
872
|
+
? database
|
|
873
|
+
: database.pipe(Layer.provideMerge(Layer.succeed(NekiTurnSessions, neki)));
|
|
874
|
+
},
|
|
875
|
+
pglite,
|
|
876
|
+
};
|