const fs = require('fs'); const path = require('path'); async function getDirLatestModifyTime(dirPath) { let latestTime = 0; const items = await fs.readdir(dirPath, { withFileTypes: true }); for (const item of items) { const itemPath = path.join(dirPath, item.name); const stats = await fs.stat(itemPath); // Update latest time if current item is newer if (stats.mtimeMs > latestTime) { latestTime = stats.mtimeMs; } // Recursively check sub-directories if (item.isDirectory()) { const subDirLatest = await getDirLatestModifyTime(itemPath); if (subDirLatest > latestTime) { latestTime = subDirLatest; } } } // If directory is empty, use its own modification time return latestTime || (await fs.stat(dirPath)).mtimeMs; } async function cleanExpiredJobDirs(maxAge = 24 * 3600000) { const resultsDir = path.join(__dirname, 'results'); const now = Date.now(); try { // Iterate through all job directories const jobDirs = await fs.readdir(resultsDir, { withFileTypes: true }); for (const dir of jobDirs) { if (dir.isDirectory()) { const jobPath = path.join(resultsDir, dir.name); const jobLatestTime = await getDirLatestModifyTime(jobPath); const jobAge = now - jobLatestTime; // Delete folder if it exceeds max retention time if (jobAge > maxAge) { // Recursively delete folder and all contents await fs.rm(jobPath, { recursive: true, force: true }); console.log(`Expired job folder deleted: ${jobPath} (Latest update: ${new Date(jobLatestTime).toLocaleString()})`); } } } } catch (error) { console.error(`Cleanup failed: ${error.message}`); } } // Export functions for use by other modules module.exports = { cleanExpiredJobDirs };