-- Shared admission state for non-text synchronous and asynchronous tasks. CREATE TABLE IF NOT EXISTS gateway_task_admissions ( task_id uuid PRIMARY KEY REFERENCES gateway_tasks(id) ON DELETE CASCADE, platform_id uuid NOT NULL REFERENCES integration_platforms(id) ON DELETE RESTRICT, platform_model_id uuid NOT NULL REFERENCES platform_models(id) ON DELETE RESTRICT, user_group_id uuid REFERENCES gateway_user_groups(id) ON DELETE SET NULL, queue_key text NOT NULL, mode text NOT NULL, status text NOT NULL DEFAULT 'waiting', priority integer NOT NULL DEFAULT 100, enqueued_at timestamptz NOT NULL DEFAULT now(), wait_deadline_at timestamptz NOT NULL, admitted_at timestamptz, waiter_id text, waiter_lease_expires_at timestamptz, reselect_requested_at timestamptz, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now(), CONSTRAINT gateway_task_admissions_mode_check CHECK (mode IN ('sync', 'async')), CONSTRAINT gateway_task_admissions_status_check CHECK (status IN ('waiting', 'admitted')), CONSTRAINT gateway_task_admissions_deadline_check CHECK (wait_deadline_at >= enqueued_at), CONSTRAINT gateway_task_admissions_sync_waiter_check CHECK ( mode = 'async' OR status = 'admitted' OR ( NULLIF(waiter_id, '') IS NOT NULL AND waiter_lease_expires_at IS NOT NULL ) ) ); CREATE INDEX IF NOT EXISTS idx_task_admissions_platform_fifo ON gateway_task_admissions(platform_model_id, priority, enqueued_at, task_id) WHERE status = 'waiting'; CREATE INDEX IF NOT EXISTS idx_task_admissions_user_group_fifo ON gateway_task_admissions(user_group_id, priority, enqueued_at, task_id) WHERE status = 'waiting' AND user_group_id IS NOT NULL; CREATE INDEX IF NOT EXISTS idx_task_admissions_waiter_expiry ON gateway_task_admissions(waiter_lease_expires_at, task_id) WHERE status = 'waiting' AND mode = 'sync'; CREATE INDEX IF NOT EXISTS idx_task_admissions_deadline ON gateway_task_admissions(wait_deadline_at, task_id) WHERE status = 'waiting'; CREATE INDEX IF NOT EXISTS idx_task_admissions_reselection ON gateway_task_admissions(reselect_requested_at, priority, enqueued_at, task_id) WHERE status = 'waiting' AND reselect_requested_at IS NOT NULL; CREATE TABLE IF NOT EXISTS gateway_worker_instances ( instance_id text PRIMARY KEY, pod_uid text NOT NULL DEFAULT '', pod_name text NOT NULL DEFAULT '', site text NOT NULL DEFAULT '', revision text NOT NULL DEFAULT '', status text NOT NULL DEFAULT 'active', desired_capacity integer NOT NULL DEFAULT 0, allocated_capacity integer NOT NULL DEFAULT 0, started_at timestamptz NOT NULL DEFAULT now(), heartbeat_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now(), CONSTRAINT gateway_worker_instances_status_check CHECK (status IN ('active', 'draining')), CONSTRAINT gateway_worker_instances_capacity_check CHECK (desired_capacity >= 0 AND allocated_capacity >= 0) ); CREATE INDEX IF NOT EXISTS idx_worker_instances_active_heartbeat ON gateway_worker_instances(status, heartbeat_at, instance_id);