mirror of
https://github.com/Dictionarry-Hub/profilarr.git
synced 2026-01-22 19:01:02 +01:00
chore(paths): move jobs into src
This commit is contained in:
75
src/jobs/definitions/cleanupLogs.ts
Normal file
75
src/jobs/definitions/cleanupLogs.ts
Normal file
@@ -0,0 +1,75 @@
|
||||
import { config } from '$config';
|
||||
import { logSettingsQueries } from '$db/queries/logSettings.ts';
|
||||
import { logger } from '$logger';
|
||||
import { cleanupLogs } from '../lib/cleanupLogs.ts';
|
||||
import type { JobDefinition, JobResult } from '../types.ts';
|
||||
|
||||
/**
|
||||
* Cleanup old log files job
|
||||
* Deletes daily log files (YYYY-MM-DD.log) older than the configured retention period
|
||||
*/
|
||||
export const cleanupLogsJob: JobDefinition = {
|
||||
name: 'cleanup_logs',
|
||||
description: 'Delete log files according to retention policy',
|
||||
schedule: 'daily',
|
||||
|
||||
handler: async (): Promise<JobResult> => {
|
||||
try {
|
||||
// Get log settings
|
||||
const settings = logSettingsQueries.get();
|
||||
if (!settings) {
|
||||
return {
|
||||
success: false,
|
||||
error: 'Log settings not found'
|
||||
};
|
||||
}
|
||||
|
||||
const retentionDays = settings.retention_days;
|
||||
const logsDir = config.paths.logs;
|
||||
|
||||
// Calculate cutoff date for logging
|
||||
const cutoffDate = new Date();
|
||||
cutoffDate.setDate(cutoffDate.getDate() - retentionDays);
|
||||
const cutoffDateStr = cutoffDate.toISOString().split('T')[0];
|
||||
|
||||
await logger.info(`Cleaning up logs older than ${retentionDays} days`, {
|
||||
source: 'CleanupLogsJob',
|
||||
meta: { cutoffDate: cutoffDateStr }
|
||||
});
|
||||
|
||||
// Run cleanup
|
||||
const result = await cleanupLogs(logsDir, retentionDays);
|
||||
|
||||
// Log individual deletions
|
||||
// Note: We don't have access to which specific files were deleted anymore
|
||||
// If we need that, we can modify cleanupLogs to return the list
|
||||
|
||||
// Log errors
|
||||
for (const { file, error } of result.errors) {
|
||||
await logger.error(`Failed to process log file: ${file}`, {
|
||||
source: 'CleanupLogsJob',
|
||||
meta: { file, error }
|
||||
});
|
||||
}
|
||||
|
||||
const message = `Cleanup completed: deleted ${result.deletedCount} file(s), ${result.errorCount} error(s)`;
|
||||
|
||||
if (result.errorCount > 0 && result.deletedCount === 0) {
|
||||
return {
|
||||
success: false,
|
||||
error: message
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: message
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : String(error)
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
66
src/jobs/logic/cleanupLogs.ts
Normal file
66
src/jobs/logic/cleanupLogs.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* Core cleanup logic for log files
|
||||
* Separated from job definition to avoid database/config dependencies for testing
|
||||
*/
|
||||
|
||||
export interface CleanupLogsResult {
|
||||
deletedCount: number;
|
||||
errorCount: number;
|
||||
errors: Array<{ file: string; error: unknown }>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Core cleanup logic - deletes log files older than retention period
|
||||
* Pure function that only depends on Deno APIs
|
||||
*
|
||||
* @param logsDir Directory containing log files
|
||||
* @param retentionDays Number of days to retain logs
|
||||
* @returns Cleanup result with counts
|
||||
*/
|
||||
export async function cleanupLogs(
|
||||
logsDir: string,
|
||||
retentionDays: number,
|
||||
): Promise<CleanupLogsResult> {
|
||||
// Calculate cutoff date (YYYY-MM-DD format)
|
||||
const cutoffDate = new Date();
|
||||
cutoffDate.setDate(cutoffDate.getDate() - retentionDays);
|
||||
const cutoffDateStr = cutoffDate.toISOString().split("T")[0]; // YYYY-MM-DD
|
||||
|
||||
let deletedCount = 0;
|
||||
let errorCount = 0;
|
||||
const errors: Array<{ file: string; error: unknown }> = [];
|
||||
|
||||
// Regex to match daily log files: YYYY-MM-DD.log
|
||||
const dateLogPattern = /^(\d{4}-\d{2}-\d{2})\.log$/;
|
||||
|
||||
try {
|
||||
for await (const entry of Deno.readDir(logsDir)) {
|
||||
if (!entry.isFile) continue;
|
||||
|
||||
// Only process log files matching YYYY-MM-DD.log pattern
|
||||
const match = entry.name.match(dateLogPattern);
|
||||
if (!match) continue;
|
||||
|
||||
const logDate = match[1]; // Extract YYYY-MM-DD from filename
|
||||
const filePath = `${logsDir}/${entry.name}`;
|
||||
|
||||
try {
|
||||
// Compare date strings directly (YYYY-MM-DD format sorts correctly)
|
||||
if (logDate < cutoffDateStr) {
|
||||
await Deno.remove(filePath);
|
||||
deletedCount++;
|
||||
}
|
||||
} catch (error) {
|
||||
errorCount++;
|
||||
errors.push({ file: entry.name, error });
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
// If we can't read the directory at all, that's a critical error
|
||||
throw new Error(
|
||||
`Failed to read logs directory: ${error instanceof Error ? error.message : String(error)}`,
|
||||
);
|
||||
}
|
||||
|
||||
return { deletedCount, errorCount, errors };
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
import { config } from '$config';
|
||||
import { logSettingsQueries } from '$db/queries/logSettings.ts';
|
||||
import { logger } from '$logger';
|
||||
import type { JobDefinition, JobResult } from '../types.ts';
|
||||
|
||||
/**
|
||||
* Cleanup old log files job
|
||||
* Deletes daily log files (YYYY-MM-DD.log) older than the configured retention period
|
||||
*/
|
||||
export const cleanupLogsJob: JobDefinition = {
|
||||
name: 'cleanup_logs',
|
||||
description: 'Delete log files according to retention policy',
|
||||
schedule: 'daily',
|
||||
|
||||
handler: async (): Promise<JobResult> => {
|
||||
try {
|
||||
// Get log settings
|
||||
const settings = logSettingsQueries.get();
|
||||
if (!settings) {
|
||||
return {
|
||||
success: false,
|
||||
error: 'Log settings not found'
|
||||
};
|
||||
}
|
||||
|
||||
const retentionDays = settings.retention_days;
|
||||
const logsDir = config.paths.logs;
|
||||
|
||||
// Calculate cutoff date (YYYY-MM-DD format)
|
||||
const cutoffDate = new Date();
|
||||
cutoffDate.setDate(cutoffDate.getDate() - retentionDays);
|
||||
const cutoffDateStr = cutoffDate.toISOString().split('T')[0]; // YYYY-MM-DD
|
||||
|
||||
await logger.info(`Cleaning up logs older than ${retentionDays} days`, {
|
||||
source: 'CleanupLogsJob',
|
||||
meta: { cutoffDate: cutoffDateStr }
|
||||
});
|
||||
|
||||
// Read all files in logs directory
|
||||
let deletedCount = 0;
|
||||
let errorCount = 0;
|
||||
|
||||
// Regex to match daily log files: YYYY-MM-DD.log
|
||||
const dateLogPattern = /^(\d{4}-\d{2}-\d{2})\.log$/;
|
||||
|
||||
try {
|
||||
for await (const entry of Deno.readDir(logsDir)) {
|
||||
if (!entry.isFile) continue;
|
||||
|
||||
// Only process log files matching YYYY-MM-DD.log pattern
|
||||
const match = entry.name.match(dateLogPattern);
|
||||
if (!match) continue;
|
||||
|
||||
const logDate = match[1]; // Extract YYYY-MM-DD from filename
|
||||
const filePath = `${logsDir}/${entry.name}`;
|
||||
|
||||
try {
|
||||
// Compare date strings directly (YYYY-MM-DD format sorts correctly)
|
||||
if (logDate < cutoffDateStr) {
|
||||
await Deno.remove(filePath);
|
||||
deletedCount++;
|
||||
|
||||
await logger.info(`Deleted old log file: ${entry.name}`, {
|
||||
source: 'CleanupLogsJob',
|
||||
meta: { file: entry.name, logDate }
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
errorCount++;
|
||||
await logger.error(`Failed to process log file: ${entry.name}`, {
|
||||
source: 'CleanupLogsJob',
|
||||
meta: { file: entry.name, error }
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
success: false,
|
||||
error: `Failed to read logs directory: ${
|
||||
error instanceof Error ? error.message : String(error)
|
||||
}`
|
||||
};
|
||||
}
|
||||
|
||||
const message = `Cleanup completed: deleted ${deletedCount} file(s), ${errorCount} error(s)`;
|
||||
|
||||
if (errorCount > 0 && deletedCount === 0) {
|
||||
return {
|
||||
success: false,
|
||||
error: message
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: message
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : String(error)
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user