@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,669 @@
|
|
|
1
|
+
import { Cause, Clock, Context, Deferred, Duration, Effect, Exit, Metric, Option, Result, Schedule, Schema, Scope, Stream, Tracer, } from "effect";
|
|
2
|
+
import { ClusterSchema, Entity, EntityId as ClusterEntityId, Sharding, ShardId, } from "effect/cluster";
|
|
3
|
+
import { Rpc } from "effect/rpc";
|
|
4
|
+
import { SqlClient, SqlError } from "effect/sql";
|
|
5
|
+
import { ActorError, ActorUnavailable } from "../../errors/actor.js";
|
|
6
|
+
import { DeliveryFailed, Executed, Outcome, Request } from "../request.js";
|
|
7
|
+
import {} from "../members.js";
|
|
8
|
+
import { ActorRef } from "../../identity/caller.js";
|
|
9
|
+
import { bootstrapTicks } from "../cron/schedule.js";
|
|
10
|
+
import { parentPlacement, routingKey } from "../storage/codec.js";
|
|
11
|
+
import { ShardLease } from "../topology/locks.js";
|
|
12
|
+
import { activationMailbox } from "./mailbox.js";
|
|
13
|
+
import { overloaded } from "../admission.js";
|
|
14
|
+
import { executeBatches } from "../turn/execute.js";
|
|
15
|
+
import { activationOwner } from "../connections/owner.js";
|
|
16
|
+
import { TenantScope } from "../database/tenancy.js";
|
|
17
|
+
import { transientSqlError } from "../database/transient.js";
|
|
18
|
+
import { FrameworkClock } from "../turn/admission.js";
|
|
19
|
+
import { connectionsEntity } from "../connections/protocol.js";
|
|
20
|
+
import { RetryTurn, TurnHooks } from "../turn/hooks.js";
|
|
21
|
+
import { OutboxRuntime } from "../turn/outbox.js";
|
|
22
|
+
import { DefectLog } from "../telemetry/defects.js";
|
|
23
|
+
import { accountsUsage, UsageAccounting } from "../telemetry/usage.js";
|
|
24
|
+
import { count, Metrics, record } from "../telemetry/metrics.js";
|
|
25
|
+
import { requestAttributes, SpanNames, triggerOf } from "../telemetry/spans.js";
|
|
26
|
+
import { activationEngine, kickedExecution, workflowCommands } from "../workflows/engine.js";
|
|
27
|
+
/**
|
|
28
|
+
* Commands are direct: the Cluster message is volatile and the receipt
|
|
29
|
+
* committed inside the turn is the only durable admission record.
|
|
30
|
+
* A lost runner loses only uncommitted work, which the caller retries by id.
|
|
31
|
+
* `Wake` builds the activation without running a turn.
|
|
32
|
+
*/
|
|
33
|
+
const makeCommandEntity = (name) => Entity.make(name, [
|
|
34
|
+
Rpc.make("Execute", {
|
|
35
|
+
payload: Request,
|
|
36
|
+
success: Executed,
|
|
37
|
+
error: Schema.Union([ActorError, DeliveryFailed]),
|
|
38
|
+
}),
|
|
39
|
+
Rpc.make("Wake"),
|
|
40
|
+
]).annotateRpcs(ClusterSchema.Uninterruptible, true);
|
|
41
|
+
/**
|
|
42
|
+
* Cluster entity ids name the tenant and actor id together.
|
|
43
|
+
*/
|
|
44
|
+
const EntityId = Schema.fromJsonString(Schema.Tuple([Schema.String, Schema.String]));
|
|
45
|
+
const encodeEntityIdOf = Schema.encodeEffect(EntityId);
|
|
46
|
+
/**
|
|
47
|
+
* A retryable turn failure, and a handler rebuilt after a death, wait
|
|
48
|
+
* `RESTART_BASE × 2^n`, capped at `RESTART_CAP`, where `n` counts the
|
|
49
|
+
* activation's failures and rebuilds since its last settled turn: prompt after
|
|
50
|
+
* a one-off failure, bounded for an actor whose turn fails on every attempt.
|
|
51
|
+
*/
|
|
52
|
+
const RESTART_BASE = Duration.millis(50);
|
|
53
|
+
const RESTART_CAP = Duration.seconds(5);
|
|
54
|
+
const restartDelay = (restarts) => Duration.min(Duration.times(RESTART_BASE, 2 ** restarts), RESTART_CAP);
|
|
55
|
+
/**
|
|
56
|
+
* The commands an activation holds, waiting and in its current batch, when its
|
|
57
|
+
* policy declares no `mailboxCapacity`. Cluster refuses the next, which
|
|
58
|
+
* dispatch answers `ActorUnavailable`: a hot actor's backlog then waits in its
|
|
59
|
+
* callers' retries, where it holds no memory or turn connection on this runner.
|
|
60
|
+
*/
|
|
61
|
+
export const ACTIVATION_MAILBOX = 1024;
|
|
62
|
+
/** The `outcome` attribute of `akter.turns` and of the turn span. */
|
|
63
|
+
const outcomeOf = (outcome, replayed = false) => replayed
|
|
64
|
+
? "replay"
|
|
65
|
+
: Outcome.match(outcome, {
|
|
66
|
+
Success: () => "success",
|
|
67
|
+
Failure: () => "failure",
|
|
68
|
+
Defect: () => "defect",
|
|
69
|
+
Acknowledged: () => "acknowledged",
|
|
70
|
+
});
|
|
71
|
+
/** Encodes a tenant and actor id as the Cluster entity id. */
|
|
72
|
+
export const encodeEntityId = (tenantAndId) => encodeEntityIdOf(tenantAndId);
|
|
73
|
+
const decodeEntityId = Schema.decodeEffect(EntityId);
|
|
74
|
+
/**
|
|
75
|
+
* How often a singleton's keeper re-wakes the default tenant's instance, and
|
|
76
|
+
* so bounds how long after its shard moves the instance is resident again.
|
|
77
|
+
*/
|
|
78
|
+
const SINGLETON_WAKE_INTERVAL = Duration.seconds(1);
|
|
79
|
+
/**
|
|
80
|
+
* Cluster's lifetime of one entity, shared by every handler a defect restart
|
|
81
|
+
* rebuilds within it.
|
|
82
|
+
*/
|
|
83
|
+
const entityScope = Effect.serviceOption(Context.Service("effect/cluster/internal/CurrentActivationScope")).pipe(Effect.flatMap(Option.match({
|
|
84
|
+
onNone: () => Effect.die(new Error("Cluster provided no entity scope")),
|
|
85
|
+
onSome: Effect.succeed,
|
|
86
|
+
})));
|
|
87
|
+
/**
|
|
88
|
+
* Runs a batch under its logs and span: a lone command's turn span, a child
|
|
89
|
+
* of its caller's span, or a batch span linked to every caller's span.
|
|
90
|
+
*/
|
|
91
|
+
const withinTurnSpan = (batch) => (effect) => {
|
|
92
|
+
const { request } = batch[0];
|
|
93
|
+
const { ref } = request;
|
|
94
|
+
const lone = batch.length === 1;
|
|
95
|
+
return effect.pipe(Effect.annotateLogs(lone
|
|
96
|
+
? {
|
|
97
|
+
actor: ref.actor,
|
|
98
|
+
id: ref.id,
|
|
99
|
+
tenant: ref.tenant,
|
|
100
|
+
command: request.command,
|
|
101
|
+
commandId: request.commandId,
|
|
102
|
+
}
|
|
103
|
+
: { actor: ref.actor, id: ref.id, tenant: ref.tenant }), Effect.withSpan(lone ? SpanNames.turn(ref.actor, request.command) : SpanNames.batch(ref.actor), {
|
|
104
|
+
kind: lone ? "server" : "internal",
|
|
105
|
+
attributes: lone
|
|
106
|
+
? requestAttributes(request)
|
|
107
|
+
: {
|
|
108
|
+
"actor.tenant": ref.tenant,
|
|
109
|
+
"actor.id": ref.id,
|
|
110
|
+
"batch.size": batch.length,
|
|
111
|
+
},
|
|
112
|
+
parent: lone ? Context.getOrUndefined(batch[0].context, Tracer.ParentSpan) : undefined,
|
|
113
|
+
links: lone
|
|
114
|
+
? []
|
|
115
|
+
: batch.flatMap(({ context }) => {
|
|
116
|
+
const span = Context.getOrUndefined(context, Tracer.ParentSpan);
|
|
117
|
+
return span === undefined ? [] : [{ span, attributes: {} }];
|
|
118
|
+
}),
|
|
119
|
+
}, { captureStackTrace: false }));
|
|
120
|
+
};
|
|
121
|
+
/**
|
|
122
|
+
* Defects that say nothing about the command: the activation restarts and
|
|
123
|
+
* the caller retries the same id.
|
|
124
|
+
*/
|
|
125
|
+
const retryable = (cause) => {
|
|
126
|
+
const defect = Cause.squash(cause);
|
|
127
|
+
return Schema.is(RetryTurn)(defect) || (SqlError.isSqlError(defect) && transientSqlError(defect));
|
|
128
|
+
};
|
|
129
|
+
/**
|
|
130
|
+
* One entity definition per actor type name, created on first use. Sharding
|
|
131
|
+
* keeps one RPC client per entity object, by identity, until the runtime
|
|
132
|
+
* closes; a fresh entity per call would retain a client per call.
|
|
133
|
+
*/
|
|
134
|
+
const oncePerName = (make) => {
|
|
135
|
+
const made = new Map();
|
|
136
|
+
return (name) => {
|
|
137
|
+
const cached = made.get(name);
|
|
138
|
+
if (cached !== undefined)
|
|
139
|
+
return cached;
|
|
140
|
+
const entity = make(name);
|
|
141
|
+
made.set(name, entity);
|
|
142
|
+
return entity;
|
|
143
|
+
};
|
|
144
|
+
};
|
|
145
|
+
/** The command entity definition for an actor type, created once per name. */
|
|
146
|
+
export const commandEntity = oncePerName(makeCommandEntity);
|
|
147
|
+
/** The connection entity definition for an actor type, created once per name. */
|
|
148
|
+
export const connectionEntity = oncePerName(connectionsEntity);
|
|
149
|
+
/**
|
|
150
|
+
* Writes a singleton's missing cron ticks, then keeps its default tenant's
|
|
151
|
+
* instance awake: one keeper re-wakes it every `SINGLETON_WAKE_INTERVAL`, or
|
|
152
|
+
* half the idle time if shorter, so it moves to a survivor with its shard.
|
|
153
|
+
*/
|
|
154
|
+
const keepSingletonAwake = Effect.fnUntraced(function* (registration, entity, services) {
|
|
155
|
+
const sharding = yield* Sharding.Sharding;
|
|
156
|
+
const ref = ActorRef.make({
|
|
157
|
+
tenant: registration.tenant,
|
|
158
|
+
actor: registration.name,
|
|
159
|
+
id: "singleton",
|
|
160
|
+
});
|
|
161
|
+
yield* bootstrapTicks(routingKey({ ref, placement: registration.placement }), ref, registration.cron).pipe(Effect.provideContext(services), Effect.orDie);
|
|
162
|
+
const address = yield* encodeEntityId([registration.tenant, "singleton"]).pipe(Effect.orDie);
|
|
163
|
+
const client = (yield* sharding.makeClient(entity))(address);
|
|
164
|
+
const wakeInterval = Duration.min(SINGLETON_WAKE_INTERVAL, Duration.millis(registration.policy.idleMs / 2));
|
|
165
|
+
yield* sharding.registerSingleton(registration.name, client.Wake().pipe(Effect.timeoutOrElse({ duration: wakeInterval, orElse: () => Effect.void }), Effect.catchCause((cause) => Effect.logDebug("Singleton wake failed", cause)), Effect.repeat(Schedule.spaced(wakeInterval))));
|
|
166
|
+
});
|
|
167
|
+
/**
|
|
168
|
+
* Registers an actor type's command entity with Cluster and starts its
|
|
169
|
+
* activations, worker, and singleton keeper.
|
|
170
|
+
*
|
|
171
|
+
* - One worker per handler runs queued commands as turn batches in delivery
|
|
172
|
+
* order, so an activation has one transaction in flight. Commands enqueue
|
|
173
|
+
* synchronously when Cluster delivers the request, and replies follow the
|
|
174
|
+
* batch's commit; broadcasts go out first. With `pipelining`, the next batch
|
|
175
|
+
* already waiting is taken while the previous one commits. Its admission
|
|
176
|
+
* waits until a batch with a workflow command is published, because that
|
|
177
|
+
* batch's kick can re-arm a running execution's timer under the generation
|
|
178
|
+
* row lock the admission would hold, and the next batch may be the very call
|
|
179
|
+
* that execution's activity is waiting on.
|
|
180
|
+
* - A retryable failure committed nothing. The worker ends the activation,
|
|
181
|
+
* waits its backoff, starts the next one in place, and only then answers each
|
|
182
|
+
* unanswered command `ActorUnavailable`, so a caller never retries into the
|
|
183
|
+
* closed activation and never waits out its delivery timeout when Cluster
|
|
184
|
+
* would drop a re-sent command mid-restart (as during a database failover).
|
|
185
|
+
* Restarts never overlap because the one worker serializes them.
|
|
186
|
+
* - A defect aborts the whole batch; a following batch whose admission was
|
|
187
|
+
* already sent is rolled back unseen. After a deterministic defect the
|
|
188
|
+
* failed batch's commands rerun one per transaction so one bad command cannot
|
|
189
|
+
* keep rolling back its neighbours, and a lone command answers `Defect`.
|
|
190
|
+
* Defect hooks do not run, since they can loop on corrupt state. A defect
|
|
191
|
+
* after the batch committed lets redelivered commands replay their receipts.
|
|
192
|
+
* - Restart backoff is kept per activation, because Cluster's own is shared by
|
|
193
|
+
* every entity of the type and never resets.
|
|
194
|
+
* - Each handler's resources live in a child of the entity's scope, closed when
|
|
195
|
+
* a rebuild supersedes it, the handler closes, or the entity ends, because a
|
|
196
|
+
* defect during shutdown can drop the superseded handler's own scope.
|
|
197
|
+
* - Full-mailbox and full-runner rejections share one Cluster error; only an
|
|
198
|
+
* activation already resident can have a full mailbox, and a rebuilt handler
|
|
199
|
+
* can overlap its predecessor, hence the count.
|
|
200
|
+
* - A singleton starts only on the runner holding its shard's lease. Every
|
|
201
|
+
* runner serves its entity, and one keeper re-wakes the default tenant's
|
|
202
|
+
* instance so it moves to a survivor. A failing singleton build answers every
|
|
203
|
+
* command with its defect instead of retrying forever.
|
|
204
|
+
* - A draining runner refuses a batch, or interrupts its run at the deadline,
|
|
205
|
+
* and every unanswered caller retries elsewhere.
|
|
206
|
+
* - The turn span carries no captured stack: its call site is always this file.
|
|
207
|
+
*/
|
|
208
|
+
export const registerActor = Effect.fnUntraced(function* (registration, transport, authorize, gate,
|
|
209
|
+
/** Fails while this runtime may not start turns, e.g. its payload writer rows are stale. */
|
|
210
|
+
writable) {
|
|
211
|
+
const sharding = yield* Sharding.Sharding;
|
|
212
|
+
const defects = yield* DefectLog;
|
|
213
|
+
const typeAttributes = { actor_type: registration.name };
|
|
214
|
+
const activations = Metric.withAttributes(Metrics.activations, typeAttributes);
|
|
215
|
+
const owner = activationOwner({
|
|
216
|
+
registration,
|
|
217
|
+
transport,
|
|
218
|
+
authorize,
|
|
219
|
+
clock: yield* FrameworkClock,
|
|
220
|
+
role: (yield* TenantScope).role,
|
|
221
|
+
});
|
|
222
|
+
const ownedOf = (entityId) => Effect.flatMap(Effect.orDie(decodeEntityId(entityId)), ([tenant, id]) => {
|
|
223
|
+
const ref = { actor: registration.name, tenant, id };
|
|
224
|
+
return owner.enter(entityId, ref, routingKey({ ref, placement: registration.placement }));
|
|
225
|
+
});
|
|
226
|
+
const services = yield* Effect.context();
|
|
227
|
+
const usage = Context.getUnsafe(services, UsageAccounting);
|
|
228
|
+
const accounting = accountsUsage(usage) ? usage : undefined;
|
|
229
|
+
const entity = commandEntity(registration.name);
|
|
230
|
+
const routingKeyOf = (ref) => routingKey({ ref, placement: registration.placement });
|
|
231
|
+
const workflowRoutes = workflowCommands({ registration, routingKeyOf, services });
|
|
232
|
+
const waited = new Set([...registration.workflows.values()].flatMap((workflow) => [...workflow.member.registry.steps.values()].flatMap((step) => step.event === undefined ? [] : [step.event])));
|
|
233
|
+
const resident = new Map();
|
|
234
|
+
const building = new Set();
|
|
235
|
+
const workers = new Map();
|
|
236
|
+
const lease = registration.singleton
|
|
237
|
+
? Option.getOrUndefined(yield* Effect.serviceOption(ShardLease))
|
|
238
|
+
: undefined;
|
|
239
|
+
/**
|
|
240
|
+
* Counts a handler of `entityId` as resident until its scope closes; a
|
|
241
|
+
* rebuilt handler can overlap its predecessor, hence the count.
|
|
242
|
+
*/
|
|
243
|
+
const residentWhile = (entityId) => Effect.acquireRelease(Effect.sync(() => resident.set(entityId, (resident.get(entityId) ?? 0) + 1)).pipe(Effect.andThen(count(Metrics.activationsStarted, typeAttributes, 1)), Effect.andThen(Metric.modify(activations, 1))), () => Effect.sync(() => {
|
|
244
|
+
const left = resident.get(entityId) - 1;
|
|
245
|
+
if (left === 0)
|
|
246
|
+
resident.delete(entityId);
|
|
247
|
+
else
|
|
248
|
+
resident.set(entityId, left);
|
|
249
|
+
}).pipe(Effect.andThen(Metric.modify(activations, -1))));
|
|
250
|
+
/**
|
|
251
|
+
* Runs a delivered command's `queued` hook under the runtime's services,
|
|
252
|
+
* captures the context its turn runs in, and waits for its reply. Defined
|
|
253
|
+
* once per actor type because a generator built for every delivery is
|
|
254
|
+
* compiled again and again as the engine sees new copies of it.
|
|
255
|
+
*/
|
|
256
|
+
const awaitReply = Effect.fnUntraced(function* (entry, mailbox) {
|
|
257
|
+
entry.context = yield* Effect.context();
|
|
258
|
+
yield* (yield* TurnHooks)
|
|
259
|
+
.at("queued", entry.request)
|
|
260
|
+
.pipe(Effect.ensuring(Effect.sync(() => mailbox.queued(entry))));
|
|
261
|
+
return yield* Deferred.await(entry.reply);
|
|
262
|
+
}, Effect.provideContext(services));
|
|
263
|
+
/** Counts what a committed batch wrote. */
|
|
264
|
+
const countWritten = Effect.fnUntraced(function* (done) {
|
|
265
|
+
yield* count(Metrics.receiptsReplayed, typeAttributes, done.replays.size);
|
|
266
|
+
yield* count(Metrics.receiptsWritten, typeAttributes, done.written.receipts);
|
|
267
|
+
yield* count(Metrics.eventsAppended, typeAttributes, done.written.events);
|
|
268
|
+
yield* count(Metrics.outboxStaged, { kind: "intent" }, done.written.intents);
|
|
269
|
+
yield* count(Metrics.outboxStaged, { kind: "job" }, done.written.jobs);
|
|
270
|
+
});
|
|
271
|
+
/**
|
|
272
|
+
* Records a deterministic defect in the defect log under its turn span's
|
|
273
|
+
* name and trace, and marks the span's outcome.
|
|
274
|
+
*/
|
|
275
|
+
const recordDefect = (request, cause) => Effect.gen(function* () {
|
|
276
|
+
const span = yield* Effect.currentSpan.pipe(Effect.option);
|
|
277
|
+
yield* defects.record({
|
|
278
|
+
span: SpanNames.turn(request.ref.actor, request.command),
|
|
279
|
+
traceId: Option.isSome(span) ? span.value.traceId : "",
|
|
280
|
+
spanId: Option.isSome(span) ? span.value.spanId : "",
|
|
281
|
+
atMs: yield* Clock.currentTimeMillis,
|
|
282
|
+
tenant: request.ref.tenant,
|
|
283
|
+
actorType: request.ref.actor,
|
|
284
|
+
actorId: request.ref.id,
|
|
285
|
+
command: request.command,
|
|
286
|
+
commandId: request.commandId,
|
|
287
|
+
trigger: triggerOf(request),
|
|
288
|
+
cause: Cause.pretty(Cause.die(Cause.squash(cause))),
|
|
289
|
+
});
|
|
290
|
+
yield* Effect.annotateCurrentSpan({ "turn.outcome": "defect" });
|
|
291
|
+
});
|
|
292
|
+
const leaseLostDefect = RetryTurn.make({
|
|
293
|
+
message: "Singleton runner no longer holds its shard lock",
|
|
294
|
+
});
|
|
295
|
+
const leaseLost = Effect.die(leaseLostDefect);
|
|
296
|
+
const restartIncomplete = RetryTurn.make({ message: "Activation restart did not complete" });
|
|
297
|
+
/**
|
|
298
|
+
* What each Cluster entity scope keeps across the handlers a defect restart
|
|
299
|
+
* rebuilds within it: rebuilds and in-place restarts since its last settled
|
|
300
|
+
* turn, absent until the first build so only a rebuild waits; the current
|
|
301
|
+
* handler's scope, closed when a rebuild supersedes it; and the ids of a
|
|
302
|
+
* batch a retryable failure aborted, each to run alone once.
|
|
303
|
+
*/
|
|
304
|
+
const memories = new WeakMap();
|
|
305
|
+
const register = sharding.registerEntity(entity, Effect.gen(function* () {
|
|
306
|
+
const activation = yield* entityScope;
|
|
307
|
+
const memory = memories.get(activation) ?? {
|
|
308
|
+
restarts: undefined,
|
|
309
|
+
handler: undefined,
|
|
310
|
+
alone: new Set(),
|
|
311
|
+
};
|
|
312
|
+
memories.set(activation, memory);
|
|
313
|
+
const rebuilt = memory.restarts;
|
|
314
|
+
memory.restarts = rebuilt === undefined ? 0 : rebuilt + 1;
|
|
315
|
+
const { entityId } = yield* Entity.CurrentAddress;
|
|
316
|
+
building.add(entityId);
|
|
317
|
+
yield* Effect.addFinalizer(() => Effect.sync(() => building.delete(entityId)));
|
|
318
|
+
if (rebuilt !== undefined)
|
|
319
|
+
yield* Effect.sleep(restartDelay(rebuilt));
|
|
320
|
+
const [tenant, id] = yield* decodeEntityId(entityId).pipe(Effect.orDie);
|
|
321
|
+
if (memory.handler !== undefined)
|
|
322
|
+
yield* Scope.close(memory.handler, Exit.void);
|
|
323
|
+
const shard = lease === undefined
|
|
324
|
+
? undefined
|
|
325
|
+
: ShardId.toString(yield* entity.getShardId(ClusterEntityId.make(entityId)));
|
|
326
|
+
if (lease !== undefined && !(yield* lease.holds(shard)))
|
|
327
|
+
return yield* leaseLost;
|
|
328
|
+
/**
|
|
329
|
+
* Why this handler refuses all work: its singleton lease is lost, or an
|
|
330
|
+
* in-place restart failed and the worker ended. Set once, never cleared;
|
|
331
|
+
* Cluster builds a new handler for the next delivery.
|
|
332
|
+
*/
|
|
333
|
+
let refused;
|
|
334
|
+
const handler = yield* Scope.fork(activation);
|
|
335
|
+
memory.handler = handler;
|
|
336
|
+
yield* residentWhile(entityId).pipe(Scope.provide(handler));
|
|
337
|
+
const start = Effect.gen(function* () {
|
|
338
|
+
const scope = yield* Scope.fork(handler);
|
|
339
|
+
if (lease !== undefined)
|
|
340
|
+
yield* lease.holds(shard).pipe(Effect.repeat({ schedule: Schedule.spaced(lease.interval), until: (held) => !held }), Effect.andThen(Effect.sync(() => {
|
|
341
|
+
refused = leaseLostDefect;
|
|
342
|
+
})), Effect.andThen(Effect.forkDetach(Scope.close(scope, Exit.void))), Effect.forkIn(scope));
|
|
343
|
+
const owned = yield* ownedOf(entityId).pipe(Scope.provide(scope));
|
|
344
|
+
const activated = yield* registration
|
|
345
|
+
.activate(ActorRef.make({ tenant, actor: registration.name, id }))
|
|
346
|
+
.pipe(Scope.provide(scope), Effect.exit);
|
|
347
|
+
if (Exit.isFailure(activated))
|
|
348
|
+
yield* Effect.logError("Actor activation failed", activated.cause).pipe(Effect.annotateLogs({ actor: registration.name, id, tenant }));
|
|
349
|
+
const started = { scope, owned, activated, engine: undefined };
|
|
350
|
+
return started;
|
|
351
|
+
});
|
|
352
|
+
const built = yield* Effect.context();
|
|
353
|
+
let current = yield* start;
|
|
354
|
+
yield* Effect.addFinalizer(() => Scope.close(handler, Exit.void));
|
|
355
|
+
const policy = registration.policy;
|
|
356
|
+
const statements = registration.tables.length > 0 || registration.blobs.length > 0;
|
|
357
|
+
const mailbox = activationMailbox(memory.alone);
|
|
358
|
+
let phase = "idle";
|
|
359
|
+
const restart = (batch, cause) => Effect.sync(() => {
|
|
360
|
+
refused ??= restartIncomplete;
|
|
361
|
+
}).pipe(Effect.andThen(Effect.forEach(batch, (entry) => entry.request.external !== true
|
|
362
|
+
? Deferred.failCause(entry.reply, Cause.die(Cause.squash(cause)))
|
|
363
|
+
: Deferred.fail(entry.reply, DeliveryFailed.make({
|
|
364
|
+
error: ActorError.make({
|
|
365
|
+
reason: ActorUnavailable.make({ cause: Cause.squash(cause) }),
|
|
366
|
+
}),
|
|
367
|
+
admitted: entry.admitted === true,
|
|
368
|
+
})), { discard: true })), Effect.andThen(Effect.interrupt));
|
|
369
|
+
const restartActivation = (batch, orphan, cause) => Effect.gen(function* () {
|
|
370
|
+
const failures = memory.restarts ?? 0;
|
|
371
|
+
phase = "restarting";
|
|
372
|
+
memory.restarts = failures + 1;
|
|
373
|
+
yield* Scope.close(current.scope, Exit.void);
|
|
374
|
+
yield* Effect.sleep(restartDelay(failures));
|
|
375
|
+
if (lease !== undefined && !(yield* lease.holds(shard))) {
|
|
376
|
+
refused = leaseLostDefect;
|
|
377
|
+
return yield* Effect.die(leaseLostDefect);
|
|
378
|
+
}
|
|
379
|
+
current = yield* start.pipe(Effect.provideContext(built));
|
|
380
|
+
mailbox.requeue(orphan);
|
|
381
|
+
const unavailable = ActorError.make({
|
|
382
|
+
reason: ActorUnavailable.make({ cause: Cause.squash(cause) }),
|
|
383
|
+
});
|
|
384
|
+
yield* Effect.forEach(batch, (entry) => entry.request.external !== true
|
|
385
|
+
? Deferred.fail(entry.reply, unavailable)
|
|
386
|
+
: Deferred.fail(entry.reply, DeliveryFailed.make({ error: unavailable, admitted: entry.admitted === true })), { discard: true });
|
|
387
|
+
}).pipe(Effect.uninterruptible, Effect.catchCause((failed) => restart([...batch, ...orphan], failed)));
|
|
388
|
+
const resolve = (batch) => {
|
|
389
|
+
const { activated } = current;
|
|
390
|
+
if (Exit.isSuccess(activated))
|
|
391
|
+
for (const entry of batch)
|
|
392
|
+
entry.command =
|
|
393
|
+
activated.value.get(entry.request.command) ??
|
|
394
|
+
workflowRoutes.get(entry.request.command) ??
|
|
395
|
+
entry.command;
|
|
396
|
+
return batch;
|
|
397
|
+
};
|
|
398
|
+
let taken = [];
|
|
399
|
+
const following = Effect.gen(function* () {
|
|
400
|
+
if (refused !== undefined ||
|
|
401
|
+
!gate.open ||
|
|
402
|
+
Exit.isFailure(current.activated) ||
|
|
403
|
+
Exit.isFailure(yield* Effect.exit(writable)))
|
|
404
|
+
return undefined;
|
|
405
|
+
const batch = resolve(mailbox.take());
|
|
406
|
+
taken.push(...batch);
|
|
407
|
+
return batch.length > 0 ? batch : undefined;
|
|
408
|
+
});
|
|
409
|
+
const labelled = new WeakMap();
|
|
410
|
+
/**
|
|
411
|
+
* The one owner of an ended batch's publication, in this order: wake the
|
|
412
|
+
* relay and running job attempts for obligations the commit made due or
|
|
413
|
+
* cancelled; record the batch's outcomes; end the transient progress of
|
|
414
|
+
* commands and jobs the batch settled; send its broadcasts, feed frames
|
|
415
|
+
* and watch updates to connections; then, per command in delivery order,
|
|
416
|
+
* run its `afterCommit` point, kick the workflow execution it started or
|
|
417
|
+
* resumed, and answer its caller. These steps follow the commit but are
|
|
418
|
+
* not atomic with it or with each other. A failure part-way stops the run
|
|
419
|
+
* as committed, so every command left unanswered is restarted and
|
|
420
|
+
* resolves through its receipt; a lost broadcast is not replayed.
|
|
421
|
+
*/
|
|
422
|
+
const publish = Effect.fnUntraced(function* (batch, done) {
|
|
423
|
+
const { owned } = current;
|
|
424
|
+
const outbox = yield* OutboxRuntime;
|
|
425
|
+
if (done.wake)
|
|
426
|
+
yield* outbox.wake;
|
|
427
|
+
if (done.cancelled)
|
|
428
|
+
yield* outbox.cancelled;
|
|
429
|
+
const labels = done.settled.map((settled, index) => Result.isSuccess(settled)
|
|
430
|
+
? outcomeOf(settled.success, done.replays.has(index))
|
|
431
|
+
: "rejected");
|
|
432
|
+
labelled.set(batch, labels);
|
|
433
|
+
yield* Effect.annotateCurrentSpan({ "actor.generation": done.generation });
|
|
434
|
+
if (batch.length === 1 && Result.isSuccess(done.settled[0]))
|
|
435
|
+
yield* Effect.annotateCurrentSpan({
|
|
436
|
+
"turn.replayed": done.replays.has(0),
|
|
437
|
+
"turn.outcome": labels[0],
|
|
438
|
+
});
|
|
439
|
+
yield* countWritten(done);
|
|
440
|
+
if (owner.hasProgress) {
|
|
441
|
+
for (const [index, settled] of done.settled.entries())
|
|
442
|
+
if (Result.isSuccess(settled) && !Outcome.guards.Defect(settled.success))
|
|
443
|
+
yield* owner.closeProgress(owned, batch[index].request.commandId);
|
|
444
|
+
for (const jobId of done.cancelledJobs)
|
|
445
|
+
yield* owner.closeProgress(owned, jobId);
|
|
446
|
+
}
|
|
447
|
+
if (owner.hasConnections || owner.hasStreams) {
|
|
448
|
+
for (const { request } of batch)
|
|
449
|
+
yield* (yield* TurnHooks).at("beforeFlush", request);
|
|
450
|
+
const feeds = yield* Effect.forEach(done.committed, owner.feedBroadcasts);
|
|
451
|
+
const watches = yield* owner.watchBroadcasts(owned, done.wrote, done.version);
|
|
452
|
+
yield* owner.flush(owned, [...done.broadcasts, ...feeds.flat(), ...watches], done.head);
|
|
453
|
+
}
|
|
454
|
+
for (const [index, settled] of done.settled.entries()) {
|
|
455
|
+
const entry = batch[index];
|
|
456
|
+
if (Result.isFailure(settled)) {
|
|
457
|
+
yield* Deferred.fail(entry.reply, settled.failure);
|
|
458
|
+
continue;
|
|
459
|
+
}
|
|
460
|
+
const outcome = settled.success;
|
|
461
|
+
memory.restarts = 0;
|
|
462
|
+
if (!Outcome.guards.Defect(outcome)) {
|
|
463
|
+
yield* (yield* TurnHooks).at("afterCommit", entry.request);
|
|
464
|
+
const kicked = workflowRoutes.has(entry.request.command)
|
|
465
|
+
? yield* kickedExecution({ request: entry.request, outcome })
|
|
466
|
+
: undefined;
|
|
467
|
+
if (kicked !== undefined) {
|
|
468
|
+
phase = "workflow kick";
|
|
469
|
+
current.engine ??= yield* activationEngine({
|
|
470
|
+
registration,
|
|
471
|
+
ref: entry.request.ref,
|
|
472
|
+
routingKey: routingKeyOf(entry.request.ref),
|
|
473
|
+
cache: current.owned.cache,
|
|
474
|
+
scope: current.scope,
|
|
475
|
+
deliveryMs: policy.deliveryMs,
|
|
476
|
+
});
|
|
477
|
+
yield* current.engine.kick(kicked.executionId, kicked.interrupt);
|
|
478
|
+
phase = "turn";
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
const executed = done.replays.has(index)
|
|
482
|
+
? { outcome, version: done.version, endedAtMs: done.endedAtMs, replayed: true }
|
|
483
|
+
: { outcome, version: done.version, endedAtMs: done.endedAtMs };
|
|
484
|
+
yield* Deferred.succeed(entry.reply, executed);
|
|
485
|
+
}
|
|
486
|
+
});
|
|
487
|
+
/** Records a finished batch's turn outcomes and duration, or the defect that ended it. */
|
|
488
|
+
const observed = Effect.fnUntraced(function* (batch, started, exit) {
|
|
489
|
+
const { request } = batch[0];
|
|
490
|
+
const lone = batch.length === 1;
|
|
491
|
+
const labels = labelled.get(batch);
|
|
492
|
+
const elapsed = (yield* Clock.currentTimeMillis) - started;
|
|
493
|
+
if (labels === undefined && Exit.isFailure(exit)) {
|
|
494
|
+
if (Cause.hasInterruptsOnly(exit.cause))
|
|
495
|
+
return;
|
|
496
|
+
if (!retryable(exit.cause) && !lone)
|
|
497
|
+
return;
|
|
498
|
+
const deterministic = !retryable(exit.cause);
|
|
499
|
+
if (deterministic)
|
|
500
|
+
yield* recordDefect(request, exit.cause);
|
|
501
|
+
yield* count(Metrics.turns, { ...typeAttributes, outcome: deterministic ? "defect" : "retried" }, batch.length);
|
|
502
|
+
yield* record(Metrics.turnDuration, typeAttributes, elapsed);
|
|
503
|
+
return;
|
|
504
|
+
}
|
|
505
|
+
for (const label of labels ?? [])
|
|
506
|
+
yield* count(Metrics.turns, { ...typeAttributes, outcome: label }, 1);
|
|
507
|
+
yield* record(Metrics.turnDuration, typeAttributes, elapsed);
|
|
508
|
+
});
|
|
509
|
+
const observe = (batch) => (effect) => Effect.flatMap(Clock.currentTimeMillis, (started) => Effect.forEach(batch, ({ request: queued }) => queued.queuedAtMs === undefined
|
|
510
|
+
? Effect.void
|
|
511
|
+
: record(Metrics.mailboxAge, typeAttributes, Math.max(0, started - queued.queuedAtMs)), { discard: true }).pipe(Effect.andThen(effect), Effect.onExit((exit) => observed(batch, started, exit)), withinTurnSpan(batch)));
|
|
512
|
+
const run = (batch, pipelining) => {
|
|
513
|
+
const { owned } = current;
|
|
514
|
+
return executeBatches({
|
|
515
|
+
first: batch,
|
|
516
|
+
next: pipelining ? following : Effect.undefined,
|
|
517
|
+
prepare: owner.prepare(owned),
|
|
518
|
+
committed: publish,
|
|
519
|
+
publishesUnderLock: (batch) => batch.some(({ request }) => workflowRoutes.has(request.command)),
|
|
520
|
+
observe,
|
|
521
|
+
}, owned.cache, owned.key, policy, registration.mintable, parentPlacement(registration.placement)?.parent, statements, waited, owner.hasConnections ? owner.list(owned) : undefined, registration.cron, accounting);
|
|
522
|
+
};
|
|
523
|
+
const recover = Effect.fnUntraced(function* ({ batch, orphan, cause, committed, poolRefused }) {
|
|
524
|
+
if (poolRefused === true) {
|
|
525
|
+
mailbox.requeue(orphan ?? []);
|
|
526
|
+
yield* Effect.forEach(batch, (entry) => Deferred.fail(entry.reply, overloaded("runner")), {
|
|
527
|
+
discard: true,
|
|
528
|
+
});
|
|
529
|
+
return;
|
|
530
|
+
}
|
|
531
|
+
if (committed || retryable(cause)) {
|
|
532
|
+
if (!committed && batch.length > 1)
|
|
533
|
+
mailbox.isolate(batch.map(({ request }) => request.commandId));
|
|
534
|
+
if (committed || refused !== undefined)
|
|
535
|
+
return yield* restart([...batch, ...(orphan ?? [])], cause);
|
|
536
|
+
return yield* restartActivation(batch, orphan ?? [], cause);
|
|
537
|
+
}
|
|
538
|
+
mailbox.requeue(orphan ?? []);
|
|
539
|
+
if (batch.length === 1) {
|
|
540
|
+
const { request } = batch[0];
|
|
541
|
+
const defect = Cause.squash(cause);
|
|
542
|
+
yield* Effect.logError("Deterministic actor defect", Cause.die(defect)).pipe(Effect.annotateLogs({
|
|
543
|
+
actor: request.ref.actor,
|
|
544
|
+
id: request.ref.id,
|
|
545
|
+
tenant: request.ref.tenant,
|
|
546
|
+
command: request.command,
|
|
547
|
+
commandId: request.commandId,
|
|
548
|
+
}));
|
|
549
|
+
memory.restarts = 0;
|
|
550
|
+
return yield* Deferred.succeed(batch[0].reply, {
|
|
551
|
+
outcome: Outcome.cases.Defect.make({ cause: defect }),
|
|
552
|
+
});
|
|
553
|
+
}
|
|
554
|
+
yield* Effect.logDebug("Turn batch failed; running its commands one at a time", cause);
|
|
555
|
+
for (const entry of batch) {
|
|
556
|
+
const stopped = yield* run(resolve([entry]), false);
|
|
557
|
+
if (stopped !== undefined)
|
|
558
|
+
yield* recover(stopped);
|
|
559
|
+
}
|
|
560
|
+
}, Effect.provideContext(services));
|
|
561
|
+
const turnBatch = Effect.fnUntraced(function* (batch) {
|
|
562
|
+
if (refused !== undefined)
|
|
563
|
+
return yield* restart(batch, Cause.die(refused));
|
|
564
|
+
yield* writable;
|
|
565
|
+
const stopped = yield* run(batch, true);
|
|
566
|
+
if (stopped !== undefined)
|
|
567
|
+
yield* recover(stopped);
|
|
568
|
+
});
|
|
569
|
+
yield* Effect.gen(function* () {
|
|
570
|
+
while (true) {
|
|
571
|
+
phase = "idle";
|
|
572
|
+
taken = [];
|
|
573
|
+
yield* mailbox.await;
|
|
574
|
+
const batch = resolve(mailbox.take());
|
|
575
|
+
if (batch.length === 0)
|
|
576
|
+
continue;
|
|
577
|
+
phase = "turn";
|
|
578
|
+
taken = [...batch];
|
|
579
|
+
if (Exit.isFailure(current.activated)) {
|
|
580
|
+
const { cause } = current.activated;
|
|
581
|
+
yield* Effect.forEach(batch, (entry) => Deferred.succeed(entry.reply, {
|
|
582
|
+
outcome: Outcome.cases.Defect.make({ cause: Cause.squash(cause) }),
|
|
583
|
+
}), { discard: true });
|
|
584
|
+
continue;
|
|
585
|
+
}
|
|
586
|
+
yield* gate.run(turnBatch(batch)).pipe(Effect.catchIf(Schema.is(ActorError), (error) => Effect.forEach(taken, (entry) => Deferred.fail(entry.reply, error), {
|
|
587
|
+
discard: true,
|
|
588
|
+
})), Effect.provideContext(batch[0].context), Effect.catchCauseIf((cause) => !Cause.hasInterruptsOnly(cause), (cause) => restart(batch, cause)));
|
|
589
|
+
}
|
|
590
|
+
}).pipe(Effect.provideContext(services), Effect.forkIn(handler));
|
|
591
|
+
const diagnose = () => ({ worker: phase, mailbox: mailbox.size(), batch: taken.length });
|
|
592
|
+
workers.set(entityId, diagnose);
|
|
593
|
+
building.delete(entityId);
|
|
594
|
+
yield* Effect.addFinalizer(() => Effect.sync(() => {
|
|
595
|
+
if (workers.get(entityId) === diagnose)
|
|
596
|
+
workers.delete(entityId);
|
|
597
|
+
}));
|
|
598
|
+
return entity.of({
|
|
599
|
+
Wake: () => Effect.suspend(() => (refused === undefined ? Effect.void : Effect.die(refused))),
|
|
600
|
+
Execute: ({ payload }) => {
|
|
601
|
+
if (refused !== undefined)
|
|
602
|
+
return Effect.die(refused);
|
|
603
|
+
const { activated } = current;
|
|
604
|
+
if (Exit.isFailure(activated))
|
|
605
|
+
return Effect.succeed({
|
|
606
|
+
outcome: Outcome.cases.Defect.make({ cause: Cause.squash(activated.cause) }),
|
|
607
|
+
});
|
|
608
|
+
const command = activated.value.get(payload.command) ?? workflowRoutes.get(payload.command);
|
|
609
|
+
if (command === undefined)
|
|
610
|
+
return Effect.die(new Error(`Unregistered command ${payload.command}`));
|
|
611
|
+
const entry = {
|
|
612
|
+
request: payload,
|
|
613
|
+
command,
|
|
614
|
+
reply: Deferred.makeUnsafe(),
|
|
615
|
+
context: Context.empty(),
|
|
616
|
+
queued: false,
|
|
617
|
+
};
|
|
618
|
+
mailbox.offer(entry);
|
|
619
|
+
return Rpc.fork(awaitReply(entry, mailbox));
|
|
620
|
+
},
|
|
621
|
+
});
|
|
622
|
+
}), {
|
|
623
|
+
concurrency: 1,
|
|
624
|
+
maxIdleTime: registration.policy.idleMs,
|
|
625
|
+
mailboxCapacity: registration.policy.mailboxCapacity === "unbounded"
|
|
626
|
+
? ACTIVATION_MAILBOX
|
|
627
|
+
: registration.policy.mailboxCapacity,
|
|
628
|
+
defectRetryPolicy: Schedule.forever,
|
|
629
|
+
});
|
|
630
|
+
const connections = connectionEntity(registration.name);
|
|
631
|
+
const connectionServices = yield* Effect.context();
|
|
632
|
+
yield* register;
|
|
633
|
+
if (owner.hasConnections || owner.hasStreams)
|
|
634
|
+
yield* sharding.registerEntity(connections, Effect.gen(function* () {
|
|
635
|
+
const { entityId } = yield* Entity.CurrentAddress;
|
|
636
|
+
const owned = yield* ownedOf(entityId);
|
|
637
|
+
yield* Effect.addFinalizer(() => owner.endStreams(owned));
|
|
638
|
+
return connections.of({
|
|
639
|
+
Progress: ({ payload }) => owner.progress(owned, payload).pipe(Effect.provideContext(connectionServices)),
|
|
640
|
+
ProgressClosed: ({ payload }) => owner.progressClosed(owned, payload).pipe(Effect.provideContext(connectionServices)),
|
|
641
|
+
Subscribe: ({ payload }) => owner.subscribe(owned, payload).pipe(Stream.provideContext(connectionServices)),
|
|
642
|
+
Open: ({ payload }) => owner.open(owned, payload).pipe(Effect.provideContext(connectionServices)),
|
|
643
|
+
Frame: ({ payload }) => owner.frame(owned, payload).pipe(Effect.provideContext(connectionServices)),
|
|
644
|
+
Close: ({ payload }) => owner.close(owned, payload).pipe(Effect.provideContext(connectionServices)),
|
|
645
|
+
Resync: ({ payload }) => owner.resync(owned, payload).pipe(Effect.provideContext(connectionServices)),
|
|
646
|
+
});
|
|
647
|
+
}), { concurrency: "unbounded", maxIdleTime: registration.policy.idleMs });
|
|
648
|
+
if (owner.hasStreams)
|
|
649
|
+
yield* owner.watchStreams.pipe(Effect.forkScoped);
|
|
650
|
+
if (registration.singleton)
|
|
651
|
+
yield* keepSingletonAwake(registration, entity, services);
|
|
652
|
+
return {
|
|
653
|
+
isResident: (entityId) => resident.has(entityId),
|
|
654
|
+
owner,
|
|
655
|
+
/** This type's view of one activation, for a delivery that timed out. */
|
|
656
|
+
diagnose: (entityId) => ({
|
|
657
|
+
handlers: resident.get(entityId) ?? 0,
|
|
658
|
+
building: building.has(entityId),
|
|
659
|
+
...(workers.get(entityId)?.() ?? { worker: "none", mailbox: 0, batch: 0 }),
|
|
660
|
+
}),
|
|
661
|
+
/** Activations of this type being rebuilt or restarted in place now. */
|
|
662
|
+
restarting: () => [
|
|
663
|
+
...new Set([
|
|
664
|
+
...building,
|
|
665
|
+
...[...workers].flatMap(([entityId, diagnose]) => diagnose().worker === "restarting" ? [entityId] : []),
|
|
666
|
+
]),
|
|
667
|
+
],
|
|
668
|
+
};
|
|
669
|
+
});
|