Add MyTischtennis fetch log functionality and new endpoints
Enhance MyTischtennis integration by introducing fetch log capabilities. Implement new controller methods to retrieve fetch logs and latest successful fetches for users. Update routes to include these new endpoints. Modify the MyTischtennis model to support fetch logs and ensure proper logging of fetch operations in various services. Update frontend components to display fetch statistics, improving user experience and data visibility.
This commit is contained in:
@@ -145,9 +145,11 @@ class MemberService {
|
||||
await checkAccess(userToken, clubId);
|
||||
|
||||
const user = await getUserByToken(userToken);
|
||||
const startTime = Date.now();
|
||||
|
||||
const myTischtennisService = (await import('./myTischtennisService.js')).default;
|
||||
const myTischtennisClient = (await import('../clients/myTischtennisClient.js')).default;
|
||||
const fetchLogService = (await import('./myTischtennisFetchLogService.js')).default;
|
||||
|
||||
try {
|
||||
// 1. myTischtennis-Session abrufen oder Login durchführen
|
||||
@@ -296,6 +298,19 @@ class MemberService {
|
||||
message += ` ${errors.length} Fehler beim Speichern.`;
|
||||
}
|
||||
|
||||
// Log successful ratings fetch
|
||||
await fetchLogService.logFetch(
|
||||
user.id,
|
||||
'ratings',
|
||||
true,
|
||||
message,
|
||||
{
|
||||
recordsProcessed: updated,
|
||||
executionTime: Date.now() - startTime,
|
||||
isAutomatic: false
|
||||
}
|
||||
);
|
||||
|
||||
return {
|
||||
status: 200,
|
||||
response: {
|
||||
@@ -310,6 +325,20 @@ class MemberService {
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('[updateRatingsFromMyTischtennis] - Error:', error);
|
||||
|
||||
// Log failed ratings fetch
|
||||
await fetchLogService.logFetch(
|
||||
user.id,
|
||||
'ratings',
|
||||
false,
|
||||
'Fehler beim Aktualisieren der Wertungen',
|
||||
{
|
||||
errorDetails: error.message,
|
||||
executionTime: Date.now() - startTime,
|
||||
isAutomatic: false
|
||||
}
|
||||
);
|
||||
|
||||
return {
|
||||
status: 500,
|
||||
response: {
|
||||
|
||||
129
backend/services/myTischtennisFetchLogService.js
Normal file
129
backend/services/myTischtennisFetchLogService.js
Normal file
@@ -0,0 +1,129 @@
|
||||
import MyTischtennisFetchLog from '../models/MyTischtennisFetchLog.js';
|
||||
import { devLog } from '../utils/logger.js';
|
||||
import { Op } from 'sequelize';
|
||||
import sequelize from '../database.js';
|
||||
|
||||
class MyTischtennisFetchLogService {
|
||||
/**
|
||||
* Log a fetch attempt
|
||||
*/
|
||||
async logFetch(userId, fetchType, success, message, options = {}) {
|
||||
try {
|
||||
await MyTischtennisFetchLog.create({
|
||||
userId,
|
||||
fetchType,
|
||||
success,
|
||||
message,
|
||||
errorDetails: options.errorDetails || null,
|
||||
recordsProcessed: options.recordsProcessed || 0,
|
||||
executionTime: options.executionTime || null,
|
||||
isAutomatic: options.isAutomatic || false
|
||||
});
|
||||
|
||||
devLog(`[FetchLog] ${fetchType} - ${success ? 'SUCCESS' : 'FAILED'} - User ${userId}`);
|
||||
} catch (error) {
|
||||
console.error('Error logging fetch:', error);
|
||||
// Don't throw - logging failures shouldn't break the main operation
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get fetch logs for a user
|
||||
*/
|
||||
async getFetchLogs(userId, options = {}) {
|
||||
try {
|
||||
const where = { userId };
|
||||
|
||||
if (options.fetchType) {
|
||||
where.fetchType = options.fetchType;
|
||||
}
|
||||
|
||||
if (options.success !== undefined) {
|
||||
where.success = options.success;
|
||||
}
|
||||
|
||||
const logs = await MyTischtennisFetchLog.findAll({
|
||||
where,
|
||||
order: [['createdAt', 'DESC']],
|
||||
limit: options.limit || 50,
|
||||
attributes: [
|
||||
'id', 'fetchType', 'success', 'message', 'errorDetails',
|
||||
'recordsProcessed', 'executionTime', 'isAutomatic', 'createdAt'
|
||||
]
|
||||
});
|
||||
|
||||
return logs;
|
||||
} catch (error) {
|
||||
console.error('Error getting fetch logs:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get latest successful fetch for each type
|
||||
*/
|
||||
async getLatestSuccessfulFetches(userId) {
|
||||
try {
|
||||
const fetchTypes = ['ratings', 'match_results', 'league_table'];
|
||||
const results = {};
|
||||
|
||||
for (const fetchType of fetchTypes) {
|
||||
const latestFetch = await MyTischtennisFetchLog.findOne({
|
||||
where: {
|
||||
userId,
|
||||
fetchType,
|
||||
success: true
|
||||
},
|
||||
order: [['createdAt', 'DESC']],
|
||||
attributes: ['createdAt', 'recordsProcessed', 'executionTime']
|
||||
});
|
||||
|
||||
results[fetchType] = latestFetch ? {
|
||||
lastFetch: latestFetch.createdAt,
|
||||
recordsProcessed: latestFetch.recordsProcessed,
|
||||
executionTime: latestFetch.executionTime
|
||||
} : null;
|
||||
}
|
||||
|
||||
return results;
|
||||
} catch (error) {
|
||||
console.error('Error getting latest successful fetches:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get fetch statistics
|
||||
*/
|
||||
async getFetchStatistics(userId, days = 30) {
|
||||
try {
|
||||
const since = new Date();
|
||||
since.setDate(since.getDate() - days);
|
||||
|
||||
const stats = await MyTischtennisFetchLog.findAll({
|
||||
where: {
|
||||
userId,
|
||||
createdAt: {
|
||||
[Op.gte]: since
|
||||
}
|
||||
},
|
||||
attributes: [
|
||||
'fetchType',
|
||||
[sequelize.fn('COUNT', sequelize.col('id')), 'totalFetches'],
|
||||
[sequelize.fn('SUM', sequelize.literal('CASE WHEN success = true THEN 1 ELSE 0 END')), 'successfulFetches'],
|
||||
[sequelize.fn('SUM', sequelize.col('records_processed')), 'totalRecordsProcessed'],
|
||||
[sequelize.fn('AVG', sequelize.col('execution_time')), 'avgExecutionTime']
|
||||
],
|
||||
group: ['fetchType']
|
||||
});
|
||||
|
||||
return stats;
|
||||
} catch (error) {
|
||||
console.error('Error getting fetch statistics:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default new MyTischtennisFetchLogService();
|
||||
|
||||
Reference in New Issue
Block a user