@electric-ax/agents-server 0.3.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/LICENSE +177 -0
- package/dist/chunk-Cl8Af3a2.js +11 -0
- package/dist/entrypoint.js +7319 -0
- package/dist/index.cjs +7090 -0
- package/dist/index.d.cts +4262 -0
- package/dist/index.d.ts +4263 -0
- package/dist/index.js +7053 -0
- package/drizzle/0000_baseline.sql +97 -0
- package/drizzle/0001_entity_tags_and_bridges.sql +45 -0
- package/drizzle/0002_tag_outbox_hardening.sql +14 -0
- package/drizzle/0003_entity_manifest_sources.sql +11 -0
- package/drizzle/0004_tenant_scoping.sql +139 -0
- package/drizzle/0005_pull_wake_control_plane.sql +156 -0
- package/drizzle/meta/0000_snapshot.json +593 -0
- package/drizzle/meta/_journal.json +48 -0
- package/package.json +89 -0
- package/src/authenticated-user-format.ts +17 -0
- package/src/claim-write-token-store.ts +74 -0
- package/src/db/index.ts +53 -0
- package/src/db/schema.ts +490 -0
- package/src/dev-asserted-auth.ts +46 -0
- package/src/dispatch-policy-schema.ts +52 -0
- package/src/electric-agents/adapter-types.ts +70 -0
- package/src/electric-agents/default-entity-schemas.ts +1 -0
- package/src/electric-agents/schema-validator.ts +143 -0
- package/src/electric-agents-http.ts +46 -0
- package/src/electric-agents-types.ts +335 -0
- package/src/entity-bridge-manager.ts +694 -0
- package/src/entity-manager.ts +2601 -0
- package/src/entity-projector.ts +765 -0
- package/src/entity-registry.ts +1162 -0
- package/src/entrypoint-lib.ts +295 -0
- package/src/entrypoint.ts +11 -0
- package/src/host.ts +323 -0
- package/src/index.ts +49 -0
- package/src/manifest-side-effects.ts +183 -0
- package/src/routing/agent-ui-router.ts +81 -0
- package/src/routing/context.ts +35 -0
- package/src/routing/cron-router.ts +45 -0
- package/src/routing/dispatch-policy.ts +248 -0
- package/src/routing/durable-streams-router.ts +407 -0
- package/src/routing/durable-streams-routing-adapter.ts +96 -0
- package/src/routing/electric-proxy-router.ts +61 -0
- package/src/routing/entities-router.ts +484 -0
- package/src/routing/entity-types-router.ts +229 -0
- package/src/routing/global-router.ts +33 -0
- package/src/routing/hooks.ts +123 -0
- package/src/routing/internal-router.ts +741 -0
- package/src/routing/oss-server-router.ts +56 -0
- package/src/routing/runners-router.ts +416 -0
- package/src/routing/schema.ts +141 -0
- package/src/routing/stream-append.ts +196 -0
- package/src/routing/tenant-stream-paths.ts +26 -0
- package/src/runtime-registry.ts +49 -0
- package/src/runtime.ts +537 -0
- package/src/scheduler.ts +788 -0
- package/src/schema-validation.ts +15 -0
- package/src/server.ts +374 -0
- package/src/standalone-runtime.ts +188 -0
- package/src/stream-client.ts +842 -0
- package/src/tag-stream-outbox-drainer.ts +188 -0
- package/src/tenant.ts +25 -0
- package/src/tracing.ts +57 -0
- package/src/utils/electric-url.ts +15 -0
- package/src/utils/log.ts +95 -0
- package/src/utils/server-utils.ts +245 -0
- package/src/utils/webhook-url.ts +33 -0
- package/src/wake-registry.ts +946 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
CREATE TABLE "consumer_callbacks" (
|
|
2
|
+
"consumer_id" text PRIMARY KEY NOT NULL,
|
|
3
|
+
"callback_url" text NOT NULL,
|
|
4
|
+
"primary_stream" text,
|
|
5
|
+
"created_at" timestamp with time zone DEFAULT now() NOT NULL
|
|
6
|
+
);
|
|
7
|
+
--> statement-breakpoint
|
|
8
|
+
CREATE TABLE "entities" (
|
|
9
|
+
"url" text PRIMARY KEY NOT NULL,
|
|
10
|
+
"type" text NOT NULL,
|
|
11
|
+
"status" text DEFAULT 'idle' NOT NULL,
|
|
12
|
+
"subscription_id" text NOT NULL,
|
|
13
|
+
"write_token" text NOT NULL,
|
|
14
|
+
"metadata" jsonb DEFAULT '{}'::jsonb,
|
|
15
|
+
"spawn_args" jsonb DEFAULT '{}'::jsonb,
|
|
16
|
+
"parent" text,
|
|
17
|
+
"type_revision" integer,
|
|
18
|
+
"inbox_schemas" jsonb,
|
|
19
|
+
"state_schemas" jsonb,
|
|
20
|
+
"metadata_schema" jsonb,
|
|
21
|
+
"created_at" bigint NOT NULL,
|
|
22
|
+
"updated_at" bigint NOT NULL,
|
|
23
|
+
CONSTRAINT "chk_entities_status" CHECK ("entities"."status" IN ('spawning', 'running', 'idle', 'stopped'))
|
|
24
|
+
);
|
|
25
|
+
--> statement-breakpoint
|
|
26
|
+
CREATE TABLE "entity_types" (
|
|
27
|
+
"name" text PRIMARY KEY NOT NULL,
|
|
28
|
+
"description" text NOT NULL,
|
|
29
|
+
"creation_schema" jsonb,
|
|
30
|
+
"inbox_schemas" jsonb,
|
|
31
|
+
"state_schemas" jsonb,
|
|
32
|
+
"metadata_schema" jsonb,
|
|
33
|
+
"serve_endpoint" text,
|
|
34
|
+
"revision" integer DEFAULT 1 NOT NULL,
|
|
35
|
+
"created_at" text NOT NULL,
|
|
36
|
+
"updated_at" text NOT NULL
|
|
37
|
+
);
|
|
38
|
+
--> statement-breakpoint
|
|
39
|
+
CREATE TABLE "scheduled_tasks" (
|
|
40
|
+
"id" bigserial PRIMARY KEY NOT NULL,
|
|
41
|
+
"kind" text NOT NULL,
|
|
42
|
+
"payload" jsonb NOT NULL,
|
|
43
|
+
"fire_at" timestamp with time zone NOT NULL,
|
|
44
|
+
"cron_expression" text,
|
|
45
|
+
"cron_timezone" text,
|
|
46
|
+
"cron_tick_number" integer,
|
|
47
|
+
"owner_entity_url" text,
|
|
48
|
+
"manifest_key" text,
|
|
49
|
+
"claimed_by" text,
|
|
50
|
+
"claimed_at" timestamp with time zone,
|
|
51
|
+
"completed_at" timestamp with time zone,
|
|
52
|
+
"last_error" text,
|
|
53
|
+
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
|
54
|
+
CONSTRAINT "uq_cron_tick" UNIQUE("cron_expression","cron_timezone","cron_tick_number"),
|
|
55
|
+
CONSTRAINT "chk_scheduled_tasks_kind" CHECK ("scheduled_tasks"."kind" IN ('delayed_send', 'cron_tick'))
|
|
56
|
+
);
|
|
57
|
+
--> statement-breakpoint
|
|
58
|
+
CREATE TABLE "subscription_webhooks" (
|
|
59
|
+
"subscription_id" text PRIMARY KEY NOT NULL,
|
|
60
|
+
"webhook_url" text NOT NULL,
|
|
61
|
+
"created_at" timestamp with time zone DEFAULT now() NOT NULL
|
|
62
|
+
);
|
|
63
|
+
--> statement-breakpoint
|
|
64
|
+
CREATE TABLE "wake_registrations" (
|
|
65
|
+
"id" serial PRIMARY KEY NOT NULL,
|
|
66
|
+
"subscriber_url" text NOT NULL,
|
|
67
|
+
"source_url" text NOT NULL,
|
|
68
|
+
"condition" jsonb NOT NULL,
|
|
69
|
+
"debounce_ms" integer DEFAULT 0 NOT NULL,
|
|
70
|
+
"timeout_ms" integer DEFAULT 0 NOT NULL,
|
|
71
|
+
"one_shot" boolean DEFAULT false NOT NULL,
|
|
72
|
+
"timeout_consumed" boolean DEFAULT false NOT NULL,
|
|
73
|
+
"include_response" boolean DEFAULT true NOT NULL,
|
|
74
|
+
"manifest_key" text,
|
|
75
|
+
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
|
76
|
+
CONSTRAINT "uq_wake_registration" UNIQUE("subscriber_url","source_url","one_shot","debounce_ms","timeout_ms","condition","manifest_key")
|
|
77
|
+
);
|
|
78
|
+
--> statement-breakpoint
|
|
79
|
+
CREATE OR REPLACE FUNCTION notify_scheduled_tasks_wake() RETURNS trigger AS $$
|
|
80
|
+
BEGIN
|
|
81
|
+
PERFORM pg_notify('scheduled_tasks_wake', '');
|
|
82
|
+
RETURN NEW;
|
|
83
|
+
END;
|
|
84
|
+
$$ LANGUAGE plpgsql;
|
|
85
|
+
--> statement-breakpoint
|
|
86
|
+
CREATE TRIGGER scheduled_tasks_notify
|
|
87
|
+
AFTER INSERT ON "scheduled_tasks"
|
|
88
|
+
FOR EACH ROW
|
|
89
|
+
EXECUTE FUNCTION notify_scheduled_tasks_wake();
|
|
90
|
+
--> statement-breakpoint
|
|
91
|
+
CREATE INDEX "idx_entities_type" ON "entities" USING btree ("type");--> statement-breakpoint
|
|
92
|
+
CREATE INDEX "idx_entities_status" ON "entities" USING btree ("status");--> statement-breakpoint
|
|
93
|
+
CREATE INDEX "idx_entities_parent" ON "entities" USING btree ("parent");--> statement-breakpoint
|
|
94
|
+
CREATE INDEX "idx_scheduled_tasks_fire_ready" ON "scheduled_tasks" USING btree ("fire_at") WHERE "scheduled_tasks"."completed_at" IS NULL AND "scheduled_tasks"."claimed_at" IS NULL;--> statement-breakpoint
|
|
95
|
+
CREATE INDEX "idx_scheduled_tasks_manifest_pending" ON "scheduled_tasks" USING btree ("owner_entity_url","manifest_key") WHERE "scheduled_tasks"."kind" = 'delayed_send' AND "scheduled_tasks"."completed_at" IS NULL AND "scheduled_tasks"."manifest_key" IS NOT NULL;--> statement-breakpoint
|
|
96
|
+
CREATE INDEX "idx_scheduled_tasks_stale_claims" ON "scheduled_tasks" USING btree ("claimed_at") WHERE "scheduled_tasks"."completed_at" IS NULL AND "scheduled_tasks"."claimed_at" IS NOT NULL;--> statement-breakpoint
|
|
97
|
+
CREATE INDEX "idx_wake_source_url" ON "wake_registrations" USING btree ("source_url");
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
-- tags_index is a text[] shadow of tags jsonb. Electric shape `where` supports
|
|
2
|
+
-- `@>` on text[] but not on jsonb, so membership queries for
|
|
3
|
+
-- observe(entities({ tags })) must scan tags_index.
|
|
4
|
+
ALTER TABLE entities
|
|
5
|
+
DROP COLUMN metadata,
|
|
6
|
+
ADD COLUMN tags jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
7
|
+
ADD COLUMN tags_index text[] NOT NULL DEFAULT '{}'::text[];
|
|
8
|
+
|
|
9
|
+
CREATE INDEX entities_tags_index_gin ON entities USING gin (tags_index);
|
|
10
|
+
|
|
11
|
+
-- REPLICA IDENTITY FULL is required so Electric's logical replication emits
|
|
12
|
+
-- full-row payloads on UPDATE/DELETE. Without it, shape consumers can't
|
|
13
|
+
-- compute diffs and bridge reconcile breaks.
|
|
14
|
+
ALTER TABLE entities REPLICA IDENTITY FULL;
|
|
15
|
+
|
|
16
|
+
CREATE TABLE entity_bridges (
|
|
17
|
+
source_ref text PRIMARY KEY,
|
|
18
|
+
tags jsonb NOT NULL,
|
|
19
|
+
stream_url text NOT NULL UNIQUE,
|
|
20
|
+
shape_handle text,
|
|
21
|
+
shape_offset text,
|
|
22
|
+
last_observer_activity_at timestamptz NOT NULL DEFAULT now(),
|
|
23
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
24
|
+
updated_at timestamptz NOT NULL DEFAULT now()
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
CREATE TABLE tag_stream_outbox (
|
|
28
|
+
id bigserial PRIMARY KEY,
|
|
29
|
+
entity_url text NOT NULL,
|
|
30
|
+
collection text NOT NULL,
|
|
31
|
+
op text NOT NULL,
|
|
32
|
+
key text NOT NULL,
|
|
33
|
+
row_data jsonb,
|
|
34
|
+
claimed_by text,
|
|
35
|
+
claimed_at timestamptz,
|
|
36
|
+
created_at timestamptz NOT NULL DEFAULT now()
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
CREATE INDEX idx_tag_stream_outbox_unclaimed
|
|
40
|
+
ON tag_stream_outbox (created_at)
|
|
41
|
+
WHERE claimed_at IS NULL;
|
|
42
|
+
|
|
43
|
+
CREATE INDEX idx_tag_stream_outbox_stale_claims
|
|
44
|
+
ON tag_stream_outbox (claimed_at)
|
|
45
|
+
WHERE claimed_at IS NOT NULL;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
ALTER TABLE tag_stream_outbox
|
|
2
|
+
ADD COLUMN attempt_count integer NOT NULL DEFAULT 0,
|
|
3
|
+
ADD COLUMN last_error text,
|
|
4
|
+
ADD COLUMN dead_lettered_at timestamptz;
|
|
5
|
+
|
|
6
|
+
DROP INDEX IF EXISTS idx_tag_stream_outbox_unclaimed;
|
|
7
|
+
CREATE INDEX idx_tag_stream_outbox_unclaimed
|
|
8
|
+
ON tag_stream_outbox (created_at)
|
|
9
|
+
WHERE claimed_at IS NULL AND dead_lettered_at IS NULL;
|
|
10
|
+
|
|
11
|
+
DROP INDEX IF EXISTS idx_tag_stream_outbox_stale_claims;
|
|
12
|
+
CREATE INDEX idx_tag_stream_outbox_stale_claims
|
|
13
|
+
ON tag_stream_outbox (claimed_at)
|
|
14
|
+
WHERE claimed_at IS NOT NULL AND dead_lettered_at IS NULL;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
CREATE TABLE entity_manifest_sources (
|
|
2
|
+
owner_entity_url text NOT NULL,
|
|
3
|
+
manifest_key text NOT NULL,
|
|
4
|
+
source_ref text NOT NULL,
|
|
5
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
6
|
+
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
7
|
+
CONSTRAINT uq_entity_manifest_source UNIQUE (owner_entity_url, manifest_key)
|
|
8
|
+
);
|
|
9
|
+
|
|
10
|
+
CREATE INDEX idx_entity_manifest_sources_source_ref
|
|
11
|
+
ON entity_manifest_sources (source_ref);
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
ALTER TABLE entity_types
|
|
2
|
+
ADD COLUMN tenant_id text NOT NULL DEFAULT 'default';
|
|
3
|
+
--> statement-breakpoint
|
|
4
|
+
ALTER TABLE entities
|
|
5
|
+
ADD COLUMN tenant_id text NOT NULL DEFAULT 'default';
|
|
6
|
+
--> statement-breakpoint
|
|
7
|
+
ALTER TABLE wake_registrations
|
|
8
|
+
ADD COLUMN tenant_id text NOT NULL DEFAULT 'default';
|
|
9
|
+
--> statement-breakpoint
|
|
10
|
+
ALTER TABLE subscription_webhooks
|
|
11
|
+
ADD COLUMN tenant_id text NOT NULL DEFAULT 'default';
|
|
12
|
+
--> statement-breakpoint
|
|
13
|
+
ALTER TABLE consumer_callbacks
|
|
14
|
+
ADD COLUMN tenant_id text NOT NULL DEFAULT 'default';
|
|
15
|
+
--> statement-breakpoint
|
|
16
|
+
ALTER TABLE scheduled_tasks
|
|
17
|
+
ADD COLUMN tenant_id text NOT NULL DEFAULT 'default';
|
|
18
|
+
--> statement-breakpoint
|
|
19
|
+
ALTER TABLE entity_bridges
|
|
20
|
+
ADD COLUMN tenant_id text NOT NULL DEFAULT 'default';
|
|
21
|
+
--> statement-breakpoint
|
|
22
|
+
ALTER TABLE entity_manifest_sources
|
|
23
|
+
ADD COLUMN tenant_id text NOT NULL DEFAULT 'default';
|
|
24
|
+
--> statement-breakpoint
|
|
25
|
+
ALTER TABLE tag_stream_outbox
|
|
26
|
+
ADD COLUMN tenant_id text NOT NULL DEFAULT 'default';
|
|
27
|
+
--> statement-breakpoint
|
|
28
|
+
ALTER TABLE entity_types
|
|
29
|
+
DROP CONSTRAINT entity_types_pkey,
|
|
30
|
+
ADD CONSTRAINT entity_types_pkey PRIMARY KEY (tenant_id, name);
|
|
31
|
+
--> statement-breakpoint
|
|
32
|
+
ALTER TABLE entities
|
|
33
|
+
DROP CONSTRAINT entities_pkey,
|
|
34
|
+
ADD CONSTRAINT entities_pkey PRIMARY KEY (tenant_id, url);
|
|
35
|
+
--> statement-breakpoint
|
|
36
|
+
ALTER TABLE subscription_webhooks
|
|
37
|
+
DROP CONSTRAINT subscription_webhooks_pkey,
|
|
38
|
+
ADD CONSTRAINT subscription_webhooks_pkey PRIMARY KEY (tenant_id, subscription_id);
|
|
39
|
+
--> statement-breakpoint
|
|
40
|
+
ALTER TABLE consumer_callbacks
|
|
41
|
+
DROP CONSTRAINT consumer_callbacks_pkey,
|
|
42
|
+
ADD CONSTRAINT consumer_callbacks_pkey PRIMARY KEY (tenant_id, consumer_id);
|
|
43
|
+
--> statement-breakpoint
|
|
44
|
+
ALTER TABLE entity_bridges
|
|
45
|
+
DROP CONSTRAINT entity_bridges_pkey,
|
|
46
|
+
DROP CONSTRAINT IF EXISTS entity_bridges_stream_url_unique,
|
|
47
|
+
DROP CONSTRAINT IF EXISTS entity_bridges_stream_url_key,
|
|
48
|
+
ADD CONSTRAINT entity_bridges_pkey PRIMARY KEY (tenant_id, source_ref),
|
|
49
|
+
ADD CONSTRAINT uq_entity_bridges_stream_url UNIQUE (tenant_id, stream_url);
|
|
50
|
+
--> statement-breakpoint
|
|
51
|
+
ALTER TABLE wake_registrations
|
|
52
|
+
DROP CONSTRAINT uq_wake_registration,
|
|
53
|
+
ADD CONSTRAINT uq_wake_registration UNIQUE (
|
|
54
|
+
tenant_id,
|
|
55
|
+
subscriber_url,
|
|
56
|
+
source_url,
|
|
57
|
+
one_shot,
|
|
58
|
+
debounce_ms,
|
|
59
|
+
timeout_ms,
|
|
60
|
+
condition,
|
|
61
|
+
manifest_key
|
|
62
|
+
);
|
|
63
|
+
--> statement-breakpoint
|
|
64
|
+
ALTER TABLE scheduled_tasks
|
|
65
|
+
DROP CONSTRAINT uq_cron_tick,
|
|
66
|
+
ADD CONSTRAINT uq_cron_tick UNIQUE (
|
|
67
|
+
tenant_id,
|
|
68
|
+
cron_expression,
|
|
69
|
+
cron_timezone,
|
|
70
|
+
cron_tick_number
|
|
71
|
+
);
|
|
72
|
+
--> statement-breakpoint
|
|
73
|
+
ALTER TABLE entity_manifest_sources
|
|
74
|
+
DROP CONSTRAINT uq_entity_manifest_source,
|
|
75
|
+
ADD CONSTRAINT uq_entity_manifest_source UNIQUE (
|
|
76
|
+
tenant_id,
|
|
77
|
+
owner_entity_url,
|
|
78
|
+
manifest_key
|
|
79
|
+
);
|
|
80
|
+
--> statement-breakpoint
|
|
81
|
+
DROP INDEX IF EXISTS idx_entities_type;
|
|
82
|
+
--> statement-breakpoint
|
|
83
|
+
DROP INDEX IF EXISTS idx_entities_status;
|
|
84
|
+
--> statement-breakpoint
|
|
85
|
+
DROP INDEX IF EXISTS idx_entities_parent;
|
|
86
|
+
--> statement-breakpoint
|
|
87
|
+
DROP INDEX IF EXISTS idx_wake_source_url;
|
|
88
|
+
--> statement-breakpoint
|
|
89
|
+
DROP INDEX IF EXISTS idx_scheduled_tasks_fire_ready;
|
|
90
|
+
--> statement-breakpoint
|
|
91
|
+
DROP INDEX IF EXISTS idx_scheduled_tasks_manifest_pending;
|
|
92
|
+
--> statement-breakpoint
|
|
93
|
+
DROP INDEX IF EXISTS idx_scheduled_tasks_stale_claims;
|
|
94
|
+
--> statement-breakpoint
|
|
95
|
+
DROP INDEX IF EXISTS idx_entity_manifest_sources_source_ref;
|
|
96
|
+
--> statement-breakpoint
|
|
97
|
+
DROP INDEX IF EXISTS idx_tag_stream_outbox_unclaimed;
|
|
98
|
+
--> statement-breakpoint
|
|
99
|
+
DROP INDEX IF EXISTS idx_tag_stream_outbox_stale_claims;
|
|
100
|
+
--> statement-breakpoint
|
|
101
|
+
CREATE INDEX idx_entities_type
|
|
102
|
+
ON entities (tenant_id, type);
|
|
103
|
+
--> statement-breakpoint
|
|
104
|
+
CREATE INDEX idx_entities_status
|
|
105
|
+
ON entities (tenant_id, status);
|
|
106
|
+
--> statement-breakpoint
|
|
107
|
+
CREATE INDEX idx_entities_parent
|
|
108
|
+
ON entities (tenant_id, parent);
|
|
109
|
+
--> statement-breakpoint
|
|
110
|
+
CREATE INDEX idx_wake_source_url
|
|
111
|
+
ON wake_registrations (tenant_id, source_url);
|
|
112
|
+
--> statement-breakpoint
|
|
113
|
+
CREATE INDEX idx_consumer_callbacks_primary_stream
|
|
114
|
+
ON consumer_callbacks (tenant_id, primary_stream);
|
|
115
|
+
--> statement-breakpoint
|
|
116
|
+
CREATE INDEX idx_scheduled_tasks_fire_ready
|
|
117
|
+
ON scheduled_tasks (tenant_id, fire_at)
|
|
118
|
+
WHERE completed_at IS NULL AND claimed_at IS NULL;
|
|
119
|
+
--> statement-breakpoint
|
|
120
|
+
CREATE INDEX idx_scheduled_tasks_manifest_pending
|
|
121
|
+
ON scheduled_tasks (tenant_id, owner_entity_url, manifest_key)
|
|
122
|
+
WHERE kind = 'delayed_send'
|
|
123
|
+
AND completed_at IS NULL
|
|
124
|
+
AND manifest_key IS NOT NULL;
|
|
125
|
+
--> statement-breakpoint
|
|
126
|
+
CREATE INDEX idx_scheduled_tasks_stale_claims
|
|
127
|
+
ON scheduled_tasks (tenant_id, claimed_at)
|
|
128
|
+
WHERE completed_at IS NULL AND claimed_at IS NOT NULL;
|
|
129
|
+
--> statement-breakpoint
|
|
130
|
+
CREATE INDEX idx_entity_manifest_sources_source_ref
|
|
131
|
+
ON entity_manifest_sources (tenant_id, source_ref);
|
|
132
|
+
--> statement-breakpoint
|
|
133
|
+
CREATE INDEX idx_tag_stream_outbox_unclaimed
|
|
134
|
+
ON tag_stream_outbox (tenant_id, created_at)
|
|
135
|
+
WHERE claimed_at IS NULL AND dead_lettered_at IS NULL;
|
|
136
|
+
--> statement-breakpoint
|
|
137
|
+
CREATE INDEX idx_tag_stream_outbox_stale_claims
|
|
138
|
+
ON tag_stream_outbox (tenant_id, claimed_at)
|
|
139
|
+
WHERE claimed_at IS NOT NULL AND dead_lettered_at IS NULL;
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
ALTER TABLE entity_types
|
|
2
|
+
ADD COLUMN default_dispatch_policy jsonb;
|
|
3
|
+
--> statement-breakpoint
|
|
4
|
+
ALTER TABLE entities
|
|
5
|
+
ADD COLUMN dispatch_policy jsonb;
|
|
6
|
+
--> statement-breakpoint
|
|
7
|
+
CREATE TABLE users (
|
|
8
|
+
tenant_id text NOT NULL DEFAULT 'default',
|
|
9
|
+
id text NOT NULL,
|
|
10
|
+
display_name text,
|
|
11
|
+
email text,
|
|
12
|
+
avatar_url text,
|
|
13
|
+
auth_provider text,
|
|
14
|
+
auth_subject text,
|
|
15
|
+
profile jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
16
|
+
metadata jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
17
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
18
|
+
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
19
|
+
PRIMARY KEY (tenant_id, id)
|
|
20
|
+
);
|
|
21
|
+
--> statement-breakpoint
|
|
22
|
+
CREATE INDEX idx_users_email ON users (tenant_id, email);
|
|
23
|
+
--> statement-breakpoint
|
|
24
|
+
CREATE INDEX idx_users_auth_identity
|
|
25
|
+
ON users (tenant_id, auth_provider, auth_subject);
|
|
26
|
+
--> statement-breakpoint
|
|
27
|
+
CREATE TABLE runners (
|
|
28
|
+
tenant_id text NOT NULL DEFAULT 'default',
|
|
29
|
+
id text NOT NULL,
|
|
30
|
+
owner_user_id text NOT NULL,
|
|
31
|
+
label text NOT NULL,
|
|
32
|
+
kind text NOT NULL DEFAULT 'local',
|
|
33
|
+
admin_status text NOT NULL DEFAULT 'enabled',
|
|
34
|
+
wake_stream text NOT NULL,
|
|
35
|
+
wake_stream_offset text,
|
|
36
|
+
last_seen_at timestamptz,
|
|
37
|
+
liveness_lease_expires_at timestamptz,
|
|
38
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
39
|
+
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
40
|
+
PRIMARY KEY (tenant_id, id),
|
|
41
|
+
CONSTRAINT uq_runners_wake_stream UNIQUE (tenant_id, wake_stream),
|
|
42
|
+
CONSTRAINT chk_runners_kind CHECK (kind IN ('local', 'cloud-worker', 'sandbox', 'ci', 'server')),
|
|
43
|
+
CONSTRAINT chk_runners_admin_status CHECK (admin_status IN ('enabled', 'disabled'))
|
|
44
|
+
);
|
|
45
|
+
--> statement-breakpoint
|
|
46
|
+
CREATE INDEX idx_runners_owner_user_id ON runners (tenant_id, owner_user_id);
|
|
47
|
+
--> statement-breakpoint
|
|
48
|
+
CREATE INDEX idx_runners_admin_status ON runners (tenant_id, admin_status);
|
|
49
|
+
--> statement-breakpoint
|
|
50
|
+
CREATE INDEX idx_runners_liveness_lease_expires_at
|
|
51
|
+
ON runners (tenant_id, liveness_lease_expires_at);
|
|
52
|
+
--> statement-breakpoint
|
|
53
|
+
CREATE TABLE entity_dispatch_state (
|
|
54
|
+
tenant_id text NOT NULL DEFAULT 'default',
|
|
55
|
+
entity_url text NOT NULL,
|
|
56
|
+
pending_source_streams jsonb NOT NULL DEFAULT '[]'::jsonb,
|
|
57
|
+
pending_reason text,
|
|
58
|
+
pending_since timestamptz,
|
|
59
|
+
outstanding_wake_id text,
|
|
60
|
+
outstanding_wake_target jsonb,
|
|
61
|
+
outstanding_wake_created_at timestamptz,
|
|
62
|
+
active_consumer_id text,
|
|
63
|
+
active_runner_id text,
|
|
64
|
+
active_epoch integer,
|
|
65
|
+
active_claimed_at timestamptz,
|
|
66
|
+
active_lease_expires_at timestamptz,
|
|
67
|
+
last_wake_id text,
|
|
68
|
+
last_claimed_at timestamptz,
|
|
69
|
+
last_released_at timestamptz,
|
|
70
|
+
last_completed_at timestamptz,
|
|
71
|
+
last_error text,
|
|
72
|
+
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
73
|
+
PRIMARY KEY (tenant_id, entity_url)
|
|
74
|
+
);
|
|
75
|
+
--> statement-breakpoint
|
|
76
|
+
CREATE INDEX idx_entity_dispatch_state_active_runner
|
|
77
|
+
ON entity_dispatch_state (tenant_id, active_runner_id);
|
|
78
|
+
--> statement-breakpoint
|
|
79
|
+
CREATE INDEX idx_entity_dispatch_state_outstanding_wake
|
|
80
|
+
ON entity_dispatch_state (tenant_id, outstanding_wake_id);
|
|
81
|
+
--> statement-breakpoint
|
|
82
|
+
CREATE INDEX idx_entity_dispatch_state_active_lease
|
|
83
|
+
ON entity_dispatch_state (tenant_id, active_lease_expires_at);
|
|
84
|
+
--> statement-breakpoint
|
|
85
|
+
INSERT INTO entity_dispatch_state (tenant_id, entity_url)
|
|
86
|
+
SELECT tenant_id, url FROM entities
|
|
87
|
+
ON CONFLICT (tenant_id, entity_url) DO NOTHING;
|
|
88
|
+
--> statement-breakpoint
|
|
89
|
+
CREATE TABLE wake_notifications (
|
|
90
|
+
tenant_id text NOT NULL DEFAULT 'default',
|
|
91
|
+
wake_id text NOT NULL,
|
|
92
|
+
entity_url text NOT NULL,
|
|
93
|
+
target_type text NOT NULL,
|
|
94
|
+
target_runner_id text,
|
|
95
|
+
target_webhook_url text,
|
|
96
|
+
target_worker_pool_id text,
|
|
97
|
+
runner_wake_stream text,
|
|
98
|
+
runner_wake_stream_offset text,
|
|
99
|
+
notification_public jsonb NOT NULL,
|
|
100
|
+
delivery_status text NOT NULL DEFAULT 'queued',
|
|
101
|
+
claim_status text NOT NULL DEFAULT 'unclaimed',
|
|
102
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
103
|
+
delivered_at timestamptz,
|
|
104
|
+
claimed_at timestamptz,
|
|
105
|
+
resolved_at timestamptz,
|
|
106
|
+
PRIMARY KEY (tenant_id, wake_id),
|
|
107
|
+
CONSTRAINT chk_wake_notifications_target_type CHECK (target_type IN ('webhook', 'runner', 'worker-pool')),
|
|
108
|
+
CONSTRAINT chk_wake_notifications_delivery_status CHECK (delivery_status IN ('queued', 'delivered', 'failed', 'superseded')),
|
|
109
|
+
CONSTRAINT chk_wake_notifications_claim_status CHECK (claim_status IN ('unclaimed', 'claimed', 'completed', 'expired'))
|
|
110
|
+
);
|
|
111
|
+
--> statement-breakpoint
|
|
112
|
+
CREATE INDEX idx_wake_notifications_entity_url
|
|
113
|
+
ON wake_notifications (tenant_id, entity_url);
|
|
114
|
+
--> statement-breakpoint
|
|
115
|
+
CREATE INDEX idx_wake_notifications_target_runner
|
|
116
|
+
ON wake_notifications (tenant_id, target_runner_id);
|
|
117
|
+
--> statement-breakpoint
|
|
118
|
+
CREATE INDEX idx_wake_notifications_delivery_status
|
|
119
|
+
ON wake_notifications (tenant_id, delivery_status);
|
|
120
|
+
--> statement-breakpoint
|
|
121
|
+
CREATE INDEX idx_wake_notifications_claim_status
|
|
122
|
+
ON wake_notifications (tenant_id, claim_status);
|
|
123
|
+
--> statement-breakpoint
|
|
124
|
+
CREATE INDEX idx_wake_notifications_created_at
|
|
125
|
+
ON wake_notifications (tenant_id, created_at);
|
|
126
|
+
--> statement-breakpoint
|
|
127
|
+
CREATE TABLE consumer_claims (
|
|
128
|
+
tenant_id text NOT NULL DEFAULT 'default',
|
|
129
|
+
consumer_id text NOT NULL,
|
|
130
|
+
epoch integer NOT NULL,
|
|
131
|
+
wake_id text,
|
|
132
|
+
entity_url text NOT NULL,
|
|
133
|
+
stream_path text NOT NULL,
|
|
134
|
+
runner_id text,
|
|
135
|
+
status text NOT NULL DEFAULT 'active',
|
|
136
|
+
claimed_at timestamptz NOT NULL DEFAULT now(),
|
|
137
|
+
last_heartbeat_at timestamptz,
|
|
138
|
+
lease_expires_at timestamptz,
|
|
139
|
+
released_at timestamptz,
|
|
140
|
+
acked_streams jsonb,
|
|
141
|
+
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
142
|
+
PRIMARY KEY (tenant_id, consumer_id, epoch),
|
|
143
|
+
CONSTRAINT chk_consumer_claims_status CHECK (status IN ('active', 'released', 'expired', 'failed'))
|
|
144
|
+
);
|
|
145
|
+
--> statement-breakpoint
|
|
146
|
+
CREATE INDEX idx_consumer_claims_entity_status
|
|
147
|
+
ON consumer_claims (tenant_id, entity_url, status);
|
|
148
|
+
--> statement-breakpoint
|
|
149
|
+
CREATE INDEX idx_consumer_claims_runner
|
|
150
|
+
ON consumer_claims (tenant_id, runner_id);
|
|
151
|
+
--> statement-breakpoint
|
|
152
|
+
CREATE INDEX idx_consumer_claims_wake_id
|
|
153
|
+
ON consumer_claims (tenant_id, wake_id);
|
|
154
|
+
--> statement-breakpoint
|
|
155
|
+
CREATE INDEX idx_consumer_claims_lease_expires_at
|
|
156
|
+
ON consumer_claims (tenant_id, lease_expires_at);
|