Netpulse_SasS/server/migrations/0022_template_graphs.sql
byrsapty 205dd5e079 Пакування: runner міграцій і вшитий у бінарник фронтенд
netpulse-migrate замість PowerShell-скрипта: у контейнері немає ані
psql, ані PowerShell, а тягнути клієнт Postgres в образ заради одного
запуску — це половина дистрибутива на порожньому місці.

Міграції вшиті через embed і переїхали в server/migrations: embed не
бачить нічого за межами кореня свого модуля, а міграції поруч із
бінарником, який їх накочує, не можуть розійтися версіями.

Накочування під advisory-блокуванням: два інстанси при rolling update
інакше застосували б ту саму міграцію двічі. Кожен файл в одній
транзакції разом із записом у schema_migrations; виняток — continuous
aggregates, які TimescaleDB забороняє в транзакції. Змінена вже
застосована міграція зупиняє запуск: у різних інсталяціях інакше
опиниться різна схема під одним номером.

Перевірено на чистій базі: 23 міграції, 101 таблиця, повторний запуск
каже «схема актуальна».

Веб віддає сам API через embed: на self-hosted це прибирає з інструкції
встановлення цілий компонент. Три політики кешування — назавжди для
assets із хешем у імені, ніколи для index.html, коротко для решти.

Знайдено живим прогоном: невідомий шлях під /api/ віддавав 200 з
index.html, і клієнт падав на розборі HTML як JSON замість чесного 404.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-25 01:01:55 +03:00

79 lines
4.5 KiB
SQL
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- =====================================================================
-- NetPulse :: 0022_template_graphs.sql
-- Графіки описуються в шаблоні разом із метриками.
--
-- Причина та сама, що для самих метрик: «завантаження каналу — це
-- if.in_bps і if.out_bps на одній осі» — це властивість класу
-- пристроїв, а не окремого хоста. Малювати той самий графік руками на
-- кожному хості означає повторювати одне рішення стільки разів,
-- скільки в мережі заліза.
-- =====================================================================
CREATE TYPE tpl.graph_kind AS ENUM (
'line', -- звичайні лінії
'area', -- лінії із заливкою
'stacked', -- заливка з накопиченням: сума має сенс (трафік по портах)
'bar', -- стовпчики: рідкі виміри, де лінія бреше про проміжок
'gauge', -- одне значення зі шкалою
'stat' -- одне значення числом
);
CREATE TABLE tpl.graphs (
id uuid PRIMARY KEY DEFAULT core.new_id(),
template_id uuid NOT NULL REFERENCES tpl.templates(id) ON DELETE CASCADE,
key core.slug NOT NULL,
name text NOT NULL,
kind tpl.graph_kind NOT NULL DEFAULT 'line',
-- Метрики на графіку: ["cpu.util_pct","mem.available_bytes"].
--
-- Ключі метрик, а не посилання на tpl.items: графік має право
-- показувати й те, що прийшло з іншого шаблону, — саме так і
-- виглядає «трафік поруч із помилками на тому ж порту».
metric_keys jsonb NOT NULL DEFAULT '[]'::jsonb,
-- Осі, кольори, межі, пороги: {"min":0,"max":100,"unit":"%"}
options jsonb NOT NULL DEFAULT '{}'::jsonb,
position int NOT NULL DEFAULT 0,
created_at timestamptz NOT NULL DEFAULT now(),
UNIQUE (template_id, key)
);
CREATE INDEX tpl_graphs_template_idx ON tpl.graphs (template_id);
ALTER TABLE tpl.graphs ENABLE ROW LEVEL SECURITY;
ALTER TABLE tpl.graphs FORCE ROW LEVEL SECURITY;
-- Видимість успадковується від шаблону — власного tenant_id у графіка
-- немає з тієї ж причини, що і в елементів: він завжди дорівнював би
-- шаблоновому, а дублювання ключа ізоляції розходиться.
CREATE POLICY graphs_follow_template ON tpl.graphs
USING (EXISTS (
SELECT 1 FROM tpl.templates t
WHERE t.id = tpl.graphs.template_id
AND (t.tenant_id IS NULL OR t.tenant_id = core.current_tenant())
))
WITH CHECK (EXISTS (
SELECT 1 FROM tpl.templates t
WHERE t.id = tpl.graphs.template_id AND t.tenant_id = core.current_tenant()
));
GRANT SELECT, INSERT, UPDATE, DELETE ON tpl.graphs TO netpulse_app, netpulse_worker;
-- ---------------------------------------------------------------------
-- Графіки вбудованих шаблонів
-- ---------------------------------------------------------------------
INSERT INTO tpl.graphs (template_id, key, name, kind, metric_keys, options) VALUES
('00000000-0000-0000-0000-0000000000c3', 'memory', 'Пам''ять', 'area',
'["mem.available_bytes","mem.total_bytes"]'::jsonb, '{"unit":"B"}'::jsonb),
('00000000-0000-0000-0000-0000000000c3', 'load', 'Середнє навантаження', 'line',
'["cpu.load1","cpu.load5"]'::jsonb, '{"min":0}'::jsonb),
('00000000-0000-0000-0000-0000000000c4', 'cpu', 'Завантаження CPU', 'gauge',
'["cpu.util_pct"]'::jsonb, '{"min":0,"max":100,"unit":"%"}'::jsonb),
('00000000-0000-0000-0000-0000000000c4', 'temp', 'Температура плати', 'line',
'["sensor.temp_c"]'::jsonb, '{"unit":"°C"}'::jsonb),
('00000000-0000-0000-0000-0000000000c5', 'rtt', 'Час відгуку', 'line',
'["icmp.rtt_avg","icmp.jitter"]'::jsonb, '{"min":0,"unit":"ms"}'::jsonb),
('00000000-0000-0000-0000-0000000000c5', 'loss', 'Втрати пакетів', 'area',
'["icmp.loss_pct"]'::jsonb, '{"min":0,"max":100,"unit":"%"}'::jsonb),
('00000000-0000-0000-0000-0000000000c1', 'uptime', 'Час роботи', 'stat',
'["sys.uptime_sec"]'::jsonb, '{"unit":"s"}'::jsonb)
ON CONFLICT DO NOTHING;