Files
tech-log-frontend/scripts/lib/provider-raw-cleanup.ts

41 lines
1.4 KiB
TypeScript

import { randomBytes } from "node:crypto";
import { lstat, rename, unlink } from "node:fs/promises";
export type ProviderRawIdentity = Readonly<{
reportPath: string;
reportDev: number;
reportIno: number;
}>;
export async function cleanupOwnedProviderReport(
identity: ProviderRawIdentity,
): Promise<boolean> {
try {
const metadata = await lstat(identity.reportPath);
if (!matchesReportIdentity(metadata, identity)) return false;
const quarantine = `${identity.reportPath}.parent-loss-${process.pid}-${randomBytes(16).toString("hex")}`;
await rename(identity.reportPath, quarantine);
const quarantinedMetadata = await lstat(quarantine);
if (!matchesReportIdentity(quarantinedMetadata, identity)) {
throw new Error("provider raw output identity changed during parent-loss cleanup");
}
await unlink(quarantine);
return true;
} catch (error) {
if (hasErrorCode(error, "ENOENT")) return false;
throw error;
}
}
function matchesReportIdentity(
metadata: Awaited<ReturnType<typeof lstat>>,
identity: ProviderRawIdentity,
): boolean {
return metadata.isFile() && !metadata.isSymbolicLink() &&
metadata.dev === identity.reportDev && metadata.ino === identity.reportIno;
}
function hasErrorCode(error: unknown, code: string): boolean {
return Boolean(error && typeof error === "object" && "code" in error && error.code === code);
}