Files
massive-cloud/server/analysisArtifacts.ts

69 lines
2.0 KiB
TypeScript

import * as fs from "node:fs";
import * as path from "node:path";
export type AnalysisArtifactPaths = {
analysisDir: string;
resultDir: string;
legacyFiles: string[];
};
function assertNumericId(name: string, value: number): void {
if (!Number.isSafeInteger(value) || value <= 0) {
throw new Error(`${name} must be a positive safe integer`);
}
}
export function getAnalysisArtifactPaths(
taskId: number,
resultId: number,
dataDir = process.env.DATA_DIR || "/data",
): AnalysisArtifactPaths {
assertNumericId("taskId", taskId);
assertNumericId("resultId", resultId);
const tasksDir = path.resolve(dataDir, "tasks");
const taskDir = path.resolve(tasksDir, String(taskId));
const analysisDir = path.resolve(taskDir, "analysis");
const resultDir = path.resolve(analysisDir, String(resultId));
if (path.dirname(taskDir) !== tasksDir || path.dirname(resultDir) !== analysisDir) {
throw new Error("analysis artifact path escaped its fixed root");
}
return {
analysisDir,
resultDir,
legacyFiles: [
path.join(analysisDir, `heatmap_${resultId}.bin`),
path.join(analysisDir, `deviation_${resultId}.bin`),
],
};
}
export async function cleanupAnalysisArtifacts(
taskId: number,
resultId: number,
dataDir = process.env.DATA_DIR || "/data",
): Promise<void> {
const paths = getAnalysisArtifactPaths(taskId, resultId, dataDir);
await fs.promises.rm(paths.resultDir, { recursive: true, force: true });
let entries: string[] = [];
try {
entries = await fs.promises.readdir(paths.analysisDir);
} catch (error) {
if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
}
const assemblyPrefix = `assembly_vertex_${resultId}_`;
const assemblyFiles = entries
.filter((name) => name.startsWith(assemblyPrefix) && name.endsWith(".bin"))
.map((name) => path.join(paths.analysisDir, name));
await Promise.all(
[...paths.legacyFiles, ...assemblyFiles].map((file) =>
fs.promises.rm(file, { force: true }),
),
);
}