mirror of
https://github.com/khoaliber/dockhand.git
synced 2026-03-05 13:20:57 +00:00
Initial commit
This commit is contained in:
202
lib/server/scheduler/tasks/system-cleanup.ts
Normal file
202
lib/server/scheduler/tasks/system-cleanup.ts
Normal file
@@ -0,0 +1,202 @@
|
||||
/**
|
||||
* 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
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user