141 lines
4.1 KiB
JavaScript
141 lines
4.1 KiB
JavaScript
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(); |