За другою рецензією:
* scripts/dbtest.sh писав у шапці «не напрямляйте на робочу базу» й
нічого для цього не робив — перевірено, пішов котити міграції на базу
з бойовим іменем. Тепер вимагає probe/test в імені.
* sendText ковтав помилку, тож журнал ескалацій писав «надіслано» на
сходинці, жодне повідомлення якої не дійшло. Три результати замість
двох: no_channels, failed, sent.
* stopped_at IS NULL рятував лише від ack; гасіння правилом і
ResolveMissing рядка драбини не чіпають, і сходинка дзвонила за
погашеним алертом. Додано перевірку стану алерту в тому ж UPDATE.
* escalate() блокував весь тік движка — мертвий вебхук одного кабінету
зупиняв обчислення правил усім. Винесено в RunEscalations.
* алерт, народжений під заглушенням, не сповіщався ніколи: ні при
народженні, ні коли вікно скінчилось. Тепер перехід suppressed→firing
сповіщається, а драбина рахує час від першого сповіщення.
* alr.rules.channel_ids приймав чужі канали, глушачи і сповіщення, і
драбину. Перевірка як для сходинок; DeleteChannel чистить посилання.
І перше, що зловив прогін проти справжньої бази: nil-зріз каналів їде
явним NULL повз DEFAULT '{}' — правило без каналів давало 500.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
30 lines
1.8 KiB
Go
30 lines
1.8 KiB
Go
package alerting
|
||
|
||
import "testing"
|
||
|
||
// Аварія, що почалась усередині вікна обслуговування, до цього не
|
||
// будила нікого й ніколи: сповіщення при народженні не йшло (заглушено),
|
||
// а коли вікно скінчилось — теж не йшло, бо алерт уже «не новий». Драбина
|
||
// ескалації при цьому теж не взводилась.
|
||
//
|
||
// Тест тримає обидва боки переходу: пропустити його — тиша на справжній
|
||
// аварії, спрацювати зайвий раз — другий дзвінок про те саме.
|
||
func TestLeftSuppression(t *testing.T) {
|
||
for _, c := range []struct {
|
||
prev, cur string
|
||
want bool
|
||
why string
|
||
}{
|
||
{"suppressed", "firing", true, "вікно скінчилось, проблема лишилась — це перша звістка для людини"},
|
||
{"firing", "suppressed", false, "пішло в заглушення: про це не сповіщають"},
|
||
{"firing", "acknowledged", false, "хтось узяв у роботу"},
|
||
{"suppressed", "resolved", false, "минулось саме — будити нема про що"},
|
||
{"acknowledged", "firing", false, "зняли підтвердження: продовження відомої проблеми, не новина"},
|
||
{"", "firing", false, "новий алерт іде своїм шляхом, не цим"},
|
||
{"suppressed", "suppressed", false, "нічого не змінилось"},
|
||
} {
|
||
if got := leftSuppression(c.prev, c.cur); got != c.want {
|
||
t.Errorf("%s → %s: маємо %v, очікували %v (%s)", c.prev, c.cur, got, c.want, c.why)
|
||
}
|
||
}
|
||
}
|