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>
32 lines
2.1 KiB
SQL
32 lines
2.1 KiB
SQL
-- =====================================================================
|
||
-- NetPulse :: 0018_rule_actions.sql
|
||
-- Правило саме каже, куди йде його алерт.
|
||
--
|
||
-- Досі маршрутизація жила тільки в alr.routes — окремій сутності з
|
||
-- власним фільтром. Це працює для великих інсталяцій, де маршрути
|
||
-- будують один раз, і не працює для звичайного випадку «це правило
|
||
-- важливе, шліть його черговому в Telegram»: людина створює правило й
|
||
-- очікує тут же сказати, кому воно телефонує.
|
||
--
|
||
-- Маршрути лишаються: вони вирішують інше завдання — спільну політику
|
||
-- на всі правила разом.
|
||
-- =====================================================================
|
||
|
||
-- Порожній масив = «як вирішать маршрути». Саме порожній, а не NULL:
|
||
-- відсутність вибору і свідомо порожній вибір тут — те саме, і два
|
||
-- способи це записати лише плодили б розбіжність.
|
||
ALTER TABLE alr.rules
|
||
ADD COLUMN channel_ids uuid[] NOT NULL DEFAULT '{}';
|
||
|
||
-- Тихі години правила: {"tz":"Europe/Kyiv","quiet":[{"days":[6,0],"from":"22:00","to":"08:00"}]}
|
||
-- Той самий формат, що в alr.routes.schedule — щоб не заводити другий
|
||
-- діалект того самого поняття.
|
||
ALTER TABLE alr.rules
|
||
ADD COLUMN notify_schedule jsonb;
|
||
|
||
-- Чи слати повідомлення про зняття алерту.
|
||
--
|
||
-- Типово так: «впало» без «піднялося» змушує людину йти перевіряти
|
||
-- руками, і цим повідомлення про аварію знецінює саме себе.
|
||
ALTER TABLE alr.rules
|
||
ADD COLUMN notify_on_resolve boolean NOT NULL DEFAULT true;
|