feat(clickTtTournamentRegistrationService): enhance error handling and diagnostics for tournament registration

- Added detailed diagnostics to capture page content and URLs during registration failures, improving error reporting.
- Implemented a function to build a debug HTML path for saving page content, aiding in troubleshooting.
- Updated error handling to include relevant diagnostic information in error messages, enhancing clarity for users.
This commit is contained in:
Torsten Schulz (local)
2026-03-11 21:16:23 +01:00
parent 8776c01e47
commit dba290c1d4
2 changed files with 59 additions and 5 deletions

View File

@@ -1,4 +1,6 @@
import { chromium } from 'playwright';
import { mkdir, writeFile } from 'fs/promises';
import path from 'path';
import Club from '../models/Club.js';
import ClickTtAccount from '../models/ClickTtAccount.js';
import OfficialTournament from '../models/OfficialTournament.js';
@@ -58,6 +60,15 @@ function parseDmyRange(value) {
};
}
function buildDebugHtmlPath() {
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
return path.join(process.cwd(), 'tmp', `clicktt-tournament-debug-${timestamp}.html`);
}
function sanitizePageText(text) {
return String(text || '').replace(/\s+/g, ' ').trim().slice(0, 500);
}
class ClickTtTournamentRegistrationService {
async autoRegisterPendingParticipants({ userToken, userId, clubId, tournamentId }) {
await checkAccess(userToken, clubId);
@@ -134,6 +145,7 @@ class ClickTtTournamentRegistrationService {
let context = null;
let page = null;
const trace = [];
let resultsPageUrl = null;
try {
browser = await chromium.launch({
@@ -154,7 +166,7 @@ class ClickTtTournamentRegistrationService {
await clickTtPlayerRegistrationService._selectClubContext(page, associationMemberNumber, trace);
await this._openTournamentSearch(page, trace);
await this._filterTournamentSearch(page, tournament, trace);
const resultsPageUrl = page.url();
resultsPageUrl = page.url();
const processedCompetitions = [];
for (const group of competitionGroups) {
@@ -197,9 +209,49 @@ class ClickTtTournamentRegistrationService {
competitions: processedCompetitions
};
} catch (error) {
throw error instanceof HttpError
? error
: new HttpError(`Click-TT-Turnieranmeldung fehlgeschlagen: ${error.message || error}`, 500);
const diagnostics = {
url: null,
text: null,
htmlPath: null,
resultsPageUrl
};
try {
const html = await page?.content?.();
const htmlPath = html ? buildDebugHtmlPath() : null;
if (html && htmlPath) {
await mkdir(path.dirname(htmlPath), { recursive: true });
await writeFile(htmlPath, html, 'utf8');
diagnostics.htmlPath = htmlPath;
}
} catch (_err) {
// keep partial diagnostics
}
try {
diagnostics.url = page?.url?.() || null;
} catch (_err) {
// ignore
}
try {
diagnostics.text = sanitizePageText(await page?.locator?.('body')?.innerText?.());
} catch (_err) {
// ignore
}
const baseMessage = error instanceof HttpError
? error.message
: `Click-TT-Turnieranmeldung fehlgeschlagen: ${error.message || error}`;
const wrappedError = new HttpError(
`${baseMessage}${diagnostics.url ? ` (Seite: ${diagnostics.url})` : ''}${diagnostics.htmlPath ? ` (HTML: ${diagnostics.htmlPath})` : ''}${diagnostics.text ? ` - ${diagnostics.text}` : ''}`,
error.statusCode || error.status || 500
);
wrappedError.htmlPath = diagnostics.htmlPath || null;
wrappedError.details = {
resultsPageUrl: diagnostics.resultsPageUrl || null
};
throw wrappedError;
} finally {
if (context) {
try { await context.close(); } catch (_err) {}