Docker images / prepare-release (push) Successful in 12s
Docker images / backend-test (push) Successful in 4m9s
Docker images / frontend-image (push) Successful in 4m28s
Docker images / updater-image (push) Successful in 58s
Docker images / backend-image (push) Successful in 2m49s
Docker images / notify-webhook (push) Skipped
Docker images / publish-release (push) Successful in 11s
При старте backend накатывает схему PostgreSQL 18 и, если база пустая, один раз импортирует mikrotik.db с тома. Повторный старт не копирует данные. Бэкап в UI идёт через pg_dump. Co-authored-by: Cursor <[email protected]>
77 lines
2.4 KiB
TypeScript
77 lines
2.4 KiB
TypeScript
import assert from "node:assert/strict"
|
|
import { eq } from "drizzle-orm"
|
|
import { db } from "../../db/index.js"
|
|
import { alertEngineConfirmPending } from "../../db/schema.js"
|
|
import type { ApiAlertRule } from "../alerts-service.js"
|
|
import { computeStabilityReadyMap, deleteConfirmPending } from "./confirm-stability.js"
|
|
import { withPgOrSkip } from "../../test/pg.js"
|
|
|
|
const ruleId = "test-confirm-stability-recovery-bypass"
|
|
|
|
const baseRule: ApiAlertRule = {
|
|
id: ruleId,
|
|
name: "Server transition",
|
|
type: "server",
|
|
target: "core-1",
|
|
targets: ["core-1"],
|
|
groupId: null,
|
|
condition: "перешёл в offline · восстановился",
|
|
conditions: ["перешёл в offline", "восстановился"],
|
|
severity: "critical",
|
|
enabled: true,
|
|
cooldown: "5м",
|
|
confirmStabilitySec: 120,
|
|
recoveryMode: "always",
|
|
recoveryStabilitySec: null,
|
|
chatId: "",
|
|
lastFiredAt: null,
|
|
}
|
|
|
|
const problemHit = {
|
|
ruleId,
|
|
ruleName: baseRule.name,
|
|
severity: baseRule.severity,
|
|
message: "Сервер: core-1 — перешёл в offline",
|
|
transition: "problem" as const,
|
|
payloadHash: "problem-1",
|
|
}
|
|
|
|
const recoveryHit = {
|
|
ruleId,
|
|
ruleName: baseRule.name,
|
|
severity: baseRule.severity,
|
|
message: "Сервер: core-1 — восстановился",
|
|
transition: "recovery" as const,
|
|
payloadHash: "recovery-1",
|
|
}
|
|
|
|
if (!(await withPgOrSkip())) {
|
|
console.log("alert-engine confirm-stability tests skip")
|
|
process.exit(0)
|
|
}
|
|
|
|
await deleteConfirmPending(ruleId)
|
|
|
|
{
|
|
const m = await computeStabilityReadyMap([baseRule], new Map([[ruleId, problemHit]]))
|
|
assert.equal(m.get(ruleId), false, "проблемный переход должен ждать confirmStabilitySec")
|
|
}
|
|
|
|
{
|
|
const m = await computeStabilityReadyMap([baseRule], new Map([[ruleId, recoveryHit]]))
|
|
assert.equal(m.get(ruleId), true, "восстановление должно отправляться без задержки")
|
|
}
|
|
|
|
{
|
|
const m = await computeStabilityReadyMap([baseRule], new Map([[ruleId, null]]))
|
|
assert.equal(m.get(ruleId), false, "без hit отправка не готова")
|
|
const left = (await db
|
|
.select()
|
|
.from(alertEngineConfirmPending)
|
|
.where(eq(alertEngineConfirmPending.ruleId, ruleId))
|
|
.limit(1))[0]
|
|
assert.equal(left, undefined, "pending должен очищаться после отсутствия hit")
|
|
}
|
|
|
|
console.log("alert-engine confirm-stability tests ok")
|