Refactor backend configuration and enhance logging in services

Updated config.js to ensure .env is loaded correctly from the backend directory. Enhanced MyTischtennisUrlController by removing unnecessary console logs and improving error handling. Updated autoFetchMatchResultsService and autoUpdateRatingsService to return detailed summaries, including counts of fetched or updated items. Improved logging in schedulerService to capture execution details, enhancing monitoring capabilities across scheduled tasks.
This commit is contained in:
Torsten Schulz (local)
2025-10-30 08:14:17 +01:00
parent 89329607dc
commit 3f2b92d886
6 changed files with 81 additions and 112 deletions

View File

@@ -54,14 +54,37 @@ class ApiLogService {
*/
async logSchedulerExecution(jobType, success, message, executionTime = null, errorMessage = null) {
try {
// Allow optional counts object in message by accepting message as string or object
const truncate = (str, maxLen = 10000) => {
if (!str) return null;
const strVal = typeof str === 'string' ? str : JSON.stringify(str);
return strVal.length > maxLen ? strVal.substring(0, maxLen) + '... (truncated)' : strVal;
};
// If message is an object with details, keep it; otherwise wrap into an object
let responseObj = null;
try {
if (typeof message === 'object' && message !== null) {
responseObj = message;
} else {
responseObj = { message };
}
} catch (e) {
responseObj = { message: String(message) };
}
// If executionTime or errorMessage present, add to response object for visibility
if (executionTime !== null) responseObj.executionTime = executionTime;
if (errorMessage) responseObj.errorMessage = errorMessage;
await ApiLog.create({
userId: null,
method: 'SCHEDULER',
path: `/scheduler/${jobType}`,
statusCode: success ? 200 : 500,
responseBody: message,
responseBody: truncate(JSON.stringify(responseObj)),
executionTime,
errorMessage,
errorMessage: truncate(errorMessage, 5000),
logType: 'scheduler',
schedulerJobType: jobType
});

View File

@@ -36,14 +36,20 @@ class AutoFetchMatchResultsService {
return;
}
// Process each account
// Process each account and collect summaries
const summaries = [];
for (const account of accounts) {
await this.processAccount(account);
const summary = await this.processAccount(account);
summaries.push({ userId: account.userId, ...summary });
}
devLog('Automatic match results fetch completed');
// Return overall summary including per-account counts
const totalFetched = summaries.reduce((acc, s) => acc + (s.fetchedCount || 0), 0);
return { success: true, totalFetched, summaries };
} catch (error) {
console.error('Error in automatic match results fetch:', error);
throw error;
}
}
@@ -85,13 +91,13 @@ class AutoFetchMatchResultsService {
devLog(`Successfully re-logged in for ${account.email}`);
}
// Perform match results fetch
const fetchResult = await this.fetchMatchResults(account);
fetchedCount = fetchResult.fetchedCount || 0;
// Perform match results fetch
const fetchResult = await this.fetchMatchResults(account);
fetchedCount = fetchResult.fetchedCount || 0;
success = true;
message = `Successfully fetched ${fetchedCount} match results`;
devLog(`Fetched ${fetchedCount} match results for ${account.email}`);
success = true;
message = `Successfully fetched ${fetchedCount} match results`;
devLog(`Fetched ${fetchedCount} match results for ${account.email}`);
} catch (error) {
success = false;
@@ -116,7 +122,10 @@ class AutoFetchMatchResultsService {
}
);
devLog(`Match results fetch for ${account.email}: ${success ? 'SUCCESS' : 'FAILED'} (${executionTime}ms)`);
devLog(`Match results fetch for ${account.email}: ${success ? 'SUCCESS' : 'FAILED'} (${executionTime}ms)`);
// Return a summary for scheduler
return { success, message, fetchedCount, errorDetails, executionTime };
}
/**
@@ -236,14 +245,12 @@ class AutoFetchMatchResultsService {
fetchExecutionTime = Date.now() - fetchStartTime;
responseStatus = playerStatsResponse.status;
if (playerStatsResponse.ok) {
if (playerStatsResponse.ok) {
const playerStatsData = await playerStatsResponse.json();
responseBodyData = playerStatsData;
// Log complete response for debugging
console.log('=== PLAYER STATS RESPONSE START ===');
console.log(JSON.stringify(playerStatsData, null, 2));
console.log('=== PLAYER STATS RESPONSE END ===');
// Avoid dumping full JSON to console; use devLog for compact info
devLog(`Received player stats for team ${team.name} - balancesheet entries: ${Array.isArray(playerStatsData.data?.balancesheet) ? playerStatsData.data.balancesheet.length : 0}`);
const playerCount = await this.processTeamData(team, playerStatsData);
totalProcessed += playerCount;
@@ -824,7 +831,7 @@ class AutoFetchMatchResultsService {
// Fetch table data from MyTischtennis
const tableUrl = `https://www.mytischtennis.de/click-tt/${league.association}/${seasonStr}/ligen/${league.groupname}/gruppe/${league.myTischtennisGroupId}/tabelle/gesamt?_data=routes%2Fclick-tt%2B%2F%24association%2B%2F%24season%2B%2F%24type%2B%2F%24groupname.gruppe.%24urlid%2B%2Ftabelle.%24filter`;
console.log(`[fetchAndUpdateLeagueTable] Fetching table from URL: ${tableUrl}`);
devLog(`[fetchAndUpdateLeagueTable] Fetching table from URL: ${tableUrl}`);
const response = await myTischtennisClient.authenticatedRequest(tableUrl, session.cookie, {
method: 'GET'
});

View File

@@ -29,12 +29,16 @@ class AutoUpdateRatingsService {
return;
}
// Process each account
// Process each account and collect summaries
const summaries = [];
for (const account of accounts) {
await this.processAccount(account);
const summary = await this.processAccount(account);
summaries.push({ userId: account.userId, ...summary });
}
devLog('Automatic rating updates completed');
const totalUpdated = summaries.reduce((acc, s) => acc + (s.updatedCount || 0), 0);
return { success: true, totalUpdated, summaries };
} catch (error) {
console.error('Error in automatic rating updates:', error);
}
@@ -118,6 +122,9 @@ class AutoUpdateRatingsService {
updatedCount,
executionTime
);
// Return summary for scheduler
return { success, message, updatedCount, errorDetails, executionTime };
}
/**

View File

@@ -33,14 +33,16 @@ class SchedulerService {
let errorMessage = null;
try {
await autoUpdateRatingsService.executeAutomaticUpdates();
// Let the service return details including counts if available
const result = await autoUpdateRatingsService.executeAutomaticUpdates();
const executionTime = Date.now() - startTime;
success = true;
message = 'Rating updates completed successfully';
// result may include updatedCount or a summary object
const messageObj = result && typeof result === 'object' ? result : { message: 'Rating updates completed successfully' };
console.log(`[${new Date().toISOString()}] CRON: Rating updates completed successfully`);
// Log to ApiLog
await apiLogService.logSchedulerExecution('rating_updates', true, message, executionTime, null);
// Log to ApiLog with rich details
await apiLogService.logSchedulerExecution('rating_updates', true, messageObj, executionTime, null);
} catch (error) {
const executionTime = Date.now() - startTime;
success = false;
@@ -49,7 +51,7 @@ class SchedulerService {
console.error('Stack trace:', error.stack);
// Log to ApiLog
await apiLogService.logSchedulerExecution('rating_updates', false, 'Rating updates failed', executionTime, errorMessage);
await apiLogService.logSchedulerExecution('rating_updates', false, { message: 'Rating updates failed' }, executionTime, errorMessage);
}
}, {
scheduled: false, // Don't start automatically
@@ -72,14 +74,15 @@ class SchedulerService {
let errorMessage = null;
try {
await autoFetchMatchResultsService.executeAutomaticFetch();
// Execute and capture returned summary (should include counts)
const result = await autoFetchMatchResultsService.executeAutomaticFetch();
const executionTime = Date.now() - startTime;
success = true;
message = 'Match results fetch completed successfully';
const messageObj = result && typeof result === 'object' ? result : { message: 'Match results fetch completed successfully' };
console.log(`[${new Date().toISOString()}] CRON: Match results fetch completed successfully`);
// Log to ApiLog
await apiLogService.logSchedulerExecution('match_results', true, message, executionTime, null);
// Log to ApiLog with rich details (including counts if present)
await apiLogService.logSchedulerExecution('match_results', true, messageObj, executionTime, null);
} catch (error) {
const executionTime = Date.now() - startTime;
success = false;
@@ -88,7 +91,7 @@ class SchedulerService {
console.error('Stack trace:', error.stack);
// Log to ApiLog
await apiLogService.logSchedulerExecution('match_results', false, 'Match results fetch failed', executionTime, errorMessage);
await apiLogService.logSchedulerExecution('match_results', false, { message: 'Match results fetch failed' }, executionTime, errorMessage);
}
}, {
scheduled: false, // Don't start automatically