Files
HealthLog/src/lib/database-backup/dump-problems.ts
T
Marc-André Bombeck 664b46d2c6 fix(db-backup): read the off-host leg of the dump on its own
A run that kept its dump on the volume and failed the upload is the newest
good dump and the newest failure at the same instant. Compared with ">", the
card showed no failure and readiness said fresh, night after night, while no
dump left the host.

The health read now carries the off-host leg separately: when the newest dump
reached the bucket, and the newest one that did not. One pure reading of it
(databaseDumpProblems) feeds both the backups card and the readiness model.
A configured bucket that missed the newest dump is attention (offhost_failed)
with the upload's error, and failing once the newest dump there is older than
36 hours (offhost_stale) or none ever arrived (offhost_never). The card shows
the refused upload and when the bucket last got a dump. A failure at the
instant of the newest dump for another reason, retention throwing, is now
shown too.
2026-10-25 16:53:24 +01:00

45 lines
1.6 KiB
TypeScript

/**
* What is wrong with the nightly dump, read from its health once, for the
* backups card and the readiness model alike, so the two cannot disagree.
*
* Pure and free of server imports: the card is a client component.
*/
import type { DatabaseBackupHealth } from "./health";
export interface DatabaseDumpProblems {
/**
* The newest run failed at or after the newest kept dump, for a reason other
* than the upload: nothing was kept, or a later step (retention) failed.
*/
failure: { at: string; error: string } | null;
/**
* The bucket is configured and the newest dump taken did not reach it.
* `lastUploadAt` is the newest dump that did, or null when none ever did.
*/
offhost: { at: string; error: string; lastUploadAt: string | null } | null;
}
export function databaseDumpProblems(
health: Pick<
DatabaseBackupHealth,
"lastGood" | "lastFailure" | "offhostConfigured" | "offhost"
>,
): DatabaseDumpProblems {
const offhost =
health.offhostConfigured && health.offhost.failure
? {
...health.offhost.failure,
lastUploadAt: health.offhost.lastUploadAt,
}
: null;
const failure = health.lastFailure;
const good = health.lastGood;
// At or after: a run that kept its dump and then failed is the newest good
// dump and the newest failure, at the same instant.
const sinceGood =
failure !== null && (good === null || failure.at >= good.at);
// That same run failing only its upload is the off-host problem, said once.
const isTheUpload = offhost !== null && failure?.at === offhost.at;
return { failure: sinceGood && !isTheUpload ? failure : null, offhost };
}