-- 025_execution_logs.up.sql -- Incremental command output for executions. -- -- Until now `executions.result` was a single JSONB blob written once, at the -- terminal state: {"output": "...everything..."}. Two consequences: -- -- 1. Nothing could be seen while a command ran. A ten-minute apt upgrade -- showed an empty row until it finished. -- 2. On the sshExecTimeout path the output was discarded entirely — the -- code returned "" — so the executions most worth inspecting (the ones -- that hung) were the ones that left no trace at all. -- -- Chunks land here as they arrive. `executions.result` still gets the full -- output at the end, so existing readers keep working unchanged and this -- table is purely additive. CREATE TABLE IF NOT EXISTS execution_logs ( execution_id UUID NOT NULL, ts TIMESTAMPTZ NOT NULL DEFAULT now(), -- Monotonic per execution. ts alone cannot order chunks: several arrive -- within the same microsecond on a fast command. seq INTEGER NOT NULL, -- 'stdout' or 'stderr'. Both are also concatenated into the combined -- output, matching what CombinedOutput used to return. stream TEXT NOT NULL, chunk TEXT NOT NULL, PRIMARY KEY (execution_id, seq, ts) ); SELECT create_hypertable('execution_logs', 'ts', chunk_time_interval => INTERVAL '7 days', if_not_exists => TRUE); -- The only query that matters: replay one execution's output in order. CREATE INDEX IF NOT EXISTS idx_execution_logs_exec_seq ON execution_logs (execution_id, seq); -- Matches the events table's 90 days. Command output is bulkier than events, -- but keeping it exactly as long as the event stream that references it avoids -- dangling 'execution.output' events pointing at rows that no longer exist. DO $$ BEGIN PERFORM add_retention_policy('execution_logs', INTERVAL '90 days'); EXCEPTION WHEN OTHERS THEN NULL; END $$;