mirror of
https://github.com/khoaliber/dockhand.git
synced 2026-03-03 05:29:05 +00:00
203 lines
5.7 KiB
TypeScript
203 lines
5.7 KiB
TypeScript
/**
|
|
* System Cleanup Tasks
|
|
*
|
|
* Handles system cleanup jobs (schedule executions, container events).
|
|
*/
|
|
|
|
import type { ScheduleTrigger } from '../../db';
|
|
import {
|
|
getScheduleRetentionDays,
|
|
cleanupOldExecutions,
|
|
getEventRetentionDays,
|
|
getScheduleCleanupEnabled,
|
|
getEventCleanupEnabled,
|
|
createScheduleExecution,
|
|
updateScheduleExecution,
|
|
appendScheduleExecutionLog
|
|
} from '../../db';
|
|
|
|
// System job IDs
|
|
export const SYSTEM_SCHEDULE_CLEANUP_ID = 1;
|
|
export const SYSTEM_EVENT_CLEANUP_ID = 2;
|
|
export const SYSTEM_VOLUME_HELPER_CLEANUP_ID = 3;
|
|
|
|
/**
|
|
* Execute schedule execution cleanup job.
|
|
*/
|
|
export async function runScheduleCleanupJob(triggeredBy: ScheduleTrigger = 'cron'): Promise<void> {
|
|
// Check if cleanup is enabled (skip check if manually triggered)
|
|
if (triggeredBy === 'cron') {
|
|
const enabled = await getScheduleCleanupEnabled();
|
|
if (!enabled) {
|
|
return; // Skip execution if disabled
|
|
}
|
|
}
|
|
|
|
const startTime = Date.now();
|
|
|
|
// Create execution record
|
|
const execution = await createScheduleExecution({
|
|
scheduleType: 'system_cleanup',
|
|
scheduleId: SYSTEM_SCHEDULE_CLEANUP_ID,
|
|
environmentId: null,
|
|
entityName: 'Schedule execution cleanup',
|
|
triggeredBy,
|
|
status: 'running'
|
|
});
|
|
|
|
await updateScheduleExecution(execution.id, {
|
|
startedAt: new Date().toISOString()
|
|
});
|
|
|
|
const log = async (message: string) => {
|
|
console.log(`[Schedule Cleanup] ${message}`);
|
|
await appendScheduleExecutionLog(execution.id, `[${new Date().toISOString()}] ${message}`);
|
|
};
|
|
|
|
try {
|
|
const retentionDays = await getScheduleRetentionDays();
|
|
await log(`Starting cleanup with ${retentionDays} day retention`);
|
|
|
|
await cleanupOldExecutions(retentionDays);
|
|
|
|
await log('Cleanup completed successfully');
|
|
await updateScheduleExecution(execution.id, {
|
|
status: 'success',
|
|
completedAt: new Date().toISOString(),
|
|
duration: Date.now() - startTime,
|
|
details: { retentionDays }
|
|
});
|
|
} catch (error: any) {
|
|
await log(`Error: ${error.message}`);
|
|
await updateScheduleExecution(execution.id, {
|
|
status: 'failed',
|
|
completedAt: new Date().toISOString(),
|
|
duration: Date.now() - startTime,
|
|
errorMessage: error.message
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Execute event cleanup job.
|
|
*/
|
|
export async function runEventCleanupJob(triggeredBy: ScheduleTrigger = 'cron'): Promise<void> {
|
|
// Check if cleanup is enabled (skip check if manually triggered)
|
|
if (triggeredBy === 'cron') {
|
|
const enabled = await getEventCleanupEnabled();
|
|
if (!enabled) {
|
|
return; // Skip execution if disabled
|
|
}
|
|
}
|
|
|
|
const startTime = Date.now();
|
|
|
|
// Create execution record
|
|
const execution = await createScheduleExecution({
|
|
scheduleType: 'system_cleanup',
|
|
scheduleId: SYSTEM_EVENT_CLEANUP_ID,
|
|
environmentId: null,
|
|
entityName: 'Container event cleanup',
|
|
triggeredBy,
|
|
status: 'running'
|
|
});
|
|
|
|
await updateScheduleExecution(execution.id, {
|
|
startedAt: new Date().toISOString()
|
|
});
|
|
|
|
const log = async (message: string) => {
|
|
console.log(`[Event Cleanup] ${message}`);
|
|
await appendScheduleExecutionLog(execution.id, `[${new Date().toISOString()}] ${message}`);
|
|
};
|
|
|
|
try {
|
|
const { deleteOldContainerEvents } = await import('../../db');
|
|
const retentionDays = await getEventRetentionDays();
|
|
|
|
await log(`Starting cleanup of events older than ${retentionDays} days`);
|
|
|
|
const deleted = await deleteOldContainerEvents(retentionDays);
|
|
|
|
await log(`Removed ${deleted} old container events`);
|
|
await updateScheduleExecution(execution.id, {
|
|
status: 'success',
|
|
completedAt: new Date().toISOString(),
|
|
duration: Date.now() - startTime,
|
|
details: { deletedCount: deleted, retentionDays }
|
|
});
|
|
} catch (error: any) {
|
|
await log(`Error: ${error.message}`);
|
|
await updateScheduleExecution(execution.id, {
|
|
status: 'failed',
|
|
completedAt: new Date().toISOString(),
|
|
duration: Date.now() - startTime,
|
|
errorMessage: error.message
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Execute volume helper cleanup job.
|
|
* Cleans up stale dockhand-browse-* containers used for volume browsing.
|
|
* @param triggeredBy - What triggered this execution
|
|
* @param cleanupFns - Optional cleanup functions (passed from scheduler to avoid dynamic import issues)
|
|
*/
|
|
export async function runVolumeHelperCleanupJob(
|
|
triggeredBy: ScheduleTrigger = 'cron',
|
|
cleanupFns?: {
|
|
cleanupStaleVolumeHelpers: () => Promise<void>;
|
|
cleanupExpiredVolumeHelpers: () => Promise<void>;
|
|
}
|
|
): Promise<void> {
|
|
const startTime = Date.now();
|
|
|
|
// Create execution record
|
|
const execution = await createScheduleExecution({
|
|
scheduleType: 'system_cleanup',
|
|
scheduleId: SYSTEM_VOLUME_HELPER_CLEANUP_ID,
|
|
environmentId: null,
|
|
entityName: 'Volume helper cleanup',
|
|
triggeredBy,
|
|
status: 'running'
|
|
});
|
|
|
|
await updateScheduleExecution(execution.id, {
|
|
startedAt: new Date().toISOString()
|
|
});
|
|
|
|
const log = async (message: string) => {
|
|
console.log(`[Volume Helper Cleanup] ${message}`);
|
|
await appendScheduleExecutionLog(execution.id, `[${new Date().toISOString()}] ${message}`);
|
|
};
|
|
|
|
try {
|
|
await log('Starting cleanup of stale and expired volume helper containers');
|
|
|
|
if (cleanupFns) {
|
|
// Use provided functions (from scheduler static imports)
|
|
await cleanupFns.cleanupStaleVolumeHelpers();
|
|
await cleanupFns.cleanupExpiredVolumeHelpers();
|
|
} else {
|
|
// Fallback to dynamic import (may not work in production)
|
|
const { runVolumeHelperCleanup } = await import('../../db');
|
|
await runVolumeHelperCleanup();
|
|
}
|
|
|
|
await log('Cleanup completed successfully');
|
|
await updateScheduleExecution(execution.id, {
|
|
status: 'success',
|
|
completedAt: new Date().toISOString(),
|
|
duration: Date.now() - startTime
|
|
});
|
|
} catch (error: any) {
|
|
await log(`Error: ${error.message}`);
|
|
await updateScheduleExecution(execution.id, {
|
|
status: 'failed',
|
|
completedAt: new Date().toISOString(),
|
|
duration: Date.now() - startTime,
|
|
errorMessage: error.message
|
|
});
|
|
}
|
|
}
|