This commit is contained in:
141
services/fileCleanupService.js
Normal file
141
services/fileCleanupService.js
Normal file
@@ -0,0 +1,141 @@
|
||||
const BaseService = require('./BaseService');
|
||||
const cron = require('node-cron');
|
||||
const fs = require('fs').promises;
|
||||
const path = require('path');
|
||||
|
||||
class FileCleanupService extends BaseService {
|
||||
constructor(config = {}) {
|
||||
super('fileCleanup', {
|
||||
fileInfoPath: config.fileInfoPath || path.join(process.cwd(), 'data', 'file_info.json'),
|
||||
cronSchedule: config.cronSchedule || '0 * * * *',
|
||||
...config
|
||||
});
|
||||
this.job = null;
|
||||
}
|
||||
|
||||
async _startImplementation() {
|
||||
if (this.job) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Valider le cron schedule
|
||||
if (!cron.validate(this.config.cronSchedule)) {
|
||||
throw new Error(`Schedule cron invalide: ${this.config.cronSchedule}`);
|
||||
}
|
||||
|
||||
this.job = cron.schedule(this.config.cronSchedule, () => this.cleanup());
|
||||
}
|
||||
|
||||
async _stopImplementation() {
|
||||
if (this.job) {
|
||||
this.job.stop();
|
||||
this.job = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Réutiliser vos méthodes existantes
|
||||
async fileExists(filepath) {
|
||||
try {
|
||||
await fs.access(filepath);
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
normalizePath(filepath) {
|
||||
return path.normalize(filepath).replace(/\\/g, '/');
|
||||
}
|
||||
|
||||
async readFileInfo() {
|
||||
try {
|
||||
const data = await fs.readFile(this.config.fileInfoPath, 'utf8');
|
||||
return JSON.parse(data);
|
||||
} catch (err) {
|
||||
this.logger.error('Erreur lors de la lecture du fichier info:', err);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
async saveFileInfo(fileInfo) {
|
||||
try {
|
||||
await fs.writeFile(
|
||||
this.config.fileInfoPath,
|
||||
JSON.stringify(fileInfo, null, 2),
|
||||
'utf8'
|
||||
);
|
||||
return true;
|
||||
} catch (err) {
|
||||
this.logger.error('Erreur lors de la sauvegarde du fichier info:', err);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async processFile(file, now) {
|
||||
const normalizedPath = this.normalizePath(file.path);
|
||||
|
||||
if (file.expiryDate && new Date(file.expiryDate) <= now) {
|
||||
return { status: 'expired', file: { ...file, path: normalizedPath } };
|
||||
}
|
||||
|
||||
if (!(await this.fileExists(normalizedPath))) {
|
||||
return { status: 'missing', file: { ...file, path: normalizedPath } };
|
||||
}
|
||||
|
||||
return { status: 'valid', file };
|
||||
}
|
||||
|
||||
async cleanup() {
|
||||
try {
|
||||
const fileInfo = await this.readFileInfo();
|
||||
const now = new Date();
|
||||
const results = {
|
||||
expired: [],
|
||||
missing: [],
|
||||
processed: 0,
|
||||
remaining: 0
|
||||
};
|
||||
|
||||
const validFiles = [];
|
||||
await Promise.all(fileInfo.map(async (file) => {
|
||||
const { status, file: processedFile } = await this.processFile(file, now);
|
||||
|
||||
if (status === 'expired') {
|
||||
results.expired.push(processedFile);
|
||||
results.processed++;
|
||||
} else if (status === 'missing') {
|
||||
results.missing.push(processedFile);
|
||||
results.processed++;
|
||||
} else {
|
||||
validFiles.push(file);
|
||||
}
|
||||
}));
|
||||
|
||||
if (results.processed > 0) {
|
||||
results.remaining = validFiles.length;
|
||||
await this.saveFileInfo(validFiles);
|
||||
|
||||
this.logger.info('Nettoyage des fichiers terminé', {
|
||||
expired: results.expired.length,
|
||||
missing: results.missing.length,
|
||||
totalProcessed: results.processed,
|
||||
remainingFiles: results.remaining
|
||||
});
|
||||
}
|
||||
|
||||
return results;
|
||||
} catch (err) {
|
||||
this.logger.error('Erreur lors du nettoyage des fichiers:', {
|
||||
error: err.message,
|
||||
stack: err.stack
|
||||
});
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
async forceCleanup() {
|
||||
return this.cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new FileCleanupService();
|
||||
Reference in New Issue
Block a user