161 lines
4.3 KiB
TypeScript
161 lines
4.3 KiB
TypeScript
interface CleanupTask {
|
|
name: string;
|
|
cleanup: () => void | Promise<void>;
|
|
interval?: number;
|
|
}
|
|
|
|
class CleanupManager {
|
|
private static instance: CleanupManager;
|
|
private tasks: Map<string, CleanupTask> = new Map();
|
|
private intervals: Map<string, NodeJS.Timeout> = new Map();
|
|
|
|
private constructor() {
|
|
// Register default cleanup tasks
|
|
this.registerDefaultTasks();
|
|
}
|
|
|
|
static getInstance(): CleanupManager {
|
|
if (!CleanupManager.instance) {
|
|
CleanupManager.instance = new CleanupManager();
|
|
}
|
|
return CleanupManager.instance;
|
|
}
|
|
|
|
private registerDefaultTasks() {
|
|
// Clean up old temporary files
|
|
this.registerTask({
|
|
name: 'temp-files-cleanup',
|
|
cleanup: async () => {
|
|
console.log('[Cleanup] Running temporary files cleanup...');
|
|
// Implementation would go here
|
|
},
|
|
interval: 3600000 // Every hour
|
|
});
|
|
|
|
// Clean up expired cache entries
|
|
this.registerTask({
|
|
name: 'cache-cleanup',
|
|
cleanup: async () => {
|
|
console.log('[Cleanup] Running cache cleanup...');
|
|
// Implementation would go here
|
|
},
|
|
interval: 1800000 // Every 30 minutes
|
|
});
|
|
}
|
|
|
|
registerTask(task: CleanupTask) {
|
|
this.tasks.set(task.name, task);
|
|
|
|
if (task.interval) {
|
|
// Clear existing interval if any
|
|
const existingInterval = this.intervals.get(task.name);
|
|
if (existingInterval) {
|
|
clearInterval(existingInterval);
|
|
}
|
|
|
|
// Set up new interval
|
|
const interval = setInterval(async () => {
|
|
try {
|
|
await task.cleanup();
|
|
} catch (error) {
|
|
console.error(`[Cleanup] Task '${task.name}' failed:`, error);
|
|
}
|
|
}, task.interval);
|
|
|
|
this.intervals.set(task.name, interval);
|
|
}
|
|
}
|
|
|
|
async runTask(taskName: string) {
|
|
const task = this.tasks.get(taskName);
|
|
if (!task) {
|
|
throw new Error(`Cleanup task '${taskName}' not found`);
|
|
}
|
|
|
|
try {
|
|
await task.cleanup();
|
|
console.log(`[Cleanup] Task '${taskName}' completed successfully`);
|
|
} catch (error) {
|
|
console.error(`[Cleanup] Task '${taskName}' failed:`, error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
async runAllTasks() {
|
|
console.log('[Cleanup] Running all cleanup tasks...');
|
|
const results: { task: string; success: boolean; error?: any }[] = [];
|
|
|
|
for (const [name, task] of this.tasks) {
|
|
try {
|
|
await task.cleanup();
|
|
results.push({ task: name, success: true });
|
|
} catch (error) {
|
|
results.push({ task: name, success: false, error });
|
|
}
|
|
}
|
|
|
|
return results;
|
|
}
|
|
|
|
stopAllIntervals() {
|
|
for (const [name, interval] of this.intervals) {
|
|
clearInterval(interval);
|
|
console.log(`[Cleanup] Stopped interval for task '${name}'`);
|
|
}
|
|
this.intervals.clear();
|
|
}
|
|
}
|
|
|
|
export const cleanupManager = CleanupManager.getInstance();
|
|
|
|
// Utility functions for common cleanup operations
|
|
export const cleanupUtils = {
|
|
// Clean up old files in a directory
|
|
async cleanupOldFiles(directory: string, maxAgeMs: number) {
|
|
// Implementation would check file ages and remove old ones
|
|
console.log(`[Cleanup] Would clean files older than ${maxAgeMs}ms in ${directory}`);
|
|
},
|
|
|
|
// Clean up unused stream handles
|
|
cleanupStreams(streams: any[]) {
|
|
streams.forEach(stream => {
|
|
if (stream && typeof stream.destroy === 'function') {
|
|
stream.destroy();
|
|
}
|
|
});
|
|
},
|
|
|
|
// Clean up IMAP connections
|
|
cleanupIMAPConnections(connections: any[]) {
|
|
connections.forEach(conn => {
|
|
try {
|
|
if (conn && typeof conn.end === 'function') {
|
|
conn.end();
|
|
}
|
|
} catch (error) {
|
|
console.error('[Cleanup] Failed to close IMAP connection:', error);
|
|
}
|
|
});
|
|
},
|
|
|
|
// Memory-efficient array processing
|
|
async processInBatches<T, R>(
|
|
items: T[],
|
|
batchSize: number,
|
|
processor: (batch: T[]) => Promise<R[]>
|
|
): Promise<R[]> {
|
|
const results: R[] = [];
|
|
|
|
for (let i = 0; i < items.length; i += batchSize) {
|
|
const batch = items.slice(i, i + batchSize);
|
|
const batchResults = await processor(batch);
|
|
results.push(...batchResults);
|
|
|
|
// Allow garbage collection between batches
|
|
await new Promise(resolve => setImmediate(resolve));
|
|
}
|
|
|
|
return results;
|
|
}
|
|
};
|