feat: 支持 PK01 多数据库逻辑备份
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
export interface LogicalDumpConfig {
|
||||
enabled: boolean;
|
||||
database: string;
|
||||
scriptPath: string;
|
||||
serviceName: string;
|
||||
timerName: string;
|
||||
schedule: string;
|
||||
retentionDays: number;
|
||||
warningAfterHours: number;
|
||||
destination: { type: string; path: string };
|
||||
pgDump: { host: string; format: "custom" };
|
||||
encryption: { enabled: boolean };
|
||||
}
|
||||
|
||||
export interface LogicalDumpRuntimeFact {
|
||||
database: string;
|
||||
databaseExists: boolean;
|
||||
scriptPath: string;
|
||||
scriptExists: boolean;
|
||||
serviceName: string;
|
||||
serviceResult: string | null;
|
||||
serviceExitStatus: number | null;
|
||||
lastSuccessAt: string | null;
|
||||
timerName: string;
|
||||
timerActive: boolean;
|
||||
timerEnabled: boolean;
|
||||
nextRunAt: string | null;
|
||||
latestNonEmptyDump: {
|
||||
path: string;
|
||||
bytes: number;
|
||||
modifiedAt: string;
|
||||
} | null;
|
||||
}
|
||||
|
||||
export interface LogicalDumpProjection extends LogicalDumpConfig {
|
||||
observed: LogicalDumpRuntimeFact | null;
|
||||
recoverability: {
|
||||
recoverable: boolean;
|
||||
latestNonEmptyDump: LogicalDumpRuntimeFact["latestNonEmptyDump"];
|
||||
};
|
||||
warnings: string[];
|
||||
}
|
||||
|
||||
export function projectLogicalDumps(
|
||||
declarations: LogicalDumpConfig[],
|
||||
facts: LogicalDumpRuntimeFact[] | null,
|
||||
observedAt = Date.now(),
|
||||
): LogicalDumpProjection[] {
|
||||
return declarations.map((declaration) => {
|
||||
const observed = facts?.find((item) => item.database === declaration.database && item.timerName === declaration.timerName) ?? null;
|
||||
const warnings: string[] = [];
|
||||
if (!declaration.enabled) return projection(declaration, observed, warnings);
|
||||
if (observed === null) {
|
||||
warnings.push("backup-observation-unavailable");
|
||||
return projection(declaration, observed, warnings);
|
||||
}
|
||||
if (!observed.databaseExists) warnings.push("backup-database-missing");
|
||||
if (!observed.scriptExists) warnings.push("backup-script-missing");
|
||||
if (!observed.timerEnabled) warnings.push("backup-timer-disabled");
|
||||
if (!observed.timerActive) warnings.push("backup-timer-inactive");
|
||||
if (observed.lastSuccessAt === null) warnings.push("backup-recent-success-missing");
|
||||
if (observed.latestNonEmptyDump === null) {
|
||||
warnings.push("backup-latest-non-empty-dump-missing");
|
||||
} else {
|
||||
const modifiedAt = Date.parse(observed.latestNonEmptyDump.modifiedAt);
|
||||
if (!Number.isFinite(modifiedAt) || observedAt - modifiedAt > declaration.warningAfterHours * 60 * 60 * 1000) {
|
||||
warnings.push("backup-latest-dump-stale");
|
||||
}
|
||||
}
|
||||
if (observed.serviceResult !== null && observed.serviceResult !== "success") warnings.push("backup-last-run-failed");
|
||||
if (observed.serviceExitStatus !== null && observed.serviceExitStatus !== 0) warnings.push("backup-last-run-nonzero");
|
||||
return projection(declaration, observed, warnings);
|
||||
});
|
||||
}
|
||||
|
||||
function projection(
|
||||
declaration: LogicalDumpConfig,
|
||||
observed: LogicalDumpRuntimeFact | null,
|
||||
warnings: string[],
|
||||
): LogicalDumpProjection {
|
||||
return {
|
||||
...declaration,
|
||||
observed,
|
||||
recoverability: {
|
||||
recoverable: observed?.databaseExists === true && observed.latestNonEmptyDump !== null,
|
||||
latestNonEmptyDump: observed?.latestNonEmptyDump ?? null,
|
||||
},
|
||||
warnings,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user