-- Worker system: runners, job definitions, jobs, and job log.
-- Migration: 015_jobs_runners
-- Date: 2026-02

BEGIN;

--------------------------------------------------------------------------------
-- Runners (registered compute workers)
--------------------------------------------------------------------------------

CREATE TABLE runners (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    name            TEXT UNIQUE NOT NULL,
    token_hash      TEXT NOT NULL,
    token_prefix    TEXT NOT NULL,
    tags            TEXT[] NOT NULL DEFAULT '{}',
    status          TEXT NOT NULL DEFAULT 'offline',
    last_heartbeat  TIMESTAMPTZ,
    last_job_id     UUID,
    metadata        JSONB DEFAULT '{}',
    created_at      TIMESTAMPTZ NOT NULL DEFAULT now(),
    updated_at      TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE INDEX idx_runners_status ON runners(status);
CREATE INDEX idx_runners_token ON runners(token_hash);

--------------------------------------------------------------------------------
-- Job Definitions (parsed from YAML, stored for reference and FK)
--------------------------------------------------------------------------------

CREATE TABLE job_definitions (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    name            TEXT UNIQUE NOT NULL,
    version         INTEGER NOT NULL DEFAULT 1,
    trigger_type    TEXT NOT NULL,
    scope_type      TEXT NOT NULL,
    compute_type    TEXT NOT NULL,
    runner_tags     TEXT[] NOT NULL DEFAULT '{}',
    timeout_seconds INTEGER NOT NULL DEFAULT 600,
    max_retries     INTEGER NOT NULL DEFAULT 1,
    priority        INTEGER NOT NULL DEFAULT 100,
    definition      JSONB NOT NULL,
    enabled         BOOLEAN NOT NULL DEFAULT true,
    created_at      TIMESTAMPTZ NOT NULL DEFAULT now(),
    updated_at      TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE INDEX idx_job_defs_trigger ON job_definitions(trigger_type);
CREATE INDEX idx_job_defs_enabled ON job_definitions(enabled) WHERE enabled = true;

--------------------------------------------------------------------------------
-- Jobs (individual compute job instances)
--------------------------------------------------------------------------------

CREATE TYPE job_status AS ENUM (
    'pending', 'claimed', 'running', 'completed', 'failed', 'cancelled'
);

CREATE TABLE jobs (
    id                UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    job_definition_id UUID REFERENCES job_definitions(id) ON DELETE SET NULL,
    definition_name   TEXT NOT NULL,
    status            job_status NOT NULL DEFAULT 'pending',
    priority          INTEGER NOT NULL DEFAULT 100,
    item_id           UUID REFERENCES items(id) ON DELETE CASCADE,
    project_id        UUID REFERENCES projects(id) ON DELETE SET NULL,
    scope_metadata    JSONB DEFAULT '{}',
    runner_id         UUID REFERENCES runners(id) ON DELETE SET NULL,
    runner_tags       TEXT[] NOT NULL DEFAULT '{}',
    created_at        TIMESTAMPTZ NOT NULL DEFAULT now(),
    claimed_at        TIMESTAMPTZ,
    started_at        TIMESTAMPTZ,
    completed_at      TIMESTAMPTZ,
    timeout_seconds   INTEGER NOT NULL DEFAULT 600,
    expires_at        TIMESTAMPTZ,
    progress          INTEGER DEFAULT 0,
    progress_message  TEXT,
    result            JSONB,
    error_message     TEXT,
    retry_count       INTEGER NOT NULL DEFAULT 0,
    max_retries       INTEGER NOT NULL DEFAULT 1,
    created_by        TEXT,
    cancelled_by      TEXT
);

CREATE INDEX idx_jobs_status ON jobs(status);
CREATE INDEX idx_jobs_pending ON jobs(status, priority, created_at)
    WHERE status = 'pending';
CREATE INDEX idx_jobs_item ON jobs(item_id);
CREATE INDEX idx_jobs_runner ON jobs(runner_id);
CREATE INDEX idx_jobs_definition ON jobs(job_definition_id);

--------------------------------------------------------------------------------
-- Job Log (append-only progress entries)
--------------------------------------------------------------------------------

CREATE TABLE job_log (
    id         UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    job_id     UUID NOT NULL REFERENCES jobs(id) ON DELETE CASCADE,
    timestamp  TIMESTAMPTZ NOT NULL DEFAULT now(),
    level      TEXT NOT NULL DEFAULT 'info',
    message    TEXT NOT NULL,
    metadata   JSONB DEFAULT '{}'
);

CREATE INDEX idx_job_log_job ON job_log(job_id, timestamp);

COMMIT;
