-- +goose Up
-- Часовой объект — единица хранения разобранных точек. Строка на точку дала бы
-- десятки миллионов строк в год; час даёт ~260 тысяч на слой независимо от
-- плотности потока.
--
-- Внутрь payload средствами SQL не заглянуть — это осознанная плата. Границы
-- содержимого и счётчик вынесены колонками, чтобы каталог разрезов не разжимал
-- каждый блоб ради диапазона.
CREATE TABLE bucket (
    metric            TEXT NOT NULL,
    -- Слой выводится из выравнивания меток, а не из заголовка доставки:
    -- sample / raw / minute / hour / day.
    layer             TEXT NOT NULL,
    -- Начало часа в UTC, RFC 3339. Час берётся по НАЧАЛУ точки: интервал
    -- пересекает границы часов, и любой другой выбор сделал бы принадлежность
    -- объекту зависящей от длительности.
    hour_utc          TEXT NOT NULL,

    -- Единицы измерения живут на уровне метрики, внутри точки их нет (проверено
    -- на 89 доставках: поле units не встретилось ни разу). Без этой колонки
    -- единицы метрики, переставшей приходить, теряются навсегда.
    units             TEXT NOT NULL DEFAULT '',

    -- Точки часа: JSON-массив исходных байтов точек, сжатый gzip. Точки
    -- упорядочены по времени начала.
    payload           BLOB NOT NULL,
    -- Хеш канонической формы содержимого: детектор изменений, а не ключ.
    -- Совпал — записи не происходит, и широкие проходы синхронизации
    -- обходятся даром.
    content_hash      TEXT NOT NULL,

    points            INTEGER NOT NULL DEFAULT 0,
    -- Границы содержимого: первая и последняя метка начала, UTC RFC 3339.
    first_ts          TEXT NOT NULL,
    last_ts           TEXT NOT NULL,

    -- Провенанс: доставка, создавшая объект. Нужен, чтобы разбирать слияния;
    -- у отдельной точки провенанса нет и не будет.
    first_delivery_id TEXT NOT NULL DEFAULT '',

    -- Час, в который досчёт уже не ожидается. Правило перевода в sealed пока
    -- не определено — порог ставится по наблюдениям, которых нет; до тех пор
    -- признак остаётся невыставленным.
    sealed            INTEGER NOT NULL DEFAULT 0,

    created_at        TEXT NOT NULL,
    updated_at        TEXT NOT NULL,

    PRIMARY KEY (metric, layer, hour_utc)
) WITHOUT ROWID;

-- Каталог разрезов и Read API ходят «дай метрику за период»: метрика и слой
-- уже в первичном ключе, но выборка по времени поверх всех метрик нужна
-- ретеншену и проверке сходимости.
CREATE INDEX bucket_hour_utc ON bucket (hour_utc);

-- +goose Down
DROP TABLE bucket;
