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:
@@ -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
|
||||
});
|
||||
|
||||
@@ -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'
|
||||
});
|
||||
|
||||
@@ -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 };
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user