-- 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);
