@rikalabs/akter 0.1.0-alpha.0 → 0.1.0-alpha.3
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 +46 -3
- package/README.md +2 -2
- package/dist/actor/definition.d.ts +13 -9
- package/dist/actor/descriptor.d.ts +2 -2
- package/dist/actor/descriptor.js +4 -4
- package/dist/client/calls.js +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.js +1 -1
- package/dist/errors/actor.d.ts +12 -42
- package/dist/errors/actor.js +13 -42
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/members/payload.d.ts +1 -1
- package/dist/protocol/inspection.d.ts +221 -1
- package/dist/protocol/inspection.js +151 -2
- package/dist/protocol/wire.d.ts +6 -49
- package/dist/protocol/wire.js +1 -10
- package/dist/runtime/actors.d.ts +3 -0
- package/dist/runtime/adoption/backfill.js +1 -1
- package/dist/runtime/adoption/enforce.js +2 -2
- package/dist/runtime/adoption/observe.js +1 -1
- package/dist/runtime/adoption/plan.d.ts +1 -1
- package/dist/runtime/adoption/startup.js +1 -1
- package/dist/runtime/adoption/status.d.ts +1 -1
- package/dist/runtime/app.d.ts +65 -0
- package/dist/runtime/app.js +38 -0
- package/dist/runtime/connections/holder.d.ts +11 -1
- package/dist/runtime/connections/holder.js +8 -4
- package/dist/runtime/connections/streams.d.ts +4 -4
- package/dist/runtime/content/store.js +15 -11
- package/dist/runtime/database/bounded.d.ts +4 -18
- package/dist/runtime/database/bounded.js +36 -22
- package/dist/runtime/database/coordination.d.ts +12 -3
- package/dist/runtime/database/coordination.js +29 -36
- package/dist/runtime/database/migrations.d.ts +61 -29
- package/dist/runtime/database/migrations.js +375 -139
- package/dist/runtime/database/replica.d.ts +4 -1
- package/dist/runtime/database/replica.js +4 -1
- package/dist/runtime/database/schema.d.ts +13 -0
- package/dist/runtime/database/schema.js +13 -0
- package/dist/runtime/database/shards.d.ts +31 -13
- package/dist/runtime/database/shards.js +38 -26
- package/dist/runtime/entity/register.d.ts +8 -1
- package/dist/runtime/entity/register.js +58 -7
- package/dist/runtime/fleet/checks.js +4 -4
- package/dist/runtime/fleet/maintainer.d.ts +1 -1
- package/dist/runtime/fleet/maintainer.js +1 -1
- package/dist/runtime/index.d.ts +2 -0
- package/dist/runtime/index.js +1 -0
- package/dist/runtime/inspector/layer.d.ts +20 -0
- package/dist/runtime/inspector/layer.js +224 -5
- package/dist/runtime/inspector/queries.d.ts +54 -8
- package/dist/runtime/inspector/queries.js +84 -15
- package/dist/runtime/layer.d.ts +48 -39
- package/dist/runtime/layer.js +124 -56
- package/dist/runtime/operators/audit.d.ts +3 -0
- package/dist/runtime/operators/audit.js +6 -2
- package/dist/runtime/operators/repair.js +30 -10
- package/dist/runtime/operators/seed.js +4 -2
- package/dist/runtime/payloads/versions.d.ts +4 -4
- package/dist/runtime/payloads/versions.js +24 -15
- package/dist/runtime/queries.js +4 -2
- package/dist/runtime/registration.d.ts +5 -2
- package/dist/runtime/registration.js +3 -3
- package/dist/runtime/runner.d.ts +12 -0
- package/dist/runtime/runner.js +12 -0
- package/dist/runtime/storage/codec.d.ts +19 -7
- package/dist/runtime/storage/codec.js +23 -7
- package/dist/runtime/storage/placements.d.ts +6 -1
- package/dist/runtime/storage/placements.js +98 -6
- package/dist/runtime/storage/retention.d.ts +6 -0
- package/dist/runtime/storage/retention.js +25 -13
- package/dist/runtime/subscriptions/relay.js +47 -44
- package/dist/runtime/subscriptions/storage.d.ts +3 -2
- package/dist/runtime/subscriptions/storage.js +9 -6
- package/dist/runtime/telemetry/live.d.ts +255 -0
- package/dist/runtime/telemetry/live.js +540 -0
- package/dist/runtime/telemetry/metrics.d.ts +2 -0
- package/dist/runtime/telemetry/metrics.js +4 -1
- package/dist/runtime/telemetry/sampler.js +33 -13
- package/dist/runtime/telemetry/spans.d.ts +1 -1
- package/dist/runtime/telemetry/spans.js +1 -1
- package/dist/runtime/topology/locks.d.ts +6 -3
- package/dist/runtime/topology/locks.js +27 -4
- package/dist/runtime/turn/execute.d.ts +2 -0
- package/dist/runtime/turn/execute.js +5 -2
- package/dist/runtime/turn/pipeline.d.ts +5 -12
- package/dist/runtime/turn/pipeline.js +11 -11
- package/dist/runtime/turn/relay.d.ts +13 -3
- package/dist/runtime/turn/relay.js +27 -14
- package/dist/runtime/turn/rows.js +4 -4
- package/dist/runtime/workflows/compatibility.d.ts +1 -1
- package/dist/runtime/workflows/compatibility.js +85 -31
- package/dist/runtime/workflows/engine.js +20 -17
- package/dist/serve/layer.js +3 -2
- package/dist/tables/owned.d.ts +1 -1
- package/dist/tables/owned.js +1 -1
- package/dist/testing/actor-test.d.ts +2 -24
- package/dist/testing/actor-test.js +1 -27
- package/dist/testing/index.d.ts +0 -12
- package/dist/testing/index.js +0 -6
- package/package.json +1 -1
- package/dist/runtime/database/neki/migrations.d.ts +0 -31
- package/dist/runtime/database/neki/migrations.js +0 -276
- package/dist/runtime/database/neki/session.d.ts +0 -23
- package/dist/runtime/database/neki/session.js +0 -31
- package/dist/testing/cluster.d.ts +0 -93
- package/dist/testing/cluster.js +0 -296
- package/dist/testing/conformance/access.d.ts +0 -5
- package/dist/testing/conformance/access.js +0 -531
- package/dist/testing/conformance/admission.d.ts +0 -11
- package/dist/testing/conformance/admission.js +0 -182
- package/dist/testing/conformance/adoption.d.ts +0 -2
- package/dist/testing/conformance/adoption.js +0 -1019
- package/dist/testing/conformance/assertions.d.ts +0 -202
- package/dist/testing/conformance/assertions.js +0 -849
- package/dist/testing/conformance/batches.d.ts +0 -41
- package/dist/testing/conformance/batches.js +0 -388
- package/dist/testing/conformance/blobs.d.ts +0 -14
- package/dist/testing/conformance/blobs.js +0 -405
- package/dist/testing/conformance/capacity.d.ts +0 -8
- package/dist/testing/conformance/capacity.js +0 -433
- package/dist/testing/conformance/client.d.ts +0 -5
- package/dist/testing/conformance/client.js +0 -719
- package/dist/testing/conformance/cold-serve.d.ts +0 -16
- package/dist/testing/conformance/cold-serve.js +0 -254
- package/dist/testing/conformance/connections/actors.d.ts +0 -1143
- package/dist/testing/conformance/connections/actors.js +0 -180
- package/dist/testing/conformance/connections/harness.d.ts +0 -1754
- package/dist/testing/conformance/connections/harness.js +0 -142
- package/dist/testing/conformance/connections/holders.d.ts +0 -4
- package/dist/testing/conformance/connections/holders.js +0 -165
- package/dist/testing/conformance/connections/lifecycle.d.ts +0 -4
- package/dist/testing/conformance/connections/lifecycle.js +0 -113
- package/dist/testing/conformance/connections/limits.d.ts +0 -4
- package/dist/testing/conformance/connections/limits.js +0 -127
- package/dist/testing/conformance/connections/reauthorization.d.ts +0 -4
- package/dist/testing/conformance/connections/reauthorization.js +0 -170
- package/dist/testing/conformance/connections/resync.d.ts +0 -4
- package/dist/testing/conformance/connections/resync.js +0 -360
- package/dist/testing/conformance/connections/takeover.d.ts +0 -4
- package/dist/testing/conformance/connections/takeover.js +0 -287
- package/dist/testing/conformance/connections.d.ts +0 -4
- package/dist/testing/conformance/connections.js +0 -15
- package/dist/testing/conformance/content-blobs.d.ts +0 -16
- package/dist/testing/conformance/content-blobs.js +0 -534
- package/dist/testing/conformance/counter.d.ts +0 -16
- package/dist/testing/conformance/counter.js +0 -813
- package/dist/testing/conformance/cron.d.ts +0 -5
- package/dist/testing/conformance/cron.js +0 -665
- package/dist/testing/conformance/drain.d.ts +0 -26
- package/dist/testing/conformance/drain.js +0 -540
- package/dist/testing/conformance/effect-control.d.ts +0 -38
- package/dist/testing/conformance/effect-control.js +0 -1059
- package/dist/testing/conformance/effects.d.ts +0 -23
- package/dist/testing/conformance/effects.js +0 -432
- package/dist/testing/conformance/events.d.ts +0 -28
- package/dist/testing/conformance/events.js +0 -335
- package/dist/testing/conformance/export.d.ts +0 -2
- package/dist/testing/conformance/export.js +0 -368
- package/dist/testing/conformance/fleet.d.ts +0 -444
- package/dist/testing/conformance/fleet.js +0 -1009
- package/dist/testing/conformance/groups.d.ts +0 -7
- package/dist/testing/conformance/groups.js +0 -353
- package/dist/testing/conformance/heap.d.ts +0 -3
- package/dist/testing/conformance/heap.js +0 -149
- package/dist/testing/conformance/http.d.ts +0 -2809
- package/dist/testing/conformance/http.js +0 -1234
- package/dist/testing/conformance/inspection-views.d.ts +0 -8
- package/dist/testing/conformance/inspection-views.js +0 -272
- package/dist/testing/conformance/inspector.d.ts +0 -7
- package/dist/testing/conformance/inspector.js +0 -650
- package/dist/testing/conformance/mint.d.ts +0 -58
- package/dist/testing/conformance/mint.js +0 -692
- package/dist/testing/conformance/multi-runner.d.ts +0 -8
- package/dist/testing/conformance/multi-runner.js +0 -403
- package/dist/testing/conformance/neki/plan.d.ts +0 -19
- package/dist/testing/conformance/neki/plan.js +0 -30
- package/dist/testing/conformance/observability.d.ts +0 -3
- package/dist/testing/conformance/observability.js +0 -343
- package/dist/testing/conformance/offline.d.ts +0 -4
- package/dist/testing/conformance/offline.js +0 -474
- package/dist/testing/conformance/operator-harness.d.ts +0 -57
- package/dist/testing/conformance/operator-harness.js +0 -78
- package/dist/testing/conformance/operator.d.ts +0 -3
- package/dist/testing/conformance/operator.js +0 -379
- package/dist/testing/conformance/outbox-cross-shard.d.ts +0 -14
- package/dist/testing/conformance/outbox-cross-shard.js +0 -160
- package/dist/testing/conformance/outbox.d.ts +0 -36
- package/dist/testing/conformance/outbox.js +0 -437
- package/dist/testing/conformance/payload-migrations.d.ts +0 -3
- package/dist/testing/conformance/payload-migrations.js +0 -612
- package/dist/testing/conformance/pipeline.d.ts +0 -3
- package/dist/testing/conformance/pipeline.js +0 -1040
- package/dist/testing/conformance/placement.d.ts +0 -22
- package/dist/testing/conformance/placement.js +0 -539
- package/dist/testing/conformance/platform.d.ts +0 -40
- package/dist/testing/conformance/platform.js +0 -101
- package/dist/testing/conformance/progress.d.ts +0 -39
- package/dist/testing/conformance/progress.js +0 -666
- package/dist/testing/conformance/properties.d.ts +0 -6
- package/dist/testing/conformance/properties.js +0 -295
- package/dist/testing/conformance/protocols.d.ts +0 -4
- package/dist/testing/conformance/protocols.js +0 -618
- package/dist/testing/conformance/provider/advertise.d.ts +0 -21
- package/dist/testing/conformance/provider/advertise.js +0 -44
- package/dist/testing/conformance/read-your-writes.d.ts +0 -20
- package/dist/testing/conformance/read-your-writes.js +0 -192
- package/dist/testing/conformance/reducers.d.ts +0 -8
- package/dist/testing/conformance/reducers.js +0 -258
- package/dist/testing/conformance/relay.d.ts +0 -42
- package/dist/testing/conformance/relay.js +0 -1115
- package/dist/testing/conformance/restore.d.ts +0 -43
- package/dist/testing/conformance/restore.js +0 -341
- package/dist/testing/conformance/retention.d.ts +0 -14
- package/dist/testing/conformance/retention.js +0 -463
- package/dist/testing/conformance/rls.d.ts +0 -24
- package/dist/testing/conformance/rls.js +0 -576
- package/dist/testing/conformance/simulation.d.ts +0 -31
- package/dist/testing/conformance/simulation.js +0 -167
- package/dist/testing/conformance/single-shard.d.ts +0 -2
- package/dist/testing/conformance/single-shard.js +0 -125
- package/dist/testing/conformance/singleton.d.ts +0 -3
- package/dist/testing/conformance/singleton.js +0 -293
- package/dist/testing/conformance/statements.d.ts +0 -60
- package/dist/testing/conformance/statements.js +0 -108
- package/dist/testing/conformance/streams.d.ts +0 -7
- package/dist/testing/conformance/streams.js +0 -280
- package/dist/testing/conformance/subscriptions/access.d.ts +0 -4
- package/dist/testing/conformance/subscriptions/access.js +0 -98
- package/dist/testing/conformance/subscriptions/actors.d.ts +0 -4910
- package/dist/testing/conformance/subscriptions/actors.js +0 -372
- package/dist/testing/conformance/subscriptions/cluster.d.ts +0 -4
- package/dist/testing/conformance/subscriptions/cluster.js +0 -89
- package/dist/testing/conformance/subscriptions/delivery.d.ts +0 -4
- package/dist/testing/conformance/subscriptions/delivery.js +0 -253
- package/dist/testing/conformance/subscriptions/deploys.d.ts +0 -4
- package/dist/testing/conformance/subscriptions/deploys.js +0 -162
- package/dist/testing/conformance/subscriptions/epochs.d.ts +0 -4
- package/dist/testing/conformance/subscriptions/epochs.js +0 -169
- package/dist/testing/conformance/subscriptions/failures.d.ts +0 -4
- package/dist/testing/conformance/subscriptions/failures.js +0 -108
- package/dist/testing/conformance/subscriptions/feeds.d.ts +0 -4
- package/dist/testing/conformance/subscriptions/feeds.js +0 -218
- package/dist/testing/conformance/subscriptions/harness.d.ts +0 -124
- package/dist/testing/conformance/subscriptions/harness.js +0 -143
- package/dist/testing/conformance/subscriptions/operator.d.ts +0 -4
- package/dist/testing/conformance/subscriptions/operator.js +0 -128
- package/dist/testing/conformance/subscriptions/retention.d.ts +0 -4
- package/dist/testing/conformance/subscriptions/retention.js +0 -288
- package/dist/testing/conformance/subscriptions/routing.d.ts +0 -4
- package/dist/testing/conformance/subscriptions/routing.js +0 -179
- package/dist/testing/conformance/subscriptions.d.ts +0 -4
- package/dist/testing/conformance/subscriptions.js +0 -19
- package/dist/testing/conformance/tables.d.ts +0 -125
- package/dist/testing/conformance/tables.js +0 -664
- package/dist/testing/conformance/transports/actors.d.ts +0 -1907
- package/dist/testing/conformance/transports/actors.js +0 -163
- package/dist/testing/conformance/transports/client.d.ts +0 -3
- package/dist/testing/conformance/transports/client.js +0 -237
- package/dist/testing/conformance/transports/feeds.d.ts +0 -3
- package/dist/testing/conformance/transports/feeds.js +0 -232
- package/dist/testing/conformance/transports/harness.d.ts +0 -93
- package/dist/testing/conformance/transports/harness.js +0 -84
- package/dist/testing/conformance/transports/streams.d.ts +0 -3
- package/dist/testing/conformance/transports/streams.js +0 -96
- package/dist/testing/conformance/transports/websocket.d.ts +0 -3
- package/dist/testing/conformance/transports/websocket.js +0 -384
- package/dist/testing/conformance/transports/wire.d.ts +0 -141
- package/dist/testing/conformance/transports/wire.js +0 -204
- package/dist/testing/conformance/transports.d.ts +0 -3
- package/dist/testing/conformance/transports.js +0 -11
- package/dist/testing/conformance/watch.d.ts +0 -59
- package/dist/testing/conformance/watch.js +0 -879
- package/dist/testing/conformance/workflow-engine.d.ts +0 -97
- package/dist/testing/conformance/workflow-engine.js +0 -253
- package/dist/testing/conformance/workflow-versions.d.ts +0 -3
- package/dist/testing/conformance/workflow-versions.js +0 -545
- package/dist/testing/conformance/workflows/access.d.ts +0 -4
- package/dist/testing/conformance/workflows/access.js +0 -147
- package/dist/testing/conformance/workflows/actors.d.ts +0 -2317
- package/dist/testing/conformance/workflows/actors.js +0 -305
- package/dist/testing/conformance/workflows/basics.d.ts +0 -4
- package/dist/testing/conformance/workflows/basics.js +0 -144
- package/dist/testing/conformance/workflows/engine.d.ts +0 -4
- package/dist/testing/conformance/workflows/engine.js +0 -80
- package/dist/testing/conformance/workflows/guards.d.ts +0 -4
- package/dist/testing/conformance/workflows/guards.js +0 -172
- package/dist/testing/conformance/workflows/harness.d.ts +0 -14
- package/dist/testing/conformance/workflows/harness.js +0 -44
- package/dist/testing/conformance/workflows/recovery.d.ts +0 -4
- package/dist/testing/conformance/workflows/recovery.js +0 -181
- package/dist/testing/conformance/workflows/starts.d.ts +0 -4
- package/dist/testing/conformance/workflows/starts.js +0 -57
- package/dist/testing/conformance/workflows/suspension.d.ts +0 -4
- package/dist/testing/conformance/workflows/suspension.js +0 -106
- package/dist/testing/conformance/workflows/waits.d.ts +0 -4
- package/dist/testing/conformance/workflows/waits.js +0 -284
- package/dist/testing/conformance/workflows.d.ts +0 -4
- package/dist/testing/conformance/workflows.js +0 -19
- package/dist/testing/conformance.d.ts +0 -330
- package/dist/testing/conformance.js +0 -364
- package/dist/testing/foundation.d.ts +0 -41
- package/dist/testing/foundation.js +0 -517
- package/dist/testing/simulate-cluster.d.ts +0 -112
- package/dist/testing/simulate-cluster.js +0 -257
- package/dist/testing/simulate.d.ts +0 -90
- package/dist/testing/simulate.js +0 -127
|
@@ -1,8 +1,71 @@
|
|
|
1
|
-
import { Effect, Option } from "effect";
|
|
1
|
+
import { Effect, Option, Schedule, Schema } from "effect";
|
|
2
2
|
import { PgClient } from "@effect/sql-pg";
|
|
3
|
-
import { Migrator, SqlClient } from "effect/sql";
|
|
4
|
-
import {
|
|
5
|
-
|
|
3
|
+
import { Migrator, SqlClient, SqlError } from "effect/sql";
|
|
4
|
+
import { withMigrationCoordination } from "./coordination.js";
|
|
5
|
+
/** Transactional migrations never resume a partially committed body. */
|
|
6
|
+
const MigrationResuming = Effect.succeed(false);
|
|
7
|
+
/** How long a migration's table DDL waits for its lock before giving way. */
|
|
8
|
+
const LOCK_TIMEOUT = "2s";
|
|
9
|
+
/** How many times a migration's table DDL that gave way is tried again. */
|
|
10
|
+
const LOCK_ATTEMPTS = 30;
|
|
11
|
+
const isLockBusy = Schema.is(Schema.Struct({ code: Schema.Literal("55P03") }));
|
|
12
|
+
/**
|
|
13
|
+
* Runs `ddl`, whose table lock would otherwise wait behind any long
|
|
14
|
+
* transaction on the table and hold every turn queued behind it, waiting at
|
|
15
|
+
* most `LOCK_TIMEOUT` for the lock. On Postgres each attempt runs in a
|
|
16
|
+
* savepoint of the migration's transaction, so one that gave way is rolled
|
|
17
|
+
* back and tried again. The previous `lock_timeout` is restored afterwards.
|
|
18
|
+
*/
|
|
19
|
+
const briefLocks = (ddl) => Effect.gen(function* () {
|
|
20
|
+
const sql = yield* SqlClient.SqlClient;
|
|
21
|
+
const [previous] = yield* sql `SELECT current_setting('lock_timeout') AS value`;
|
|
22
|
+
const limit = sql `SELECT set_config('lock_timeout', ${LOCK_TIMEOUT}, true)`;
|
|
23
|
+
const restore = sql `SELECT set_config('lock_timeout', ${previous.value}, true)`.pipe(Effect.ignore);
|
|
24
|
+
return yield* sql.withTransaction(Effect.andThen(limit, ddl)).pipe(Effect.retry({
|
|
25
|
+
while: (error) => SqlError.isSqlError(error) && isLockBusy(error.reason.cause),
|
|
26
|
+
times: LOCK_ATTEMPTS,
|
|
27
|
+
schedule: Schedule.spaced("500 millis"),
|
|
28
|
+
}), Effect.ensuring(restore));
|
|
29
|
+
});
|
|
30
|
+
/** The first set of inspection views and the version the catalog lists for each. */
|
|
31
|
+
const FIRST_VIEWS = [
|
|
32
|
+
["actors", 1],
|
|
33
|
+
["state", 1],
|
|
34
|
+
["receipts", 2],
|
|
35
|
+
["events", 1],
|
|
36
|
+
["outbox", 1],
|
|
37
|
+
["timers", 1],
|
|
38
|
+
["jobs", 1],
|
|
39
|
+
["dead_letters", 2],
|
|
40
|
+
["workflows", 1],
|
|
41
|
+
["workflow_steps", 1],
|
|
42
|
+
["contents", 1],
|
|
43
|
+
["content_refs", 1],
|
|
44
|
+
["operator_audit", 1],
|
|
45
|
+
];
|
|
46
|
+
/** The single-table views `0031_routable_views` creates. */
|
|
47
|
+
export const ROUTABLE_VIEWS = [
|
|
48
|
+
"actors_v2",
|
|
49
|
+
"state_v2",
|
|
50
|
+
"receipts_v2",
|
|
51
|
+
"events_v2",
|
|
52
|
+
"outbox_v2",
|
|
53
|
+
"timers_v2",
|
|
54
|
+
"jobs_v2",
|
|
55
|
+
"dead_letters_v2",
|
|
56
|
+
"workflows_v2",
|
|
57
|
+
"workflow_steps_v2",
|
|
58
|
+
"contents_v2",
|
|
59
|
+
"content_sweeps_v2",
|
|
60
|
+
"content_refs_v2",
|
|
61
|
+
"operator_audit_v2",
|
|
62
|
+
"placements_v2",
|
|
63
|
+
];
|
|
64
|
+
/**
|
|
65
|
+
* Applied migration bodies retain their original calls; every supported database
|
|
66
|
+
* creates the joined inspection views.
|
|
67
|
+
*/
|
|
68
|
+
const joinedViews = (_tables, views) => views;
|
|
6
69
|
/** Every framework migration by id, applied in order above the latest applied id. */
|
|
7
70
|
export const migrations = {
|
|
8
71
|
"0001_foundation": Effect.gen(function* () {
|
|
@@ -317,74 +380,85 @@ export const migrations = {
|
|
|
317
380
|
"0013_inspection_views": Effect.gen(function* () {
|
|
318
381
|
const sql = yield* SqlClient.SqlClient;
|
|
319
382
|
yield* sql `CREATE SCHEMA durable`;
|
|
320
|
-
yield*
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
o.
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
383
|
+
yield* joinedViews([
|
|
384
|
+
"actor_generations",
|
|
385
|
+
"actor_state",
|
|
386
|
+
"actor_receipts",
|
|
387
|
+
"actor_events",
|
|
388
|
+
"actor_outbox",
|
|
389
|
+
"actor_dead_letters",
|
|
390
|
+
"actor_workflow_executions",
|
|
391
|
+
"actor_workflow_step",
|
|
392
|
+
], Effect.gen(function* () {
|
|
393
|
+
yield* sql `CREATE VIEW durable.actors AS
|
|
394
|
+
SELECT g.tenant_id, g.actor_type, g.actor_id, g.routing_key, p.placement,
|
|
395
|
+
g.generation, g.created, g.event_sequence AS last_event_sequence
|
|
396
|
+
FROM actor_generations g
|
|
397
|
+
LEFT JOIN actor_placements p ON p.actor_type = g.actor_type`;
|
|
398
|
+
yield* sql `CREATE VIEW durable.state AS
|
|
399
|
+
SELECT s.tenant_id, s.actor_type, s.actor_id, s.routing_key, p.placement,
|
|
400
|
+
s.key, s.value, octet_length(s.value) AS value_bytes
|
|
401
|
+
FROM actor_state s
|
|
402
|
+
LEFT JOIN actor_placements p ON p.actor_type = s.actor_type`;
|
|
403
|
+
yield* sql `CREATE VIEW durable.receipts AS
|
|
404
|
+
SELECT r.tenant_id, r.actor_type, r.actor_id, r.routing_key, p.placement,
|
|
405
|
+
r.command_id, r.command, r.caller_key,
|
|
406
|
+
r.outcome::jsonb ->> '_tag' AS outcome_tag, r.outcome,
|
|
407
|
+
r.expires_at_ms, to_timestamp(r.expires_at_ms::float8 / 1000) AS expires_at
|
|
408
|
+
FROM actor_receipts r
|
|
409
|
+
LEFT JOIN actor_placements p ON p.actor_type = r.actor_type`;
|
|
410
|
+
yield* sql `CREATE VIEW durable.events AS
|
|
411
|
+
SELECT e.tenant_id, e.actor_type, e.actor_id, e.routing_key, p.placement,
|
|
412
|
+
e.sequence, e.event, e.command_id, e.value, octet_length(e.value) AS value_bytes,
|
|
413
|
+
e.emitted_at_ms, to_timestamp(e.emitted_at_ms::float8 / 1000) AS emitted_at
|
|
414
|
+
FROM actor_events e
|
|
415
|
+
LEFT JOIN actor_placements p ON p.actor_type = e.actor_type`;
|
|
416
|
+
yield* sql `CREATE VIEW durable.outbox AS
|
|
417
|
+
SELECT o.tenant_id, o.actor_type, o.actor_id, o.routing_key, p.placement,
|
|
418
|
+
o.intent_id, o.timer_key, o.target_type, o.target_id, o.command, o.payload, o.caller,
|
|
419
|
+
o.attempts, o.last_error, o.due_at_ms, to_timestamp(o.due_at_ms::float8 / 1000) AS due_at
|
|
420
|
+
FROM actor_outbox o
|
|
421
|
+
LEFT JOIN actor_placements p ON p.actor_type = o.actor_type
|
|
422
|
+
WHERE o.kind = 'intent'`;
|
|
423
|
+
yield* sql `CREATE VIEW durable.timers AS
|
|
424
|
+
SELECT o.tenant_id, o.actor_type, o.actor_id, o.routing_key, p.placement,
|
|
425
|
+
o.timer_key, o.intent_id, o.target_type, o.target_id, o.command, o.payload, o.caller,
|
|
426
|
+
o.attempts, o.due_at_ms, to_timestamp(o.due_at_ms::float8 / 1000) AS due_at
|
|
427
|
+
FROM actor_outbox o
|
|
428
|
+
LEFT JOIN actor_placements p ON p.actor_type = o.actor_type
|
|
429
|
+
WHERE o.kind = 'intent' AND o.timer_key IS NOT NULL`;
|
|
430
|
+
yield* sql `CREATE VIEW durable.effects AS
|
|
431
|
+
SELECT o.tenant_id, o.actor_type, o.actor_id, o.routing_key, p.placement,
|
|
432
|
+
o.intent_id AS effect_id, o.command AS effect, o.payload, o.caller,
|
|
433
|
+
o.attempts, o.last_error, o.ambiguous,
|
|
434
|
+
o.due_at_ms, to_timestamp(o.due_at_ms::float8 / 1000) AS due_at
|
|
435
|
+
FROM actor_outbox o
|
|
436
|
+
LEFT JOIN actor_placements p ON p.actor_type = o.actor_type
|
|
437
|
+
WHERE o.kind = 'effect'`;
|
|
438
|
+
yield* sql `CREATE VIEW durable.dead_letters AS
|
|
439
|
+
SELECT d.tenant_id, d.actor_type, d.actor_id, d.routing_key, p.placement,
|
|
440
|
+
d.effect_id, d.effect, d.payload, d.attempts, d.cause, d.ambiguous,
|
|
441
|
+
d.dead_at_ms, to_timestamp(d.dead_at_ms::float8 / 1000) AS dead_at
|
|
442
|
+
FROM actor_dead_letters d
|
|
443
|
+
LEFT JOIN actor_placements p ON p.actor_type = d.actor_type`;
|
|
444
|
+
yield* sql `CREATE VIEW durable.workflows AS
|
|
445
|
+
SELECT w.tenant_id, w.actor_type, w.actor_id, w.routing_key, p.placement,
|
|
446
|
+
w.execution_id, w.workflow, w.workflow_key, w.manifest_hash, w.status, w.interrupt,
|
|
447
|
+
w.caller, w.payload, octet_length(w.payload) AS payload_bytes,
|
|
448
|
+
w.result, octet_length(w.result) AS result_bytes,
|
|
449
|
+
w.started_at_ms, to_timestamp(w.started_at_ms::float8 / 1000) AS started_at,
|
|
450
|
+
w.finished_at_ms, to_timestamp(w.finished_at_ms::float8 / 1000) AS finished_at
|
|
451
|
+
FROM actor_workflow_executions w
|
|
452
|
+
LEFT JOIN actor_placements p ON p.actor_type = w.actor_type`;
|
|
453
|
+
yield* sql `CREATE VIEW durable.workflow_steps AS
|
|
454
|
+
SELECT s.tenant_id, s.actor_type, s.actor_id, s.routing_key, p.placement,
|
|
455
|
+
s.execution_id, s.step, s.attempt, s.kind, s.exit, s.wait_event, s.version,
|
|
456
|
+
s.due_at_ms, to_timestamp(s.due_at_ms::float8 / 1000) AS due_at,
|
|
457
|
+
s.started_at_ms, to_timestamp(s.started_at_ms::float8 / 1000) AS started_at,
|
|
458
|
+
s.settled_at_ms, to_timestamp(s.settled_at_ms::float8 / 1000) AS settled_at
|
|
459
|
+
FROM actor_workflow_step s
|
|
460
|
+
LEFT JOIN actor_placements p ON p.actor_type = s.actor_type`;
|
|
461
|
+
}));
|
|
388
462
|
yield* sql `CREATE VIEW durable.views AS
|
|
389
463
|
SELECT view_name, version FROM (VALUES
|
|
390
464
|
('actors', 1), ('state', 1), ('receipts', 1), ('events', 1), ('outbox', 1),
|
|
@@ -618,17 +692,19 @@ export const migrations = {
|
|
|
618
692
|
actor_type text PRIMARY KEY,
|
|
619
693
|
turn_ms bigint NOT NULL CHECK (turn_ms > 0)
|
|
620
694
|
)`;
|
|
621
|
-
yield*
|
|
622
|
-
|
|
623
|
-
c.
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
r.
|
|
630
|
-
|
|
631
|
-
|
|
695
|
+
yield* joinedViews(["tenant_contents", "tenant_content_sweeps", "actor_content_refs"], Effect.gen(function* () {
|
|
696
|
+
yield* sql `CREATE VIEW durable.contents AS
|
|
697
|
+
SELECT c.tenant_id, c.routing_key, c.hash, c.size,
|
|
698
|
+
c.granted_until_ms, to_timestamp(c.granted_until_ms::float8 / 1000) AS granted_until,
|
|
699
|
+
s.swept_at_ms, to_timestamp(s.swept_at_ms::float8 / 1000) AS swept_at
|
|
700
|
+
FROM tenant_contents c
|
|
701
|
+
LEFT JOIN tenant_content_sweeps s ON s.routing_key = c.routing_key AND s.tenant_id = c.tenant_id`;
|
|
702
|
+
yield* sql `CREATE VIEW durable.content_refs AS
|
|
703
|
+
SELECT r.tenant_id, r.actor_type, r.actor_id, r.routing_key, p.placement,
|
|
704
|
+
r.blob, r.name, r.hash, r.size
|
|
705
|
+
FROM actor_content_refs r
|
|
706
|
+
LEFT JOIN actor_placements p ON p.actor_type = r.actor_type`;
|
|
707
|
+
}));
|
|
632
708
|
yield* sql `CREATE OR REPLACE VIEW durable.views AS
|
|
633
709
|
SELECT view_name, version FROM (VALUES
|
|
634
710
|
('actors', 1), ('state', 1), ('receipts', 1), ('events', 1), ('outbox', 1),
|
|
@@ -685,29 +761,31 @@ export const migrations = {
|
|
|
685
761
|
)`;
|
|
686
762
|
yield* sql `CREATE INDEX actor_payload_writers_version
|
|
687
763
|
ON actor_payload_writers (actor_type, kind, tag, version, refreshed_at_ms)`;
|
|
688
|
-
yield*
|
|
689
|
-
|
|
690
|
-
e.
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
o.
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
764
|
+
yield* joinedViews(["actor_events", "actor_outbox", "actor_dead_letters"], Effect.gen(function* () {
|
|
765
|
+
yield* sql `CREATE OR REPLACE VIEW durable.events AS
|
|
766
|
+
SELECT e.tenant_id, e.actor_type, e.actor_id, e.routing_key, p.placement,
|
|
767
|
+
e.sequence, e.event, e.command_id, e.value, octet_length(e.value) AS value_bytes,
|
|
768
|
+
e.emitted_at_ms, to_timestamp(e.emitted_at_ms::float8 / 1000) AS emitted_at,
|
|
769
|
+
e.payload_version
|
|
770
|
+
FROM actor_events e
|
|
771
|
+
LEFT JOIN actor_placements p ON p.actor_type = e.actor_type`;
|
|
772
|
+
yield* sql `CREATE OR REPLACE VIEW durable.effects AS
|
|
773
|
+
SELECT o.tenant_id, o.actor_type, o.actor_id, o.routing_key, p.placement,
|
|
774
|
+
o.intent_id AS effect_id, o.command AS effect, o.payload, o.caller,
|
|
775
|
+
o.attempts, o.last_error, o.ambiguous,
|
|
776
|
+
o.due_at_ms, to_timestamp(o.due_at_ms::float8 / 1000) AS due_at,
|
|
777
|
+
o.payload_version
|
|
778
|
+
FROM actor_outbox o
|
|
779
|
+
LEFT JOIN actor_placements p ON p.actor_type = o.actor_type
|
|
780
|
+
WHERE o.kind = 'effect'`;
|
|
781
|
+
yield* sql `CREATE OR REPLACE VIEW durable.dead_letters AS
|
|
782
|
+
SELECT d.tenant_id, d.actor_type, d.actor_id, d.routing_key, p.placement,
|
|
783
|
+
d.effect_id, d.effect, d.payload, d.attempts, d.cause, d.ambiguous,
|
|
784
|
+
d.dead_at_ms, to_timestamp(d.dead_at_ms::float8 / 1000) AS dead_at,
|
|
785
|
+
d.payload_version
|
|
786
|
+
FROM actor_dead_letters d
|
|
787
|
+
LEFT JOIN actor_placements p ON p.actor_type = d.actor_type`;
|
|
788
|
+
}));
|
|
711
789
|
}),
|
|
712
790
|
/**
|
|
713
791
|
* A parent-placed type routes through its parent type's placement, so the parent is part of
|
|
@@ -752,12 +830,12 @@ export const migrations = {
|
|
|
752
830
|
yield* sql `CREATE POLICY durable_tenant ON actor_operator_audit
|
|
753
831
|
USING (tenant_id = current_setting('durable.tenant', true))
|
|
754
832
|
WITH CHECK (tenant_id = current_setting('durable.tenant', true))`;
|
|
755
|
-
yield* sql `CREATE VIEW durable.operator_audit AS
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
833
|
+
yield* joinedViews(["actor_operator_audit"], sql `CREATE VIEW durable.operator_audit AS
|
|
834
|
+
SELECT a.tenant_id, a.actor_type, a.actor_id, a.routing_key, p.placement, a.audit_id,
|
|
835
|
+
a.operator, a.action, a.target, a.capability, a.reason, a.outcome,
|
|
836
|
+
a.at_ms, to_timestamp(a.at_ms::float8 / 1000) AS at
|
|
837
|
+
FROM actor_operator_audit a
|
|
838
|
+
LEFT JOIN actor_placements p ON p.actor_type = a.actor_type`);
|
|
761
839
|
yield* sql `CREATE OR REPLACE VIEW durable.views AS
|
|
762
840
|
SELECT view_name, version FROM (VALUES
|
|
763
841
|
('actors', 1), ('state', 1), ('receipts', 1), ('events', 1), ('outbox', 1),
|
|
@@ -929,24 +1007,26 @@ export const migrations = {
|
|
|
929
1007
|
}
|
|
930
1008
|
yield* sql `ALTER TABLE actor_subscription_tags DROP CONSTRAINT actor_subscription_tags_rows_check,
|
|
931
1009
|
ADD CONSTRAINT actor_subscription_tags_rows_check CHECK (rows >= 0)`;
|
|
932
|
-
yield*
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
o.
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
1010
|
+
yield* joinedViews(["actor_outbox", "actor_dead_letters"], Effect.gen(function* () {
|
|
1011
|
+
yield* sql `DROP VIEW durable.effects`;
|
|
1012
|
+
yield* sql `DROP VIEW durable.dead_letters`;
|
|
1013
|
+
yield* sql `CREATE VIEW durable.jobs AS
|
|
1014
|
+
SELECT o.tenant_id, o.actor_type, o.actor_id, o.routing_key, p.placement,
|
|
1015
|
+
o.intent_id AS job_id, o.command AS job, o.payload, o.caller,
|
|
1016
|
+
o.attempts, o.last_error, o.ambiguous,
|
|
1017
|
+
o.due_at_ms, to_timestamp(o.due_at_ms::float8 / 1000) AS due_at,
|
|
1018
|
+
o.payload_version
|
|
1019
|
+
FROM actor_outbox o
|
|
1020
|
+
LEFT JOIN actor_placements p ON p.actor_type = o.actor_type
|
|
1021
|
+
WHERE o.kind = 'job'`;
|
|
1022
|
+
yield* sql `CREATE VIEW durable.dead_letters AS
|
|
1023
|
+
SELECT d.tenant_id, d.actor_type, d.actor_id, d.routing_key, p.placement,
|
|
1024
|
+
d.job_id, d.job, d.payload, d.attempts, d.cause, d.ambiguous,
|
|
1025
|
+
d.dead_at_ms, to_timestamp(d.dead_at_ms::float8 / 1000) AS dead_at,
|
|
1026
|
+
d.payload_version
|
|
1027
|
+
FROM actor_dead_letters d
|
|
1028
|
+
LEFT JOIN actor_placements p ON p.actor_type = d.actor_type`;
|
|
1029
|
+
}));
|
|
950
1030
|
yield* sql `CREATE OR REPLACE VIEW durable.views AS
|
|
951
1031
|
SELECT view_name, version FROM (VALUES
|
|
952
1032
|
('actors', 1), ('state', 1), ('receipts', 1), ('events', 1), ('outbox', 1),
|
|
@@ -970,6 +1050,169 @@ export const migrations = {
|
|
|
970
1050
|
runner_shards BETWEEN 1 AND 65536)
|
|
971
1051
|
)`;
|
|
972
1052
|
}),
|
|
1053
|
+
/**
|
|
1054
|
+
* A receipt's start is the clock its batch's fenced read selected, and its commit time the
|
|
1055
|
+
* clock when the commit flight writes the row, so both are the database's own clock and a
|
|
1056
|
+
* receipt binds nothing for the second. The default is set after the column exists, so rows
|
|
1057
|
+
* written before this migration keep `null` instead of the migration's own time.
|
|
1058
|
+
*/
|
|
1059
|
+
"0030_receipt_timing": Effect.gen(function* () {
|
|
1060
|
+
const sql = yield* SqlClient.SqlClient;
|
|
1061
|
+
yield* briefLocks(Effect.gen(function* () {
|
|
1062
|
+
yield* sql `ALTER TABLE actor_receipts ADD COLUMN started_at_ms bigint,
|
|
1063
|
+
ADD COLUMN committed_at_ms bigint`;
|
|
1064
|
+
yield* sql `ALTER TABLE actor_receipts ALTER COLUMN committed_at_ms
|
|
1065
|
+
SET DEFAULT floor(extract(epoch FROM clock_timestamp()) * 1000)::bigint`;
|
|
1066
|
+
}));
|
|
1067
|
+
yield* joinedViews(["actor_receipts"], sql `CREATE OR REPLACE VIEW durable.receipts AS
|
|
1068
|
+
SELECT r.tenant_id, r.actor_type, r.actor_id, r.routing_key, p.placement,
|
|
1069
|
+
r.command_id, r.command, r.caller_key,
|
|
1070
|
+
r.outcome::jsonb ->> '_tag' AS outcome_tag, r.outcome,
|
|
1071
|
+
r.expires_at_ms, to_timestamp(r.expires_at_ms::float8 / 1000) AS expires_at,
|
|
1072
|
+
r.started_at_ms, r.committed_at_ms,
|
|
1073
|
+
to_timestamp(r.committed_at_ms::float8 / 1000) AS committed_at,
|
|
1074
|
+
r.committed_at_ms - r.started_at_ms AS duration_ms
|
|
1075
|
+
FROM actor_receipts r
|
|
1076
|
+
LEFT JOIN actor_placements p ON p.actor_type = r.actor_type`);
|
|
1077
|
+
yield* sql `CREATE OR REPLACE VIEW durable.views AS
|
|
1078
|
+
SELECT view_name, version FROM (VALUES
|
|
1079
|
+
('actors', 1), ('state', 1), ('receipts', 2), ('events', 1), ('outbox', 1),
|
|
1080
|
+
('timers', 1), ('jobs', 1), ('dead_letters', 2), ('workflows', 1),
|
|
1081
|
+
('workflow_steps', 1), ('views', 1), ('contents', 1), ('content_refs', 1),
|
|
1082
|
+
('operator_audit', 1)
|
|
1083
|
+
) AS v(view_name, version)`;
|
|
1084
|
+
}),
|
|
1085
|
+
/**
|
|
1086
|
+
* A second set of inspection views, each reading exactly one table, with the actor type's
|
|
1087
|
+
* placement in a view of its own (`placements_v2`) that a tool joins by `actor_type`. A Neki
|
|
1088
|
+
* router serves a view on a group routed by `routing_key` only when it is a projection or
|
|
1089
|
+
* filter of one table; the first set joins `actor_placements` to every view, and a view over
|
|
1090
|
+
* several tables of one group is refused too.
|
|
1091
|
+
*
|
|
1092
|
+
* Every column keeps its name, meaning and type apart from `placement`, which moves. A single
|
|
1093
|
+
* table view is automatically updatable, so the migration takes every write privilege on
|
|
1094
|
+
* each of them from its owner; the first set's joins kept it read-only structurally.
|
|
1095
|
+
*
|
|
1096
|
+
* The catalog lists the first set only where it exists, because a routed layout never
|
|
1097
|
+
* created it.
|
|
1098
|
+
*/
|
|
1099
|
+
"0031_routable_views": Effect.gen(function* () {
|
|
1100
|
+
const sql = yield* SqlClient.SqlClient;
|
|
1101
|
+
yield* sql `CREATE VIEW durable.actors_v2 AS
|
|
1102
|
+
SELECT g.tenant_id, g.actor_type, g.actor_id, g.routing_key,
|
|
1103
|
+
g.generation, g.created, g.event_sequence AS last_event_sequence
|
|
1104
|
+
FROM actor_generations g`;
|
|
1105
|
+
yield* sql `CREATE VIEW durable.state_v2 AS
|
|
1106
|
+
SELECT s.tenant_id, s.actor_type, s.actor_id, s.routing_key,
|
|
1107
|
+
s.key, s.value, octet_length(s.value) AS value_bytes
|
|
1108
|
+
FROM actor_state s`;
|
|
1109
|
+
yield* sql `CREATE VIEW durable.receipts_v2 AS
|
|
1110
|
+
SELECT r.tenant_id, r.actor_type, r.actor_id, r.routing_key,
|
|
1111
|
+
r.command_id, r.command, r.caller_key,
|
|
1112
|
+
r.outcome::jsonb ->> '_tag' AS outcome_tag, r.outcome,
|
|
1113
|
+
r.expires_at_ms, to_timestamp(r.expires_at_ms::float8 / 1000) AS expires_at,
|
|
1114
|
+
r.started_at_ms, r.committed_at_ms,
|
|
1115
|
+
to_timestamp(r.committed_at_ms::float8 / 1000) AS committed_at,
|
|
1116
|
+
r.committed_at_ms - r.started_at_ms AS duration_ms
|
|
1117
|
+
FROM actor_receipts r`;
|
|
1118
|
+
yield* sql `CREATE VIEW durable.events_v2 AS
|
|
1119
|
+
SELECT e.tenant_id, e.actor_type, e.actor_id, e.routing_key,
|
|
1120
|
+
e.sequence, e.event, e.command_id, e.value, octet_length(e.value) AS value_bytes,
|
|
1121
|
+
e.emitted_at_ms, to_timestamp(e.emitted_at_ms::float8 / 1000) AS emitted_at,
|
|
1122
|
+
e.payload_version
|
|
1123
|
+
FROM actor_events e`;
|
|
1124
|
+
yield* sql `CREATE VIEW durable.outbox_v2 AS
|
|
1125
|
+
SELECT o.tenant_id, o.actor_type, o.actor_id, o.routing_key,
|
|
1126
|
+
o.intent_id, o.timer_key, o.target_type, o.target_id, o.command, o.payload, o.caller,
|
|
1127
|
+
o.attempts, o.last_error, o.due_at_ms, to_timestamp(o.due_at_ms::float8 / 1000) AS due_at
|
|
1128
|
+
FROM actor_outbox o
|
|
1129
|
+
WHERE o.kind = 'intent'`;
|
|
1130
|
+
yield* sql `CREATE VIEW durable.timers_v2 AS
|
|
1131
|
+
SELECT o.tenant_id, o.actor_type, o.actor_id, o.routing_key,
|
|
1132
|
+
o.timer_key, o.intent_id, o.target_type, o.target_id, o.command, o.payload, o.caller,
|
|
1133
|
+
o.attempts, o.due_at_ms, to_timestamp(o.due_at_ms::float8 / 1000) AS due_at
|
|
1134
|
+
FROM actor_outbox o
|
|
1135
|
+
WHERE o.kind = 'intent' AND o.timer_key IS NOT NULL`;
|
|
1136
|
+
yield* sql `CREATE VIEW durable.jobs_v2 AS
|
|
1137
|
+
SELECT o.tenant_id, o.actor_type, o.actor_id, o.routing_key,
|
|
1138
|
+
o.intent_id AS job_id, o.command AS job, o.payload, o.caller,
|
|
1139
|
+
o.attempts, o.last_error, o.ambiguous,
|
|
1140
|
+
o.due_at_ms, to_timestamp(o.due_at_ms::float8 / 1000) AS due_at,
|
|
1141
|
+
o.payload_version
|
|
1142
|
+
FROM actor_outbox o
|
|
1143
|
+
WHERE o.kind = 'job'`;
|
|
1144
|
+
yield* sql `CREATE VIEW durable.dead_letters_v2 AS
|
|
1145
|
+
SELECT d.tenant_id, d.actor_type, d.actor_id, d.routing_key,
|
|
1146
|
+
d.job_id, d.job, d.payload, d.attempts, d.cause, d.ambiguous,
|
|
1147
|
+
d.dead_at_ms, to_timestamp(d.dead_at_ms::float8 / 1000) AS dead_at,
|
|
1148
|
+
d.payload_version
|
|
1149
|
+
FROM actor_dead_letters d`;
|
|
1150
|
+
yield* sql `CREATE VIEW durable.workflows_v2 AS
|
|
1151
|
+
SELECT w.tenant_id, w.actor_type, w.actor_id, w.routing_key,
|
|
1152
|
+
w.execution_id, w.workflow, w.workflow_key, w.manifest_hash, w.status, w.interrupt,
|
|
1153
|
+
w.caller, w.payload, octet_length(w.payload) AS payload_bytes,
|
|
1154
|
+
w.result, octet_length(w.result) AS result_bytes,
|
|
1155
|
+
w.started_at_ms, to_timestamp(w.started_at_ms::float8 / 1000) AS started_at,
|
|
1156
|
+
w.finished_at_ms, to_timestamp(w.finished_at_ms::float8 / 1000) AS finished_at
|
|
1157
|
+
FROM actor_workflow_executions w`;
|
|
1158
|
+
yield* sql `CREATE VIEW durable.workflow_steps_v2 AS
|
|
1159
|
+
SELECT s.tenant_id, s.actor_type, s.actor_id, s.routing_key,
|
|
1160
|
+
s.execution_id, s.step, s.attempt, s.kind, s.exit, s.wait_event, s.version,
|
|
1161
|
+
s.due_at_ms, to_timestamp(s.due_at_ms::float8 / 1000) AS due_at,
|
|
1162
|
+
s.started_at_ms, to_timestamp(s.started_at_ms::float8 / 1000) AS started_at,
|
|
1163
|
+
s.settled_at_ms, to_timestamp(s.settled_at_ms::float8 / 1000) AS settled_at
|
|
1164
|
+
FROM actor_workflow_step s`;
|
|
1165
|
+
yield* sql `CREATE VIEW durable.contents_v2 AS
|
|
1166
|
+
SELECT c.tenant_id, c.routing_key, c.hash, c.size,
|
|
1167
|
+
c.granted_until_ms, to_timestamp(c.granted_until_ms::float8 / 1000) AS granted_until
|
|
1168
|
+
FROM tenant_contents c`;
|
|
1169
|
+
yield* sql `CREATE VIEW durable.content_sweeps_v2 AS
|
|
1170
|
+
SELECT s.tenant_id, s.routing_key,
|
|
1171
|
+
s.swept_at_ms, to_timestamp(s.swept_at_ms::float8 / 1000) AS swept_at
|
|
1172
|
+
FROM tenant_content_sweeps s`;
|
|
1173
|
+
yield* sql `CREATE VIEW durable.content_refs_v2 AS
|
|
1174
|
+
SELECT r.tenant_id, r.actor_type, r.actor_id, r.routing_key,
|
|
1175
|
+
r.blob, r.name, r.hash, r.size
|
|
1176
|
+
FROM actor_content_refs r`;
|
|
1177
|
+
yield* sql `CREATE VIEW durable.operator_audit_v2 AS
|
|
1178
|
+
SELECT a.tenant_id, a.actor_type, a.actor_id, a.routing_key, a.audit_id,
|
|
1179
|
+
a.operator, a.action, a.target, a.capability, a.reason, a.outcome,
|
|
1180
|
+
a.at_ms, to_timestamp(a.at_ms::float8 / 1000) AS at
|
|
1181
|
+
FROM actor_operator_audit a`;
|
|
1182
|
+
yield* sql `CREATE VIEW durable.placements_v2 AS
|
|
1183
|
+
SELECT p.actor_type, p.placement, p.parent_type
|
|
1184
|
+
FROM actor_placements p`;
|
|
1185
|
+
yield* sql.unsafe(`REVOKE INSERT, UPDATE, DELETE, TRUNCATE ON ${ROUTABLE_VIEWS.map((view) => `durable.${view}`).join(", ")} FROM CURRENT_USER`);
|
|
1186
|
+
const present = yield* sql `
|
|
1187
|
+
SELECT relname AS view FROM pg_class
|
|
1188
|
+
WHERE relnamespace = 'durable'::regnamespace AND relkind = 'v'`;
|
|
1189
|
+
const first = FIRST_VIEWS.filter(([view]) => present.some((row) => row.view === view));
|
|
1190
|
+
const rows = [...first, ...ROUTABLE_VIEWS.map((view) => [view, 1]), ["views", 1]];
|
|
1191
|
+
yield* sql.unsafe(`CREATE OR REPLACE VIEW durable.views AS
|
|
1192
|
+
SELECT view_name, version FROM (VALUES
|
|
1193
|
+
${rows.map(([view, version]) => `('${view}', ${version})`).join(", ")}
|
|
1194
|
+
) AS v(view_name, version)`);
|
|
1195
|
+
}),
|
|
1196
|
+
/**
|
|
1197
|
+
* An authority-placed type keeps every routing key in the one bucket a split topology leaves
|
|
1198
|
+
* on the authoritative shard, so its turns reach the tables the database does not route on
|
|
1199
|
+
* the shard that holds them.
|
|
1200
|
+
*/
|
|
1201
|
+
"0032_authority_placement": Effect.gen(function* () {
|
|
1202
|
+
const sql = yield* SqlClient.SqlClient;
|
|
1203
|
+
yield* sql `ALTER TABLE actor_placements DROP CONSTRAINT actor_placements_placement_check,
|
|
1204
|
+
ADD CONSTRAINT actor_placements_placement_check
|
|
1205
|
+
CHECK (placement IN ('tenant', 'actor', 'parent', 'authority'))`;
|
|
1206
|
+
}),
|
|
1207
|
+
/** Retires the single-table inspection variants without rewriting the applied migration that created them. */
|
|
1208
|
+
"0033_joined_inspection": Effect.gen(function* () {
|
|
1209
|
+
const sql = yield* SqlClient.SqlClient;
|
|
1210
|
+
yield* sql.unsafe(`DROP VIEW ${ROUTABLE_VIEWS.map((view) => `durable.${view}`).join(", ")}`);
|
|
1211
|
+
yield* sql.unsafe(`CREATE OR REPLACE VIEW durable.views AS
|
|
1212
|
+
SELECT view_name, version FROM (VALUES
|
|
1213
|
+
${[...FIRST_VIEWS, ["views", 1]].map(([view, version]) => `('${view}', ${version})`).join(", ")}
|
|
1214
|
+
) AS v(view_name, version)`);
|
|
1215
|
+
}),
|
|
973
1216
|
};
|
|
974
1217
|
/**
|
|
975
1218
|
* Runs `record` like `Migrator`, but first refuses a database where a
|
|
@@ -1002,16 +1245,9 @@ export const migrator = (record) => {
|
|
|
1002
1245
|
});
|
|
1003
1246
|
const transactional = refuseSkipped.pipe(Effect.andThen(run), Effect.tap(() => refuseSkipped));
|
|
1004
1247
|
return Effect.gen(function* () {
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
? nekiMigrator({
|
|
1008
|
-
record: Object.fromEntries(Object.entries(record).map(([key, effect]) => [key, Effect.orDie(effect)])),
|
|
1009
|
-
refuseSkipped,
|
|
1010
|
-
})
|
|
1248
|
+
return yield* Option.isSome(yield* Effect.serviceOption(PgClient.PgClient))
|
|
1249
|
+
? withMigrationCoordination(transactional)
|
|
1011
1250
|
: transactional;
|
|
1012
|
-
return yield* neki || Option.isSome(yield* Effect.serviceOption(PgClient.PgClient))
|
|
1013
|
-
? withMigrationCoordination(selected)
|
|
1014
|
-
: selected;
|
|
1015
1251
|
});
|
|
1016
1252
|
};
|
|
1017
1253
|
/** Applies every framework migration not yet recorded in `actor_migrations`, refusing a database that skipped one. */
|
|
@@ -28,7 +28,10 @@ export declare const replicaLayer: (options: PgClient.PgPoolConfig | undefined)
|
|
|
28
28
|
* is built on that client.
|
|
29
29
|
*/
|
|
30
30
|
export declare const QueryPool: Context.Reference<SqlClient.SqlClient | undefined>;
|
|
31
|
-
/**
|
|
31
|
+
/**
|
|
32
|
+
* Provides `QueryPool` as a bounded, first-come, first-served pool for
|
|
33
|
+
* `options`, independent of the off-turn client's checkouts.
|
|
34
|
+
*/
|
|
32
35
|
export declare const queryPoolLayer: (options: PgClient.PgPoolConfig) => Layer.Layer<never, import("effect/sql/SqlError").SqlError, never>;
|
|
33
36
|
/**
|
|
34
37
|
* Whether the replica has replayed WAL through `version`. A server not in
|
|
@@ -34,7 +34,10 @@ export const replicaLayer = (options) => Layer.effect(ReadReplica, Effect.gen(fu
|
|
|
34
34
|
* is built on that client.
|
|
35
35
|
*/
|
|
36
36
|
export const QueryPool = Context.Reference("@rikalabs/akter/runtime/database/replica/QueryPool", { defaultValue: () => undefined });
|
|
37
|
-
/**
|
|
37
|
+
/**
|
|
38
|
+
* Provides `QueryPool` as a bounded, first-come, first-served pool for
|
|
39
|
+
* `options`, independent of the off-turn client's checkouts.
|
|
40
|
+
*/
|
|
38
41
|
export const queryPoolLayer = (options) => Layer.effect(QueryPool, boundedPool(options)).pipe(Layer.provide(Reactivity.layer));
|
|
39
42
|
/**
|
|
40
43
|
* Whether the replica has replayed WAL through `version`. A server not in
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { SqlClient } from "effect/sql";
|
|
3
|
+
import type { SqlError } from "effect/sql";
|
|
4
|
+
/**
|
|
5
|
+
* Runs an application's own schema setup on the ambient `SqlClient` while
|
|
6
|
+
* holding advisory lock `lock`, so processes starting together apply it one
|
|
7
|
+
* at a time. The lock and every statement share one transaction, so a failed
|
|
8
|
+
* setup rolls back together and releases its lock.
|
|
9
|
+
*/
|
|
10
|
+
export declare const schemaChange: {
|
|
11
|
+
(lock: number): <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E | SqlError.SqlError, R | SqlClient.SqlClient>;
|
|
12
|
+
<A, E, R>(effect: Effect.Effect<A, E, R>, lock: number): Effect.Effect<A, E | SqlError.SqlError, R | SqlClient.SqlClient>;
|
|
13
|
+
};
|