feat(logging): implement change tracking and logging for media settings and naming updates

This commit is contained in:
Sam Chau
2026-01-03 02:01:38 +10:30
parent fc2211c146
commit e44228d147
4 changed files with 137 additions and 45 deletions

View File

@@ -5,6 +5,7 @@
import type { PCDCache } from '../../cache.ts';
import { writeOperation, type OperationLayer } from '../../writer.ts';
import { logger } from '$logger/logger.ts';
import type {
PropersRepacks,
ColonReplacementFormat,
@@ -52,6 +53,20 @@ export async function updateRadarrMediaSettings(options: UpdateMediaSettingsOpti
.where('enable_media_info', '=', current.enable_media_info ? 1 : 0)
.compile();
// Track changes
const changes: Record<string, { from: unknown; to: unknown }> = {};
if (current.propers_repacks !== input.propers_repacks) {
changes.propers_repacks = { from: current.propers_repacks, to: input.propers_repacks };
}
if (current.enable_media_info !== input.enable_media_info) {
changes.enable_media_info = { from: current.enable_media_info, to: input.enable_media_info };
}
await logger.info('Save radarr media settings', {
source: 'MediaManagement',
meta: { id: current.id, changes }
});
return await writeOperation({
databaseId,
layer,
@@ -84,6 +99,20 @@ export async function updateSonarrMediaSettings(options: UpdateMediaSettingsOpti
.where('enable_media_info', '=', current.enable_media_info ? 1 : 0)
.compile();
// Track changes
const changes: Record<string, { from: unknown; to: unknown }> = {};
if (current.propers_repacks !== input.propers_repacks) {
changes.propers_repacks = { from: current.propers_repacks, to: input.propers_repacks };
}
if (current.enable_media_info !== input.enable_media_info) {
changes.enable_media_info = { from: current.enable_media_info, to: input.enable_media_info };
}
await logger.info('Save sonarr media settings', {
source: 'MediaManagement',
meta: { id: current.id, changes }
});
return await writeOperation({
databaseId,
layer,
@@ -149,6 +178,44 @@ export async function updateSonarrNaming(options: UpdateSonarrNamingOptions) {
.where('replace_illegal_characters', '=', current.replace_illegal_characters ? 1 : 0)
.compile();
// Track changes
const changes: Record<string, { from: unknown; to: unknown }> = {};
if (current.rename !== input.rename) {
changes.rename = { from: current.rename, to: input.rename };
}
if (current.replace_illegal_characters !== input.replace_illegal_characters) {
changes.replace_illegal_characters = { from: current.replace_illegal_characters, to: input.replace_illegal_characters };
}
if (current.colon_replacement_format !== input.colon_replacement_format) {
changes.colon_replacement_format = { from: current.colon_replacement_format, to: input.colon_replacement_format };
}
if (current.custom_colon_replacement_format !== input.custom_colon_replacement_format) {
changes.custom_colon_replacement_format = { from: current.custom_colon_replacement_format, to: input.custom_colon_replacement_format };
}
if (current.standard_episode_format !== input.standard_episode_format) {
changes.standard_episode_format = { from: current.standard_episode_format, to: input.standard_episode_format };
}
if (current.daily_episode_format !== input.daily_episode_format) {
changes.daily_episode_format = { from: current.daily_episode_format, to: input.daily_episode_format };
}
if (current.anime_episode_format !== input.anime_episode_format) {
changes.anime_episode_format = { from: current.anime_episode_format, to: input.anime_episode_format };
}
if (current.series_folder_format !== input.series_folder_format) {
changes.series_folder_format = { from: current.series_folder_format, to: input.series_folder_format };
}
if (current.season_folder_format !== input.season_folder_format) {
changes.season_folder_format = { from: current.season_folder_format, to: input.season_folder_format };
}
if (current.multi_episode_style !== input.multi_episode_style) {
changes.multi_episode_style = { from: current.multi_episode_style, to: input.multi_episode_style };
}
await logger.info('Save sonarr naming settings', {
source: 'MediaManagement',
meta: { id: current.id, changes }
});
return await writeOperation({
databaseId,
layer,
@@ -204,6 +271,29 @@ export async function updateRadarrNaming(options: UpdateRadarrNamingOptions) {
.where('replace_illegal_characters', '=', current.replace_illegal_characters ? 1 : 0)
.compile();
// Track changes
const changes: Record<string, { from: unknown; to: unknown }> = {};
if (current.rename !== input.rename) {
changes.rename = { from: current.rename, to: input.rename };
}
if (current.replace_illegal_characters !== input.replace_illegal_characters) {
changes.replace_illegal_characters = { from: current.replace_illegal_characters, to: input.replace_illegal_characters };
}
if (current.colon_replacement_format !== input.colon_replacement_format) {
changes.colon_replacement_format = { from: current.colon_replacement_format, to: input.colon_replacement_format };
}
if (current.movie_format !== input.movie_format) {
changes.movie_format = { from: current.movie_format, to: input.movie_format };
}
if (current.movie_folder_format !== input.movie_folder_format) {
changes.movie_folder_format = { from: current.movie_folder_format, to: input.movie_folder_format };
}
await logger.info('Save radarr naming settings', {
source: 'MediaManagement',
meta: { id: current.id, changes }
});
return await writeOperation({
databaseId,
layer,
@@ -245,6 +335,9 @@ export async function updateRadarrQualityDefinitions(options: UpdateQualityDefin
const { databaseId, cache, layer, current, input } = options;
const db = cache.kb;
// Track changes per quality definition
const changes: Record<string, { from: unknown; to: unknown }> = {};
// Build queries for each changed definition
const queries = input.map((def) => {
const currentDef = current.find((c) => c.quality_id === def.quality_id);
@@ -252,6 +345,21 @@ export async function updateRadarrQualityDefinitions(options: UpdateQualityDefin
throw new Error(`Quality definition not found for quality_id: ${def.quality_id}`);
}
// Track changes for this definition
const defChanges: Record<string, { from: unknown; to: unknown }> = {};
if (currentDef.min_size !== def.min_size) {
defChanges.min_size = { from: currentDef.min_size, to: def.min_size };
}
if (currentDef.max_size !== def.max_size) {
defChanges.max_size = { from: currentDef.max_size, to: def.max_size };
}
if (currentDef.preferred_size !== def.preferred_size) {
defChanges.preferred_size = { from: currentDef.preferred_size, to: def.preferred_size };
}
if (Object.keys(defChanges).length > 0) {
changes[currentDef.quality_name] = defChanges as { from: unknown; to: unknown };
}
return db
.updateTable('radarr_quality_definitions')
.set({
@@ -267,6 +375,11 @@ export async function updateRadarrQualityDefinitions(options: UpdateQualityDefin
.compile();
});
await logger.info('Save radarr quality definitions', {
source: 'MediaManagement',
meta: { changes }
});
return await writeOperation({
databaseId,
layer,
@@ -287,6 +400,9 @@ export async function updateSonarrQualityDefinitions(options: UpdateQualityDefin
const { databaseId, cache, layer, current, input } = options;
const db = cache.kb;
// Track changes per quality definition
const changes: Record<string, { from: unknown; to: unknown }> = {};
// Build queries for each changed definition
const queries = input.map((def) => {
const currentDef = current.find((c) => c.quality_id === def.quality_id);
@@ -294,6 +410,21 @@ export async function updateSonarrQualityDefinitions(options: UpdateQualityDefin
throw new Error(`Quality definition not found for quality_id: ${def.quality_id}`);
}
// Track changes for this definition
const defChanges: Record<string, { from: unknown; to: unknown }> = {};
if (currentDef.min_size !== def.min_size) {
defChanges.min_size = { from: currentDef.min_size, to: def.min_size };
}
if (currentDef.max_size !== def.max_size) {
defChanges.max_size = { from: currentDef.max_size, to: def.max_size };
}
if (currentDef.preferred_size !== def.preferred_size) {
defChanges.preferred_size = { from: currentDef.preferred_size, to: def.preferred_size };
}
if (Object.keys(defChanges).length > 0) {
changes[currentDef.quality_name] = defChanges as { from: unknown; to: unknown };
}
return db
.updateTable('sonarr_quality_definitions')
.set({
@@ -309,6 +440,11 @@ export async function updateSonarrQualityDefinitions(options: UpdateQualityDefin
.compile();
});
await logger.info('Save sonarr quality definitions', {
source: 'MediaManagement',
meta: { changes }
});
return await writeOperation({
databaseId,
layer,

View File

@@ -331,7 +331,7 @@ export async function writeOperation(options: WriteOptions): Promise<WriteResult
// This avoids waiting for the file watcher's debounce delay
await compile(instance.local_path, instance.id);
await logger.info('Cache recompiled after write', {
await logger.debug('Cache recompiled after write', {
source: 'PCDWriter',
meta: { databaseId }
});

View File

@@ -96,11 +96,6 @@ export const actions: Actions = {
return fail(500, { error: result.error || 'Failed to update media settings' });
}
await logger.info('Radarr media settings updated', {
source: 'MediaManagement',
meta: { databaseId: currentDatabaseId, layer, propersRepacks, enableMediaInfo }
});
return { success: true };
},
@@ -181,17 +176,6 @@ export const actions: Actions = {
return fail(500, { error: result.error || 'Failed to update naming settings' });
}
await logger.info('Radarr naming settings updated', {
source: 'MediaManagement',
meta: {
databaseId: currentDatabaseId,
layer,
rename,
replaceIllegalCharacters,
colonReplacement: effectiveColonReplacement
}
});
return { success: true };
},
@@ -262,11 +246,6 @@ export const actions: Actions = {
return fail(500, { error: result.error || 'Failed to update quality definitions' });
}
await logger.info('Radarr quality definitions updated', {
source: 'MediaManagement',
meta: { databaseId: currentDatabaseId, layer, definitionsCount: definitions.length }
});
return { success: true };
}
};

View File

@@ -96,11 +96,6 @@ export const actions: Actions = {
return fail(500, { error: result.error || 'Failed to update media settings' });
}
await logger.info('Sonarr media settings updated', {
source: 'MediaManagement',
meta: { databaseId: currentDatabaseId, layer, propersRepacks, enableMediaInfo }
});
return { success: true };
},
@@ -201,19 +196,6 @@ export const actions: Actions = {
return fail(500, { error: result.error || 'Failed to update naming settings' });
}
await logger.info('Sonarr naming settings updated', {
source: 'MediaManagement',
meta: {
databaseId: currentDatabaseId,
layer,
rename,
replaceIllegalCharacters,
colonReplacement: effectiveColonReplacement,
customColonReplacement: effectiveColonReplacement === 'custom' ? customColonReplacement : null,
multiEpisodeStyle
}
});
return { success: true };
},
@@ -284,11 +266,6 @@ export const actions: Actions = {
return fail(500, { error: result.error || 'Failed to update quality definitions' });
}
await logger.info('Sonarr quality definitions updated', {
source: 'MediaManagement',
meta: { databaseId: currentDatabaseId, layer, definitionsCount: definitions.length }
});
return { success: true };
}
};