Асиметрія: аварія о 21:59 ескалювала всю ніч, о 22:01 не ескалювала ніколи. Дві хвилини різниці — протилежні наслідки, причому гірший (повна тиша) виглядав як тиша справна. ВАДА. targets() повертав порожньо в тиху годину, а взведення читало це як «немає куди слати». Взводять лише новий алерт, тож драбина не з'являлась уже ніколи: тиха година вимикала механізм саме тоді, коли перше сповіщення не спрацювало. Тепер targets() розрізняє «каналів немає» і «канали є, просто зараз ніч». ВИБІР. 0072 додає respect_quiet_hours на драбину: false (типово, як діяло) — драбина пробивається; true — сходинка відкладається до ранку і НЕ витрачається. Залежить від того, чи є в кабінету нічна зміна — це вирішує кабінет. disaster пробивається за будь-якого значення, як і в targets(). Відлік драбини — від першого сповіщення, а не від started_at: інакше для розглушеного алерту вона протухла б ще у вікні. І сам прогін проти бази брехав: dbtest.sh котив схему готовим образом (старі міграції), а тести брав із нового дерева. Тепер міграції з того ж дерева. 64 міграції, усе зелене. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
54 lines
3.9 KiB
SQL
54 lines
3.9 KiB
SQL
-- =====================================================================
|
||
-- NetPulse :: 0072_escalation_quiet_hours.sql
|
||
-- Що тиха година правила означає для драбини ескалації.
|
||
--
|
||
-- ЩО БУЛО НЕ ТАК
|
||
--
|
||
-- Тиха година діяла на перше сповіщення й не діяла на драбину взагалі.
|
||
-- Це давало асиметрію, яку неможливо пояснити людині, що її переживе:
|
||
--
|
||
-- аварія о 21:59 — перше сповіщення пішло, драбина взвелась, і вона
|
||
-- дзвонить усю ніч, бо про тиху годину не знає;
|
||
-- аварія о 22:01 — перше сповіщення притлумлено тихою годиною, тож
|
||
-- каналів «не знайшлось», тож драбина не взвелась —
|
||
-- і не взведеться вже НІКОЛИ, бо взводять лише
|
||
-- новий алерт.
|
||
--
|
||
-- Дві хвилини різниці — і протилежні наслідки, причому гірший із них
|
||
-- (повна тиша на аварії) виглядає як тиша справна.
|
||
--
|
||
-- ЧОМУ ЦЕ ПРАПОРЕЦЬ, А НЕ ОБРАНА НАМИ ПОВЕДІНКА
|
||
--
|
||
-- Обидві відповіді правильні, і вибір між ними — не технічний:
|
||
--
|
||
-- * «драбина не зважає на тиху годину» — тиха година стосується
|
||
-- ПЕРШОГО сповіщення, а сенс драбини рівно в тому, щоб пробитись,
|
||
-- коли перше проґавили. Так працює чергування: тебе не будять по
|
||
-- дрібницях, але якщо ніхто не відповів — будять.
|
||
--
|
||
-- * «драбина відкладає сходинку до кінця тихої години» — тиха година
|
||
-- означає «ці люди зараз не на зміні», і будити їх драбиною так
|
||
-- само неправильно, як першим сповіщенням.
|
||
--
|
||
-- Правильна відповідь залежить від того, чи є в кабінету нічна зміна, а
|
||
-- це вирішує кабінет, а не ми. Тому прапорець на драбині — там же, де
|
||
-- людина вирішує, кого й через скільки будити.
|
||
--
|
||
-- Типове значення false — та поведінка, яка вже діє для взведених
|
||
-- драбин. Оновлення не має тихо роззброїти нічні дзвінки в тих, у кого
|
||
-- вони працюють.
|
||
--
|
||
-- DISASTER ПРОБИВАЄТЬСЯ ЗАВЖДИ
|
||
--
|
||
-- Виняток не новий: targets() уже пропускає disaster крізь тиху годину
|
||
-- маршруту й правила з тим самим міркуванням — сенс чергування в тому,
|
||
-- щоб найважче підняли. Драбина мусить поводитись так само, інакше одне
|
||
-- і те саме слово в двох місцях означало б різне.
|
||
-- =====================================================================
|
||
|
||
ALTER TABLE alr.escalation_policies
|
||
ADD COLUMN IF NOT EXISTS respect_quiet_hours boolean NOT NULL DEFAULT false;
|
||
|
||
COMMENT ON COLUMN alr.escalation_policies.respect_quiet_hours IS
|
||
'Чи відкладати сходинки на час тихої години правила. false — драбина '
|
||
'пробивається крізь тиху годину (типово). disaster пробивається завжди.';
|