@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,22 @@
|
|
|
1
|
+
import { Effect, Layer } from "effect";
|
|
2
|
+
import { SqlClient } from "effect/sql";
|
|
3
|
+
import { Actors } from "../../index.ts";
|
|
4
|
+
import type { InternalActors } from "../../runtime/actors.ts";
|
|
5
|
+
import { ActorTest } from "../actor-test.ts";
|
|
6
|
+
import type { ConformanceCase, ConformanceSuite } from "../conformance.ts";
|
|
7
|
+
export declare const placementLayer: Layer.Layer<never, never, InternalActors | SqlClient.SqlClient>;
|
|
8
|
+
export interface PlacementWorkload {
|
|
9
|
+
readonly create: Effect.Effect<void, never, Actors | ActorTest>;
|
|
10
|
+
readonly wake: Effect.Effect<void, never, Actors | ActorTest>;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Two halves of one workload over the placement actors, for the single-shard
|
|
14
|
+
* statement check: `create` builds an order, a shipment, and a label; `wake`
|
|
15
|
+
* runs after a restart and touches every path a placed turn takes: a wake, a
|
|
16
|
+
* due-work delivery, both family group reads, a mint, and a report back.
|
|
17
|
+
*/
|
|
18
|
+
export declare const placementWorkload: PlacementWorkload;
|
|
19
|
+
/** Placement cases: rows of a family share their root's routing key, family reads use one snapshot, and a build that changes placement is refused. */
|
|
20
|
+
export declare const placementConformance: ReadonlyArray<ConformanceCase>;
|
|
21
|
+
/** Placement actors. */
|
|
22
|
+
export declare const placementSuite: ConformanceSuite;
|
|
@@ -0,0 +1,539 @@
|
|
|
1
|
+
import { pgTable, text } from "drizzle-orm/pg-core";
|
|
2
|
+
import { Cause, Effect, Exit, Layer, Option, Result, Schema } from "effect";
|
|
3
|
+
import { Headers, HttpRouter } from "effect/http";
|
|
4
|
+
import { SqlClient } from "effect/sql";
|
|
5
|
+
import { Actor, Actors, Intent, Unauthorized, User } from "../../index.js";
|
|
6
|
+
import { childId, parseChildId } from "../../identity/child.js";
|
|
7
|
+
import { deriveMintId } from "../../identity/mint.js";
|
|
8
|
+
import { routingKey } from "../../runtime/storage/codec.js";
|
|
9
|
+
import { ActorTest } from "../actor-test.js";
|
|
10
|
+
import { serve } from "../../serve/layer.js";
|
|
11
|
+
import { Auth } from "../../runtime/index.js";
|
|
12
|
+
import { retryPoolRefusal } from "../../runtime/database/bounded.js";
|
|
13
|
+
const orderRows = Actor.table(pgTable("placement_orders", { id: text("id").primaryKey() }));
|
|
14
|
+
const shipmentRows = Actor.table(pgTable("placement_shipments", {
|
|
15
|
+
id: text("id").primaryKey(),
|
|
16
|
+
carrier: text("carrier").notNull(),
|
|
17
|
+
}));
|
|
18
|
+
const placementDdl = [
|
|
19
|
+
`CREATE TABLE IF NOT EXISTS placement_orders (
|
|
20
|
+
routing_key bigint NOT NULL, tenant_id text NOT NULL, actor_id text NOT NULL, id text NOT NULL,
|
|
21
|
+
PRIMARY KEY (routing_key, tenant_id, actor_id, id))`,
|
|
22
|
+
`CREATE TABLE IF NOT EXISTS placement_shipments (
|
|
23
|
+
routing_key bigint NOT NULL, tenant_id text NOT NULL, actor_id text NOT NULL, id text NOT NULL,
|
|
24
|
+
carrier text NOT NULL, PRIMARY KEY (routing_key, tenant_id, actor_id, id))`,
|
|
25
|
+
...["placement_orders", "placement_shipments"].flatMap((table) => [
|
|
26
|
+
`ALTER TABLE ${table} ENABLE ROW LEVEL SECURITY`,
|
|
27
|
+
`DO $$ BEGIN
|
|
28
|
+
CREATE POLICY durable_tenant ON ${table} AS PERMISSIVE FOR ALL TO public
|
|
29
|
+
USING (tenant_id = current_setting('durable.tenant', true))
|
|
30
|
+
WITH CHECK (tenant_id = current_setting('durable.tenant', true));
|
|
31
|
+
EXCEPTION WHEN duplicate_object THEN NULL;
|
|
32
|
+
END $$`,
|
|
33
|
+
]),
|
|
34
|
+
];
|
|
35
|
+
const labels = Actor.blob("placementLabels");
|
|
36
|
+
const Shipped = Actor.event("PlacementShipped", { carrier: Schema.String });
|
|
37
|
+
const Family = Schema.Struct({
|
|
38
|
+
orders: Schema.Array(Schema.String),
|
|
39
|
+
shipments: Schema.Array(Schema.String),
|
|
40
|
+
});
|
|
41
|
+
const OrderKey = Schema.String.check(Schema.isPattern(/^o-/u));
|
|
42
|
+
const ShipmentKey = Schema.String.check(Schema.isPattern(/^s-/u));
|
|
43
|
+
const Place = Actor.command("Place");
|
|
44
|
+
const Ship = Actor.command("Ship", {
|
|
45
|
+
payload: Schema.Struct({
|
|
46
|
+
shipment: Schema.String,
|
|
47
|
+
carrier: Schema.String,
|
|
48
|
+
later: Schema.Boolean,
|
|
49
|
+
}),
|
|
50
|
+
success: Schema.String,
|
|
51
|
+
});
|
|
52
|
+
const MintParcel = Actor.command("MintParcel", { success: Schema.String });
|
|
53
|
+
const Acknowledge = Actor.command("Acknowledge", { payload: Schema.String });
|
|
54
|
+
const Acknowledged = Actor.query("Acknowledged", { success: Schema.Array(Schema.String) });
|
|
55
|
+
const OrderFamily = Actor.command("OrderFamily", { success: Family });
|
|
56
|
+
const Order = Actor.make("PlacementOrder", {
|
|
57
|
+
key: OrderKey,
|
|
58
|
+
placement: "actor",
|
|
59
|
+
state: Actor.state({
|
|
60
|
+
acknowledged: Schema.Array(Schema.String).pipe(Schema.withDecodingDefault(Effect.succeed([]))),
|
|
61
|
+
}),
|
|
62
|
+
tables: [orderRows],
|
|
63
|
+
api: { Place, Ship, MintParcel, Acknowledge, Acknowledged, OrderFamily },
|
|
64
|
+
});
|
|
65
|
+
const Open = Actor.command("Open", { payload: Schema.String });
|
|
66
|
+
const Report = Actor.command("Report", { payload: Schema.String });
|
|
67
|
+
const Carrier = Actor.query("Carrier", { success: Schema.String });
|
|
68
|
+
const ShipmentFamily = Actor.query("ShipmentFamily", { success: Family });
|
|
69
|
+
const Shipment = Actor.make("PlacementShipment", {
|
|
70
|
+
key: ShipmentKey,
|
|
71
|
+
placement: { parent: Order },
|
|
72
|
+
state: Actor.state({
|
|
73
|
+
carrier: Schema.String.pipe(Schema.withDecodingDefault(Effect.succeed(""))),
|
|
74
|
+
}),
|
|
75
|
+
events: [Shipped],
|
|
76
|
+
tables: [shipmentRows],
|
|
77
|
+
blobs: [labels],
|
|
78
|
+
api: { Open, Report, Carrier, ShipmentFamily },
|
|
79
|
+
});
|
|
80
|
+
const Print = Actor.command("Print");
|
|
81
|
+
/** Two levels below its root order: a shipment's label. */
|
|
82
|
+
const Label = Actor.make("PlacementLabel", {
|
|
83
|
+
key: Schema.NonEmptyString,
|
|
84
|
+
placement: { parent: Shipment },
|
|
85
|
+
state: Actor.state({
|
|
86
|
+
printed: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(false))),
|
|
87
|
+
}),
|
|
88
|
+
api: { Print },
|
|
89
|
+
});
|
|
90
|
+
const Title = Actor.query("Title", { success: Schema.String });
|
|
91
|
+
const MintStray = Actor.command("MintStray");
|
|
92
|
+
const Parcel = Actor.make("PlacementParcel", {
|
|
93
|
+
placement: { parent: Order },
|
|
94
|
+
state: Actor.state({ title: Schema.String.pipe(Schema.withDecodingDefault(Effect.succeed(""))) }),
|
|
95
|
+
api: { Open, Title, MintStray },
|
|
96
|
+
createdBy: Open,
|
|
97
|
+
});
|
|
98
|
+
const familyOf = Effect.fnUntraced(function* (group) {
|
|
99
|
+
const orders = yield* group((db) => db.select({ id: orderRows.id }).from(orderRows));
|
|
100
|
+
const shipments = yield* group((db) => db.select({ id: shipmentRows.id }).from(shipmentRows).orderBy(shipmentRows.id));
|
|
101
|
+
return { orders: orders.map(({ id }) => id), shipments: shipments.map(({ id }) => id) };
|
|
102
|
+
});
|
|
103
|
+
export const placementLayer = Layer.unwrap(Effect.gen(function* () {
|
|
104
|
+
const sql = yield* SqlClient.SqlClient;
|
|
105
|
+
for (const statement of placementDdl)
|
|
106
|
+
yield* retryPoolRefusal(sql.unsafe(statement)).pipe(Effect.orDie);
|
|
107
|
+
return Layer.mergeAll(Order.toLayer(Effect.succeed({
|
|
108
|
+
Place: Effect.fnUntraced(function* () {
|
|
109
|
+
const turn = yield* Order.Turn;
|
|
110
|
+
yield* turn.rows(orderRows).insert({ id: turn.id });
|
|
111
|
+
}),
|
|
112
|
+
Ship: Effect.fnUntraced(function* ({ shipment, carrier, later }) {
|
|
113
|
+
const turn = yield* Order.Turn;
|
|
114
|
+
const id = Shipment.idOf(turn.id, shipment);
|
|
115
|
+
const open = (yield* Shipment.intents(id)).Open(carrier);
|
|
116
|
+
yield* later ? open.pipe(Intent.after("1 hour")) : open;
|
|
117
|
+
return id;
|
|
118
|
+
}),
|
|
119
|
+
MintParcel: Effect.fnUntraced(function* () {
|
|
120
|
+
const id = yield* (yield* Order.Turn).mint(Parcel);
|
|
121
|
+
yield* (yield* Parcel.intents(id)).Open("parcel");
|
|
122
|
+
return id;
|
|
123
|
+
}),
|
|
124
|
+
Acknowledge: Effect.fnUntraced(function* (shipment) {
|
|
125
|
+
const turn = yield* Order.Turn;
|
|
126
|
+
yield* turn.state.set({ acknowledged: [...turn.state.acknowledged, shipment] });
|
|
127
|
+
}),
|
|
128
|
+
OrderFamily: Effect.fnUntraced(function* () {
|
|
129
|
+
return yield* familyOf((yield* Order.Turn).group);
|
|
130
|
+
}),
|
|
131
|
+
})), Order.toQueryLayer(Effect.succeed({
|
|
132
|
+
Acknowledged: Effect.fnUntraced(function* () {
|
|
133
|
+
return (yield* Order.Read).state.acknowledged;
|
|
134
|
+
}),
|
|
135
|
+
})), Shipment.toLayer(Effect.succeed({
|
|
136
|
+
Open: Effect.fnUntraced(function* (carrier) {
|
|
137
|
+
const turn = yield* Shipment.Turn;
|
|
138
|
+
yield* turn.state.set({ carrier });
|
|
139
|
+
yield* turn.rows(shipmentRows).insert({ id: turn.id, carrier });
|
|
140
|
+
yield* turn.emit(Shipped.make({ carrier }));
|
|
141
|
+
yield* turn.blob(labels).set("label", new TextEncoder().encode(carrier));
|
|
142
|
+
}),
|
|
143
|
+
Report: Effect.fnUntraced(function* (order) {
|
|
144
|
+
const turn = yield* Shipment.Turn;
|
|
145
|
+
yield* (yield* Order.intents(order)).Acknowledge(turn.id).pipe(Intent.after("1 hour"));
|
|
146
|
+
}),
|
|
147
|
+
})), Shipment.toQueryLayer(Effect.succeed({
|
|
148
|
+
Carrier: Effect.fnUntraced(function* () {
|
|
149
|
+
return (yield* Shipment.Read).state.carrier;
|
|
150
|
+
}),
|
|
151
|
+
ShipmentFamily: Effect.fnUntraced(function* () {
|
|
152
|
+
return yield* familyOf((yield* Shipment.Read).group);
|
|
153
|
+
}),
|
|
154
|
+
})), Label.toLayer(Effect.succeed({
|
|
155
|
+
Print: Effect.fnUntraced(function* () {
|
|
156
|
+
yield* (yield* Label.Turn).state.set({ printed: true });
|
|
157
|
+
}),
|
|
158
|
+
})), Parcel.toLayer(Effect.succeed({
|
|
159
|
+
Open: Effect.fnUntraced(function* (title) {
|
|
160
|
+
yield* (yield* Parcel.Turn).state.set({ title });
|
|
161
|
+
}),
|
|
162
|
+
MintStray: Effect.fnUntraced(function* () {
|
|
163
|
+
yield* (yield* Parcel.Turn).mint(Parcel);
|
|
164
|
+
}),
|
|
165
|
+
})), Parcel.toQueryLayer(Effect.succeed({
|
|
166
|
+
Title: Effect.fnUntraced(function* () {
|
|
167
|
+
return (yield* Parcel.Read).state.title;
|
|
168
|
+
}),
|
|
169
|
+
})));
|
|
170
|
+
}).pipe(Effect.orDie));
|
|
171
|
+
const shipment = (id) => Shipment.get(id);
|
|
172
|
+
const parcel = (id) => Parcel.get(id);
|
|
173
|
+
/** The message `make` throws, or "returned" when it does not throw. */
|
|
174
|
+
const thrown = (make) => Result.match(Result.try(() => make()), { onSuccess: () => "returned", onFailure: (error) => String(error) });
|
|
175
|
+
const defect = (exit) => Exit.isFailure(exit) ? Cause.pretty(exit.cause) : "succeeded";
|
|
176
|
+
/** The routing keys stored for `ids` of `tenant` in every framework table. */
|
|
177
|
+
const storedKeys = Effect.fnUntraced(function* (tenant, ids) {
|
|
178
|
+
const sql = yield* SqlClient.SqlClient;
|
|
179
|
+
const found = {};
|
|
180
|
+
for (const table of [
|
|
181
|
+
"actor_generations",
|
|
182
|
+
"actor_state",
|
|
183
|
+
"actor_receipts",
|
|
184
|
+
"actor_events",
|
|
185
|
+
"actor_outbox",
|
|
186
|
+
"actor_blobs",
|
|
187
|
+
"placement_shipments",
|
|
188
|
+
]) {
|
|
189
|
+
const rows = yield* sql `
|
|
190
|
+
SELECT DISTINCT routing_key::text AS key FROM ${sql(table)}
|
|
191
|
+
WHERE tenant_id = ${tenant} AND actor_id IN ${sql.in(ids)}`.pipe(Effect.orDie);
|
|
192
|
+
found[table] = rows.map(({ key }) => key);
|
|
193
|
+
}
|
|
194
|
+
return found;
|
|
195
|
+
});
|
|
196
|
+
const bearer = (request) => Option.match(Headers.get(request.headers, "authorization"), {
|
|
197
|
+
onNone: () => Effect.fail(Unauthorized.make({ code: "missing_credentials" })),
|
|
198
|
+
onSome: (header) => {
|
|
199
|
+
const [tenant, subject] = header.replace(/^Bearer /, "").split(":");
|
|
200
|
+
return Effect.succeed({ tenant: tenant, caller: User.make({ subject: subject }) });
|
|
201
|
+
},
|
|
202
|
+
});
|
|
203
|
+
const encodeJson = Schema.encodeEffect(Schema.fromJsonString(Schema.Json));
|
|
204
|
+
const decodeJson = Schema.decodeEffect(Schema.fromJsonString(Schema.Json));
|
|
205
|
+
const WireReason = Schema.Struct({
|
|
206
|
+
reason: Schema.Struct({ _tag: Schema.String, code: Schema.optionalKey(Schema.String) }),
|
|
207
|
+
});
|
|
208
|
+
/** The wire failure reason of a reply body, as `tag` and `code`. */
|
|
209
|
+
const reasonOf = (body) => Schema.decodeUnknownEffect(WireReason)(body).pipe(Effect.orDie, Effect.map(({ reason }) => ({ tag: reason._tag, code: reason.code })));
|
|
210
|
+
/** Serves the placement actors in memory and returns a request sender. */
|
|
211
|
+
const served = Effect.fnUntraced(function* (tenant) {
|
|
212
|
+
const context = yield* Effect.context();
|
|
213
|
+
const web = HttpRouter.toWebHandler(serve({ actors: [Order, Shipment, Parcel], auth: Auth.make(bearer) }).pipe(Layer.provide(Layer.succeedContext(context))), { disableLogger: true });
|
|
214
|
+
yield* Effect.addFinalizer(() => Effect.promise(() => web.dispose()));
|
|
215
|
+
const actors = yield* Actors;
|
|
216
|
+
return (path, body) => Effect.gen(function* () {
|
|
217
|
+
const key = yield* actors.mintCommandId;
|
|
218
|
+
const encoded = body === undefined ? null : yield* encodeJson(body);
|
|
219
|
+
const response = yield* Effect.promise(() => web.handler(new Request(`http://placement.test${path}`, {
|
|
220
|
+
method: "POST",
|
|
221
|
+
headers: {
|
|
222
|
+
authorization: `Bearer ${tenant}:alice`,
|
|
223
|
+
"idempotency-key": key,
|
|
224
|
+
"content-type": "application/json",
|
|
225
|
+
},
|
|
226
|
+
body: encoded,
|
|
227
|
+
})));
|
|
228
|
+
const text = yield* Effect.promise(() => response.text());
|
|
229
|
+
return { status: response.status, body: text === "" ? undefined : yield* decodeJson(text) };
|
|
230
|
+
}).pipe(Effect.orDie);
|
|
231
|
+
});
|
|
232
|
+
/**
|
|
233
|
+
* Two halves of one workload over the placement actors, for the single-shard
|
|
234
|
+
* statement check: `create` builds an order, a shipment, and a label; `wake`
|
|
235
|
+
* runs after a restart and touches every path a placed turn takes: a wake, a
|
|
236
|
+
* due-work delivery, both family group reads, a mint, and a report back.
|
|
237
|
+
*/
|
|
238
|
+
export const placementWorkload = {
|
|
239
|
+
create: Effect.gen(function* () {
|
|
240
|
+
const test = yield* ActorTest;
|
|
241
|
+
const order = yield* Order.get("o-shard-1");
|
|
242
|
+
yield* order.Place();
|
|
243
|
+
yield* order.Ship({ shipment: "s-1", carrier: "ups", later: false });
|
|
244
|
+
yield* test.advance(0);
|
|
245
|
+
yield* (yield* Label.get(Label.idOf(Shipment.idOf("o-shard-1", "s-1"), "l-1"))).Print();
|
|
246
|
+
}).pipe(Effect.orDie),
|
|
247
|
+
wake: Effect.gen(function* () {
|
|
248
|
+
const test = yield* ActorTest;
|
|
249
|
+
const order = yield* Order.get("o-shard-1");
|
|
250
|
+
const woken = yield* order.Ship({ shipment: "s-2", carrier: "dhl", later: false });
|
|
251
|
+
yield* test.advance(0);
|
|
252
|
+
const child = yield* shipment(woken);
|
|
253
|
+
yield* child.Report(order.ref.id);
|
|
254
|
+
yield* child.Carrier();
|
|
255
|
+
yield* child.ShipmentFamily();
|
|
256
|
+
yield* order.OrderFamily();
|
|
257
|
+
yield* (yield* Label.get(Label.idOf(Shipment.idOf("o-shard-1", "s-1"), "l-1"))).Print();
|
|
258
|
+
const fresh = yield* Order.get("o-shard-2");
|
|
259
|
+
yield* fresh.Place();
|
|
260
|
+
yield* fresh.MintParcel();
|
|
261
|
+
yield* test.advance("2 hours");
|
|
262
|
+
yield* order.Acknowledged();
|
|
263
|
+
}).pipe(Effect.orDie),
|
|
264
|
+
};
|
|
265
|
+
/** Placement cases: rows of a family share their root's routing key, family reads use one snapshot, and a build that changes placement is refused. */
|
|
266
|
+
export const placementConformance = [
|
|
267
|
+
{
|
|
268
|
+
name: "stores every framework and owned row of a child under its root's routing key",
|
|
269
|
+
run: ({ expect, environment }) => environment.run(Effect.gen(function* () {
|
|
270
|
+
const test = yield* ActorTest;
|
|
271
|
+
const order = yield* Order.get("o-stored");
|
|
272
|
+
yield* order.Place();
|
|
273
|
+
const id = yield* order.Ship({ shipment: "s-1", carrier: "ups", later: false });
|
|
274
|
+
yield* test.advance(0);
|
|
275
|
+
const child = yield* shipment(id);
|
|
276
|
+
yield* child.Report(order.ref.id);
|
|
277
|
+
const label = Label.idOf(Shipment.idOf("o-stored", "s-1"), "l-1");
|
|
278
|
+
yield* (yield* Label.get(label)).Print();
|
|
279
|
+
expect(id).toBe("c1.8.o-stored.s-1");
|
|
280
|
+
expect(label).toBe("c1.17.c1.8.o-stored.s-1.l-1");
|
|
281
|
+
expect(yield* child.Carrier()).toBe("ups");
|
|
282
|
+
const root = String(routingKey({ ref: order.ref, placement: "actor" }));
|
|
283
|
+
const found = yield* storedKeys(test.tenant, [order.ref.id, id, label]);
|
|
284
|
+
expect(found).toEqual({
|
|
285
|
+
actor_generations: [root],
|
|
286
|
+
actor_state: [root],
|
|
287
|
+
actor_receipts: [root],
|
|
288
|
+
actor_events: [root],
|
|
289
|
+
actor_outbox: [root],
|
|
290
|
+
actor_blobs: [root],
|
|
291
|
+
placement_shipments: [root],
|
|
292
|
+
});
|
|
293
|
+
const sql = yield* SqlClient.SqlClient;
|
|
294
|
+
const recorded = yield* sql `
|
|
295
|
+
SELECT actor_type, placement, parent_type AS parent FROM actor_placements
|
|
296
|
+
WHERE actor_type IN ('PlacementOrder', 'PlacementShipment', 'PlacementLabel')
|
|
297
|
+
ORDER BY actor_type`.pipe(Effect.orDie);
|
|
298
|
+
expect(recorded).toEqual([
|
|
299
|
+
{ actor_type: "PlacementLabel", placement: "parent", parent: "PlacementShipment" },
|
|
300
|
+
{ actor_type: "PlacementOrder", placement: "actor", parent: null },
|
|
301
|
+
{ actor_type: "PlacementShipment", placement: "parent", parent: "PlacementOrder" },
|
|
302
|
+
]);
|
|
303
|
+
})),
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
name: "reads a parent and its children in one group snapshot and nothing beyond the family",
|
|
307
|
+
run: ({ expect, environment }) => environment.run(Effect.gen(function* () {
|
|
308
|
+
const test = yield* ActorTest;
|
|
309
|
+
const first = yield* Order.get("o-family");
|
|
310
|
+
const second = yield* Order.get("o-other");
|
|
311
|
+
yield* first.Place();
|
|
312
|
+
yield* second.Place();
|
|
313
|
+
yield* first.Ship({ shipment: "s-1", carrier: "ups", later: false });
|
|
314
|
+
yield* first.Ship({ shipment: "s-2", carrier: "dhl", later: false });
|
|
315
|
+
yield* second.Ship({ shipment: "s-1", carrier: "fedex", later: false });
|
|
316
|
+
yield* test.advance(0);
|
|
317
|
+
const family = {
|
|
318
|
+
orders: ["o-family"],
|
|
319
|
+
shipments: ["c1.8.o-family.s-1", "c1.8.o-family.s-2"],
|
|
320
|
+
};
|
|
321
|
+
expect(yield* first.OrderFamily()).toEqual(family);
|
|
322
|
+
expect(yield* (yield* shipment("c1.8.o-family.s-2")).ShipmentFamily()).toEqual(family);
|
|
323
|
+
expect(yield* second.OrderFamily()).toEqual({
|
|
324
|
+
orders: ["o-other"],
|
|
325
|
+
shipments: ["c1.7.o-other.s-1"],
|
|
326
|
+
});
|
|
327
|
+
})),
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
name: "refuses a build that changes a type's placement, encoding, or parent type",
|
|
331
|
+
run: ({ expect, environment }) => environment.run(Effect.gen(function* () {
|
|
332
|
+
const sql = yield* SqlClient.SqlClient;
|
|
333
|
+
const Ping = Actor.command("Ping");
|
|
334
|
+
const deploy = (name, placement) => Layer.build(Actor.make(name, { key: Schema.NonEmptyString, placement, api: { Ping } }).toLayer(Effect.succeed({ Ping: () => Effect.void }))).pipe(Effect.scoped, Effect.exit);
|
|
335
|
+
const refused = "placement differs from the deployment; migrate explicitly";
|
|
336
|
+
expect(defect(yield* deploy("PlacementMoved", { parent: Order }))).toBe("succeeded");
|
|
337
|
+
expect(defect(yield* deploy("PlacementMoved", "actor"))).toContain(`Actor PlacementMoved ${refused}`);
|
|
338
|
+
const Other = Actor.make("PlacementOtherRoot", {
|
|
339
|
+
key: OrderKey,
|
|
340
|
+
placement: "actor",
|
|
341
|
+
api: { Ping },
|
|
342
|
+
});
|
|
343
|
+
const moved = yield* Layer.build(Actor.make("PlacementMoved", {
|
|
344
|
+
key: Schema.NonEmptyString,
|
|
345
|
+
placement: { parent: Other },
|
|
346
|
+
api: { Ping },
|
|
347
|
+
}).toLayer(Effect.succeed({ Ping: () => Effect.void }))).pipe(Effect.scoped, Effect.exit);
|
|
348
|
+
expect(defect(moved)).toContain(`Actor PlacementMoved ${refused}`);
|
|
349
|
+
yield* sql `UPDATE actor_placements SET encoding = 2
|
|
350
|
+
WHERE actor_type = 'PlacementMoved'`.pipe(Effect.orDie);
|
|
351
|
+
expect(defect(yield* deploy("PlacementMoved", { parent: Order }))).toContain(`Actor PlacementMoved ${refused}`);
|
|
352
|
+
yield* sql `UPDATE actor_placements SET encoding = 1
|
|
353
|
+
WHERE actor_type = 'PlacementMoved'`.pipe(Effect.orDie);
|
|
354
|
+
expect(defect(yield* deploy("PlacementMoved", { parent: Order }))).toBe("succeeded");
|
|
355
|
+
expect(defect(yield* deploy("PlacementRootMoved", "actor"))).toBe("succeeded");
|
|
356
|
+
const RootAsChild = Actor.make("PlacementRootMoved", {
|
|
357
|
+
key: Schema.NonEmptyString,
|
|
358
|
+
placement: { parent: Order },
|
|
359
|
+
api: { Ping },
|
|
360
|
+
});
|
|
361
|
+
const grandchild = yield* Layer.build(Actor.make("PlacementUnderMovedRoot", {
|
|
362
|
+
key: Schema.NonEmptyString,
|
|
363
|
+
placement: { parent: RootAsChild },
|
|
364
|
+
api: { Ping },
|
|
365
|
+
}).toLayer(Effect.succeed({ Ping: () => Effect.void }))).pipe(Effect.scoped, Effect.exit);
|
|
366
|
+
expect(defect(grandchild)).toContain(`Actor PlacementRootMoved ${refused}`);
|
|
367
|
+
})),
|
|
368
|
+
},
|
|
369
|
+
{
|
|
370
|
+
name: "rejects a tenant-placed parent and chains deeper than four levels at Actor.make",
|
|
371
|
+
run: ({ expect }) => Effect.runPromise(Effect.sync(() => {
|
|
372
|
+
const Ping = Actor.command("Ping");
|
|
373
|
+
const Tenanted = Actor.make("PlacementTenanted", {
|
|
374
|
+
key: Schema.NonEmptyString,
|
|
375
|
+
api: { Ping },
|
|
376
|
+
});
|
|
377
|
+
expect(thrown(() => Actor.make("PlacementOnTenant", {
|
|
378
|
+
key: Schema.NonEmptyString,
|
|
379
|
+
// @ts-expect-error a tenant-placed parent's children already share its shard
|
|
380
|
+
placement: { parent: Tenanted },
|
|
381
|
+
api: { Ping },
|
|
382
|
+
}))).toContain("PlacementOnTenant's parent PlacementTenanted is tenant-placed");
|
|
383
|
+
const second = Actor.make("PlacementDepth2", {
|
|
384
|
+
key: Schema.NonEmptyString,
|
|
385
|
+
placement: { parent: Shipment },
|
|
386
|
+
api: { Ping },
|
|
387
|
+
});
|
|
388
|
+
const third = Actor.make("PlacementDepth3", {
|
|
389
|
+
key: Schema.NonEmptyString,
|
|
390
|
+
placement: { parent: second },
|
|
391
|
+
api: { Ping },
|
|
392
|
+
});
|
|
393
|
+
const fourth = Actor.make("PlacementDepth4", {
|
|
394
|
+
key: Schema.NonEmptyString,
|
|
395
|
+
placement: { parent: third },
|
|
396
|
+
api: { Ping },
|
|
397
|
+
});
|
|
398
|
+
expect(thrown(() => Actor.make("PlacementDepth5", {
|
|
399
|
+
key: Schema.NonEmptyString,
|
|
400
|
+
placement: { parent: fourth },
|
|
401
|
+
api: { Ping },
|
|
402
|
+
}))).toContain("PlacementDepth5 would be 5 levels below its root; parent placement allows 4");
|
|
403
|
+
expect(thrown(() => Actor.make("PlacementUnkeyed", { placement: { parent: Order }, api: { Ping } }))).toContain("Parent-placed PlacementUnkeyed needs a key or createdBy");
|
|
404
|
+
expect(thrown(() => Actor.make("PlacementSingleton", {
|
|
405
|
+
key: Actor.singleton,
|
|
406
|
+
placement: { parent: Order },
|
|
407
|
+
api: { Ping },
|
|
408
|
+
}))).toContain("Singleton PlacementSingleton cannot be parent-placed");
|
|
409
|
+
expect(thrown(() => Actor.make("PlacementOnPlainObject", {
|
|
410
|
+
key: Schema.NonEmptyString,
|
|
411
|
+
placement: { parent: { name: "PlacementOrder" } },
|
|
412
|
+
api: { Ping },
|
|
413
|
+
}))).toContain("placement.parent takes an Actor.make definition");
|
|
414
|
+
})),
|
|
415
|
+
},
|
|
416
|
+
{
|
|
417
|
+
name: "mints a parent-placed child as c1 form whose createdBy proof verifies, and refuses X.create()",
|
|
418
|
+
run: ({ expect, environment }) => environment.run(Effect.gen(function* () {
|
|
419
|
+
const test = yield* ActorTest;
|
|
420
|
+
const order = yield* Order.get("o-mint");
|
|
421
|
+
const commandId = yield* (yield* Actors).mintCommandId;
|
|
422
|
+
const id = yield* order.MintParcel().pipe(Actor.commandId(commandId));
|
|
423
|
+
const local = yield* deriveMintId({
|
|
424
|
+
parent: order.ref,
|
|
425
|
+
commandId,
|
|
426
|
+
ordinal: 0,
|
|
427
|
+
child: "PlacementParcel",
|
|
428
|
+
});
|
|
429
|
+
expect(id).toBe(childId({ parent: "o-mint", local }));
|
|
430
|
+
yield* test.advance(0);
|
|
431
|
+
const child = yield* parcel(id);
|
|
432
|
+
expect(yield* child.Title()).toBe("parcel");
|
|
433
|
+
expect(yield* test.receiptsFor({ tenant: test.tenant, actor: "PlacementParcel", id }, "Open")).toBe(1);
|
|
434
|
+
expect(yield* test.inspect(order.ref)).toMatchObject({ outbox: 0 });
|
|
435
|
+
const unminted = childId({
|
|
436
|
+
parent: "o-mint",
|
|
437
|
+
local: yield* deriveMintId({
|
|
438
|
+
parent: order.ref,
|
|
439
|
+
commandId: "never-committed",
|
|
440
|
+
ordinal: 0,
|
|
441
|
+
child: "PlacementParcel",
|
|
442
|
+
}),
|
|
443
|
+
});
|
|
444
|
+
expect(yield* parcel(unminted).pipe(Effect.flatMap((forged) => forged.Open("forged")), Effect.flip)).toMatchObject({ reason: Unauthorized.make({ code: "access_denied" }) });
|
|
445
|
+
const create = Effect.suspend(() =>
|
|
446
|
+
// @ts-expect-error a parent-placed minted child is minted only by its parent
|
|
447
|
+
Parcel.create());
|
|
448
|
+
expect(defect(yield* Effect.exit(create))).toContain("PlacementParcel is minted only by its parent PlacementOrder");
|
|
449
|
+
expect(defect(yield* child.MintStray().pipe(Effect.exit))).toContain("turn.mint(PlacementParcel) needs a turn of its parent PlacementOrder");
|
|
450
|
+
})),
|
|
451
|
+
},
|
|
452
|
+
{
|
|
453
|
+
name: "rejects a malformed child id or a parent part the parent's key refuses as InvalidInput before any turn",
|
|
454
|
+
run: ({ expect, environment }) => environment.run(Effect.gen(function* () {
|
|
455
|
+
const test = yield* ActorTest;
|
|
456
|
+
const send = yield* served(test.tenant);
|
|
457
|
+
const malformed = [
|
|
458
|
+
"s-1",
|
|
459
|
+
"c1.4.o-17",
|
|
460
|
+
"c1.5.o-17.s-1",
|
|
461
|
+
"c1.4.x-17.s-1",
|
|
462
|
+
"c1.4.o-17.x-1",
|
|
463
|
+
"c1.4.o-17.",
|
|
464
|
+
];
|
|
465
|
+
for (const id of malformed) {
|
|
466
|
+
const reply = yield* send(`/actors/PlacementShipment/${encodeURIComponent(id)}/Open`, "ups");
|
|
467
|
+
expect(reply.status).toBe(400);
|
|
468
|
+
expect(yield* reasonOf(reply.body)).toEqual({ tag: "InvalidInput", code: "decode" });
|
|
469
|
+
expect(Exit.isFailure(yield* Effect.exit(shipment(id)))).toBe(true);
|
|
470
|
+
}
|
|
471
|
+
const unminted = yield* send(`/actors/PlacementParcel/${encodeURIComponent("c1.4.o-17.p-1")}/Title`);
|
|
472
|
+
expect(unminted.status).toBe(400);
|
|
473
|
+
expect(yield* reasonOf(unminted.body)).toEqual({ tag: "InvalidInput", code: "decode" });
|
|
474
|
+
const sql = yield* SqlClient.SqlClient;
|
|
475
|
+
const touched = yield* sql `
|
|
476
|
+
SELECT actor_id AS id FROM actor_generations
|
|
477
|
+
WHERE tenant_id = ${test.tenant} AND actor_id IN ${sql.in(malformed)}`.pipe(Effect.orDie);
|
|
478
|
+
expect(touched).toEqual([]);
|
|
479
|
+
})),
|
|
480
|
+
},
|
|
481
|
+
{
|
|
482
|
+
name: "delivers intents between a parent and its child as same-shard outbox rows",
|
|
483
|
+
run: ({ expect, environment }) => environment.run(Effect.gen(function* () {
|
|
484
|
+
const test = yield* ActorTest;
|
|
485
|
+
const sql = yield* SqlClient.SqlClient;
|
|
486
|
+
const order = yield* Order.get("o-intents");
|
|
487
|
+
const id = yield* order.Ship({ shipment: "s-1", carrier: "dhl", later: true });
|
|
488
|
+
const root = String(routingKey({ ref: order.ref, placement: "actor" }));
|
|
489
|
+
const rows = () => sql `
|
|
490
|
+
SELECT routing_key::text AS key, actor_id AS sender, target_id AS target
|
|
491
|
+
FROM actor_outbox WHERE tenant_id = ${test.tenant}
|
|
492
|
+
AND (actor_id = ${order.ref.id} OR actor_id = ${id})`.pipe(Effect.orDie);
|
|
493
|
+
expect(yield* rows()).toEqual([{ key: root, sender: "o-intents", target: id }]);
|
|
494
|
+
yield* test.advance("1 hour");
|
|
495
|
+
const child = yield* shipment(id);
|
|
496
|
+
expect(yield* child.Carrier()).toBe("dhl");
|
|
497
|
+
yield* child.Report(order.ref.id);
|
|
498
|
+
expect(yield* rows()).toEqual([{ key: root, sender: id, target: "o-intents" }]);
|
|
499
|
+
yield* test.advance("1 hour");
|
|
500
|
+
expect(yield* order.Acknowledged()).toEqual([id]);
|
|
501
|
+
expect(yield* rows()).toEqual([]);
|
|
502
|
+
expect(parseChildId(id)).toEqual({ parent: "o-intents", local: "s-1" });
|
|
503
|
+
})),
|
|
504
|
+
},
|
|
505
|
+
{
|
|
506
|
+
name: "serves and routes a child id through the HTTP protocol",
|
|
507
|
+
run: ({ expect, environment }) => environment.run(Effect.gen(function* () {
|
|
508
|
+
const test = yield* ActorTest;
|
|
509
|
+
const send = yield* served(test.tenant);
|
|
510
|
+
const id = Shipment.idOf("o-served", "s-1");
|
|
511
|
+
expect(yield* send(`/actors/PlacementShipment/${encodeURIComponent(id)}/Open`, "ups")).toMatchObject({ status: 204 });
|
|
512
|
+
expect(yield* send(`/actors/PlacementShipment/${encodeURIComponent(id)}/Carrier`)).toEqual({ status: 200, body: "ups" });
|
|
513
|
+
expect(yield* send(`/actors/PlacementShipment/${id}/Carrier`)).toEqual({
|
|
514
|
+
status: 200,
|
|
515
|
+
body: "ups",
|
|
516
|
+
});
|
|
517
|
+
const minted = yield* send("/actors/PlacementOrder/o-served/MintParcel");
|
|
518
|
+
expect(minted.status).toBe(200);
|
|
519
|
+
const parcelId = yield* Schema.decodeUnknownEffect(Schema.String)(minted.body).pipe(Effect.orDie);
|
|
520
|
+
yield* test.advance(0);
|
|
521
|
+
expect(yield* send(`/actors/PlacementParcel/${encodeURIComponent(parcelId)}/Title`)).toEqual({ status: 200, body: "parcel" });
|
|
522
|
+
expect(parseChildId(parcelId)?.parent).toBe("o-served");
|
|
523
|
+
const forged = childId({
|
|
524
|
+
parent: "o-served",
|
|
525
|
+
local: parseChildId(parcelId).local.replace(/^./, (c) => (c === "0" ? "1" : "0")),
|
|
526
|
+
});
|
|
527
|
+
const refused = yield* send(`/actors/PlacementParcel/${encodeURIComponent(forged)}/Open`, "forged");
|
|
528
|
+
expect(yield* reasonOf(refused.body)).toEqual({
|
|
529
|
+
tag: "Unauthorized",
|
|
530
|
+
code: "access_denied",
|
|
531
|
+
});
|
|
532
|
+
expect(yield* test.receiptsFor({ tenant: test.tenant, actor: "PlacementParcel", id: forged }, "Open")).toBe(0);
|
|
533
|
+
})),
|
|
534
|
+
},
|
|
535
|
+
];
|
|
536
|
+
/** Placement actors. */
|
|
537
|
+
export const placementSuite = {
|
|
538
|
+
layer: () => placementLayer,
|
|
539
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Effect, Layer, Stream, type Scope } from "effect";
|
|
2
|
+
import type { Crypto } from "effect";
|
|
3
|
+
import { HttpServer } from "effect/http";
|
|
4
|
+
/** Whether this process runs on Bun, whose native server and platform layers are faster than Node's. */
|
|
5
|
+
export declare const onBun: boolean;
|
|
6
|
+
/**
|
|
7
|
+
* The runtime's `Crypto` service. The platform package is imported when the
|
|
8
|
+
* layer builds, so a Node process never loads Bun's package and a Bun process
|
|
9
|
+
* never loads Node's.
|
|
10
|
+
*/
|
|
11
|
+
export declare const cryptoLayer: Layer.Layer<Crypto.Crypto>;
|
|
12
|
+
/** A listening `HttpServer` on a free loopback port, from the running platform's package. */
|
|
13
|
+
export declare const httpServerLayer: Layer.Layer<HttpServer.HttpServer>;
|
|
14
|
+
/**
|
|
15
|
+
* Serves a web `fetch` handler from a real listening loopback server until
|
|
16
|
+
* the scope closes, and answers its port. Bun serves it natively; Node serves
|
|
17
|
+
* it through Effect's `HttpServer`.
|
|
18
|
+
*/
|
|
19
|
+
export declare const serveFetch: (fetch: (request: Request) => Response | Promise<Response>) => Effect.Effect<number, never, Scope.Scope>;
|
|
20
|
+
/**
|
|
21
|
+
* A loopback TCP port that accepts connections and never answers, until the
|
|
22
|
+
* scope closes: a runner that is reachable but hung.
|
|
23
|
+
*/
|
|
24
|
+
export declare const silentListener: Effect.Effect<number, never, Scope.Scope>;
|
|
25
|
+
/** Decompresses a zstd frame: Bun's native decoder when it runs, Node's `zlib` otherwise. */
|
|
26
|
+
export declare const zstdDecompress: (bytes: Uint8Array) => Uint8Array;
|
|
27
|
+
/** How a process ended: its exit code, or the signal that killed it. */
|
|
28
|
+
export interface Exit {
|
|
29
|
+
readonly code: number | null;
|
|
30
|
+
readonly signal: string | null;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Runs a TypeScript fixture in its own process on the runtime that runs the
|
|
34
|
+
* suite: Bun runs the file as is and Node strips its types, so the sources it loads may use only erasable syntax. The scope
|
|
35
|
+
* SIGKILLs the process if it still runs.
|
|
36
|
+
*/
|
|
37
|
+
export declare const spawnFixture: (script: URL, env: Readonly<Record<string, string>>) => Effect.Effect<{
|
|
38
|
+
stdout: Stream.Stream<Uint8Array<ArrayBufferLike>, "unreadable", never>;
|
|
39
|
+
kill: Effect.Effect<Exit, never, never>;
|
|
40
|
+
}, never, Scope.Scope>;
|