fix(scheduler): читать снимки JSONB и показывать недоступные результаты
This commit is contained in:
1 parent
63b2f75012
commit
92b7399ddb
8 files changed
+102
-9
No files matched your search
@@ -93,6 +93,10 @@ export interface BackupsRunSnapshot {
|
||||
created: number
|
||||
failures: number
|
||||
pruned: number
|
||||
uploadFailures?: number
|
||||
pruneFailures?: number
|
||||
metadataError?: string
|
||||
eventErrors?: string[]
|
||||
errors?: string[]
|
||||
fatalError?: string
|
||||
}
|
||||
@@ -220,12 +224,32 @@ export interface SpeedScheduledRunSnapshot {
|
||||
runs: SpeedRunSnapshot[]
|
||||
}
|
||||
|
||||
export function parseSchedulerRunSnapshot(raw: string | null | undefined): SchedulerRunSnapshot | null {
|
||||
if (raw == null || raw.trim() === "") return null
|
||||
/** PostgreSQL JSONB returns an object; older records may still contain JSON text. */
|
||||
export function parseSchedulerRunSnapshot(raw: unknown): SchedulerRunSnapshot | null {
|
||||
try {
|
||||
const o = JSON.parse(raw) as { v?: unknown; job?: string }
|
||||
if (o?.v !== 1 || typeof o.job !== "string") return null
|
||||
return o as SchedulerRunSnapshot
|
||||
const value: unknown = typeof raw === "string" ? (raw.trim() ? JSON.parse(raw) : null) : raw
|
||||
if (!value || typeof value !== "object" || Array.isArray(value)) return null
|
||||
const o = value as Record<string, unknown>
|
||||
if (o.v !== 1 || typeof o.job !== "string" || typeof o.sampledAt !== "string" || !Number.isFinite(Date.parse(o.sampledAt))) return null
|
||||
if (o.skipped !== undefined && typeof o.skipped !== "boolean") return null
|
||||
if (o.fatalError !== undefined && typeof o.fatalError !== "string") return null
|
||||
for (const field of ["errors", "eventErrors"]) if (o[field] !== undefined && (!Array.isArray(o[field]) || !(o[field] as unknown[]).every(error => typeof error === "string"))) return null
|
||||
const arrays: Record<string, string> = { traffic: "servers", uptime_resources: "servers", servers_rest_ping: "servers", uptime_ping: "probes", uptime_speed: "runs" }
|
||||
if (Object.hasOwn(arrays, o.job)) {
|
||||
if (!Array.isArray(o[arrays[o.job]])) return null
|
||||
} else {
|
||||
const fields: Record<string, string[]> = { gre_bgp: ["greWritten", "bgpWritten"], internet_path: ["homes"], certificates_renew: ["checked", "renewed", "skippedTargets"], backups: ["created", "failures", "pruned"], geoip_update: ["checked", "downloaded", "skippedUnchanged", "bytes"], alert_engine: ["rulesChecked", "standaloneFires", "groupFires"] }
|
||||
if (!Object.hasOwn(fields, o.job) || !fields[o.job].every(field => typeof o[field] === "number" && Number.isSafeInteger(o[field]) && (o[field] as number) >= 0)) return null
|
||||
if (["certificates_renew", "geoip_update"].includes(o.job) && !Array.isArray(o.errors)) return null
|
||||
if (o.job === "backups") {
|
||||
if (typeof o.due !== "boolean") return null
|
||||
for (const field of ["uploadFailures", "pruneFailures"]) if (o[field] !== undefined && (typeof o[field] !== "number" || !Number.isSafeInteger(o[field]) || (o[field] as number) < 0)) return null
|
||||
if (o.metadataError !== undefined && typeof o.metadataError !== "string") return null
|
||||
}
|
||||
if (o.job === "internet_path" && typeof o.snapshotSaved !== "boolean") return null
|
||||
if (o.job === "alert_engine" && typeof o.skippedNoTelegram !== "boolean") return null
|
||||
}
|
||||
return o as unknown as SchedulerRunSnapshot
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user