CREATE TABLE IF NOT EXISTS gateway_execution_pools ( pool_id text PRIMARY KEY, labels jsonb NOT NULL DEFAULT '{}'::jsonb, capabilities jsonb NOT NULL DEFAULT '{}'::jsonb, state text NOT NULL DEFAULT 'active', created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now(), CONSTRAINT gateway_execution_pools_id_check CHECK (pool_id ~ '^[A-Za-z0-9][A-Za-z0-9._:/-]{0,127}$'), CONSTRAINT gateway_execution_pools_state_check CHECK (state IN ('active', 'draining', 'disabled')), CONSTRAINT gateway_execution_pools_labels_object_check CHECK (jsonb_typeof(labels) = 'object'), CONSTRAINT gateway_execution_pools_capabilities_object_check CHECK (jsonb_typeof(capabilities) = 'object') ); INSERT INTO gateway_execution_pools (pool_id, labels) VALUES ('legacy-default', '{"migration":"legacy"}'::jsonb) ON CONFLICT (pool_id) DO NOTHING; INSERT INTO gateway_execution_pools (pool_id, labels) SELECT DISTINCT site, jsonb_build_object('legacy_site', site) FROM gateway_worker_instances WHERE NULLIF(site, '') IS NOT NULL ON CONFLICT (pool_id) DO NOTHING; ALTER TABLE gateway_worker_instances ADD COLUMN pool_id text DEFAULT 'legacy-default', ADD COLUMN worker_id text DEFAULT '', ADD COLUMN endpoint text DEFAULT '', ADD COLUMN orchestrator_instance_ref text DEFAULT '', ADD COLUMN labels jsonb DEFAULT '{}'::jsonb, ADD COLUMN capabilities jsonb DEFAULT '{}'::jsonb, ADD COLUMN protocol_version text DEFAULT 'v1'; UPDATE gateway_worker_instances SET pool_id = site WHERE NULLIF(site, '') IS NOT NULL AND pool_id = 'legacy-default'; UPDATE gateway_worker_instances SET worker_id = instance_id WHERE worker_id = ''; UPDATE gateway_worker_instances SET orchestrator_instance_ref = pod_name WHERE orchestrator_instance_ref = '' AND NULLIF(pod_name, '') IS NOT NULL; ALTER TABLE gateway_worker_instances ADD CONSTRAINT gateway_worker_instances_pool_fk FOREIGN KEY (pool_id) REFERENCES gateway_execution_pools(pool_id) ON DELETE RESTRICT, ADD CONSTRAINT gateway_worker_instances_routing_fields_not_null_check CHECK (num_nonnulls(pool_id, worker_id, endpoint, orchestrator_instance_ref, labels, capabilities, protocol_version) = 7) NOT VALID, ADD CONSTRAINT gateway_worker_instances_labels_object_check CHECK (jsonb_typeof(labels) = 'object') NOT VALID, ADD CONSTRAINT gateway_worker_instances_capabilities_object_check CHECK (jsonb_typeof(capabilities) = 'object') NOT VALID; ALTER TABLE gateway_worker_instances VALIDATE CONSTRAINT gateway_worker_instances_routing_fields_not_null_check; ALTER TABLE gateway_worker_instances VALIDATE CONSTRAINT gateway_worker_instances_labels_object_check; ALTER TABLE gateway_worker_instances VALIDATE CONSTRAINT gateway_worker_instances_capabilities_object_check; CREATE INDEX IF NOT EXISTS idx_worker_instances_pool_heartbeat ON gateway_worker_instances(pool_id, status, heartbeat_at, instance_id); CREATE TABLE IF NOT EXISTS gateway_route_health ( pool_id text NOT NULL REFERENCES gateway_execution_pools(pool_id) ON DELETE CASCADE, route_profile_key text NOT NULL, state text NOT NULL DEFAULT 'unknown', success_rate double precision NOT NULL DEFAULT 0, connect_tls_p95_ms bigint NOT NULL DEFAULT 0, first_byte_p95_ms bigint NOT NULL DEFAULT 0, upload_bytes_per_second double precision NOT NULL DEFAULT 0, jitter_p95_ms bigint NOT NULL DEFAULT 0, consecutive_failures integer NOT NULL DEFAULT 0, consecutive_successes integer NOT NULL DEFAULT 0, sample_count integer NOT NULL DEFAULT 0, sampled_at timestamptz NOT NULL, expires_at timestamptz NOT NULL, updated_at timestamptz NOT NULL DEFAULT now(), PRIMARY KEY (pool_id, route_profile_key), CONSTRAINT gateway_route_health_state_check CHECK (state IN ('healthy', 'degraded', 'unreachable', 'unknown')), CONSTRAINT gateway_route_health_values_check CHECK ( success_rate >= 0 AND success_rate <= 1 AND connect_tls_p95_ms >= 0 AND first_byte_p95_ms >= 0 AND upload_bytes_per_second >= 0 AND jitter_p95_ms >= 0 AND consecutive_failures >= 0 AND consecutive_successes >= 0 AND sample_count >= 0 AND expires_at >= sampled_at ) ); CREATE INDEX IF NOT EXISTS idx_gateway_route_health_fresh ON gateway_route_health(route_profile_key, expires_at, state, pool_id); CREATE TABLE IF NOT EXISTS gateway_route_preferences ( route_profile_key text PRIMARY KEY, current_pool_id text NOT NULL DEFAULT '', current_since timestamptz, challenger_pool_id text NOT NULL DEFAULT '', challenger_wins integer NOT NULL DEFAULT 0, updated_at timestamptz NOT NULL DEFAULT now(), CONSTRAINT gateway_route_preferences_wins_check CHECK (challenger_wins >= 0) ); CREATE TABLE IF NOT EXISTS gateway_route_probe_requests ( route_profile_key text PRIMARY KEY, requested_at timestamptz NOT NULL DEFAULT now(), expires_at timestamptz NOT NULL DEFAULT now() + interval '30 seconds' ); CREATE INDEX IF NOT EXISTS idx_gateway_route_probe_requests_due ON gateway_route_probe_requests(expires_at, requested_at); CREATE TABLE IF NOT EXISTS gateway_pool_capacity_desires ( pool_id text PRIMARY KEY REFERENCES gateway_execution_pools(pool_id) ON DELETE CASCADE, desired integer NOT NULL, reason text NOT NULL DEFAULT '', valid_until timestamptz NOT NULL, updated_at timestamptz NOT NULL DEFAULT now(), CONSTRAINT gateway_pool_capacity_desires_value_check CHECK (desired >= 0) ); CREATE TABLE IF NOT EXISTS gateway_worker_execution_leases ( lease_id uuid PRIMARY KEY, task_id uuid NOT NULL REFERENCES gateway_tasks(id) ON DELETE CASCADE, pool_id text NOT NULL REFERENCES gateway_execution_pools(pool_id) ON DELETE RESTRICT, worker_id text NOT NULL, instance_id text NOT NULL REFERENCES gateway_worker_instances(instance_id) ON DELETE CASCADE, nonce_hash text NOT NULL UNIQUE, state text NOT NULL DEFAULT 'reserved', expires_at timestamptz NOT NULL, released_at timestamptz, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now(), CONSTRAINT gateway_worker_execution_leases_state_check CHECK (state IN ('reserved', 'running', 'released', 'expired')) ); CREATE INDEX IF NOT EXISTS idx_worker_execution_leases_active ON gateway_worker_execution_leases(pool_id, instance_id, expires_at) WHERE released_at IS NULL; ALTER TABLE gateway_tasks ADD COLUMN assigned_pool_id text, ADD COLUMN assigned_worker_id text, ADD COLUMN route_profile_key text, ADD COLUMN routing_platform_id uuid, ADD COLUMN routing_platform_model_id uuid, ADD COLUMN routing_version text, ADD COLUMN routing_reason text, ADD COLUMN routing_snapshot jsonb, ADD COLUMN submission_state text DEFAULT 'not_started'; ALTER TABLE gateway_tasks ADD CONSTRAINT gateway_tasks_assigned_pool_fk FOREIGN KEY (assigned_pool_id) REFERENCES gateway_execution_pools(pool_id) ON DELETE SET NULL, ADD CONSTRAINT gateway_tasks_routing_platform_fk FOREIGN KEY (routing_platform_id) REFERENCES integration_platforms(id) ON DELETE SET NULL, ADD CONSTRAINT gateway_tasks_routing_platform_model_fk FOREIGN KEY (routing_platform_model_id) REFERENCES platform_models(id) ON DELETE SET NULL, ADD CONSTRAINT gateway_tasks_routing_snapshot_object_check CHECK (routing_snapshot IS NULL OR jsonb_typeof(routing_snapshot) = 'object') NOT VALID, ADD CONSTRAINT gateway_tasks_submission_state_not_null_check CHECK (num_nonnulls(submission_state) = 1) NOT VALID, ADD CONSTRAINT gateway_tasks_submission_state_check CHECK (submission_state IN ('not_started', 'submitting', 'submitted', 'submission_confirmation_pending', 'completed')) NOT VALID; ALTER TABLE gateway_tasks VALIDATE CONSTRAINT gateway_tasks_submission_state_not_null_check; ALTER TABLE gateway_tasks VALIDATE CONSTRAINT gateway_tasks_routing_snapshot_object_check; ALTER TABLE gateway_tasks VALIDATE CONSTRAINT gateway_tasks_submission_state_check; CREATE INDEX IF NOT EXISTS idx_gateway_tasks_assigned_pool_queue ON gateway_tasks(assigned_pool_id, status, next_run_at, priority, created_at) WHERE async_mode = true AND status = 'queued';