fix: little bugs and refacto debug service

This commit is contained in:
Julien Froidefond
2025-03-06 21:41:24 +01:00
parent 0ca63a1fbd
commit 907e09682b
7 changed files with 84 additions and 67 deletions

View File

@@ -48,6 +48,8 @@ services:
limits: limits:
cpus: "0.5" cpus: "0.5"
memory: 512M memory: 512M
ports:
- "27017:27017"
command: ["mongod", "--auth", "--bind_ip_all"] command: ["mongod", "--auth", "--bind_ip_all"]
networks: networks:

View File

@@ -13,7 +13,7 @@ export const metadata: Metadata = {
description: "Connectez-vous à votre compte StripStream", description: "Connectez-vous à votre compte StripStream",
}; };
function LoginPage({ searchParams }: PageProps) { async function LoginPage({ searchParams }: PageProps) {
return <LoginContent searchParams={searchParams} />; return <LoginContent searchParams={await searchParams} />;
} }
export default withPageTiming("LoginPage", LoginPage); export default withPageTiming("LoginPage", LoginPage);

View File

@@ -301,7 +301,9 @@
"SERIES_NO_BOOKS_FOUND": "No books found in the series", "SERIES_NO_BOOKS_FOUND": "No books found in the series",
"BOOK_PAGES_FETCH_ERROR": "Error fetching book pages", "BOOK_PAGES_FETCH_ERROR": "Error fetching book pages",
"GENERIC_ERROR": "An error occurred" "GENERIC_ERROR": "An error occurred",
"MONGODB_CONNECTION_FAILED": "MongoDB connection failed"
}, },
"reader": { "reader": {
"controls": { "controls": {

View File

@@ -299,7 +299,8 @@
"SERIES_NO_BOOKS_FOUND": "Aucun livre trouvé dans la série", "SERIES_NO_BOOKS_FOUND": "Aucun livre trouvé dans la série",
"BOOK_PAGES_FETCH_ERROR": "Erreur lors de la récupération des pages du livre", "BOOK_PAGES_FETCH_ERROR": "Erreur lors de la récupération des pages du livre",
"GENERIC_ERROR": "Une erreur est survenue" "GENERIC_ERROR": "Une erreur est survenue",
"MONGODB_CONNECTION_FAILED": "Erreur lors de la connexion à MongoDB"
}, },
"reader": { "reader": {
"controls": { "controls": {

View File

@@ -41,6 +41,7 @@ async function connectDB(): Promise<typeof mongoose> {
try { try {
cached.conn = await cached.promise; cached.conn = await cached.promise;
} catch (e) { } catch (e) {
console.error("Error connecting to MongoDB:", e);
cached.promise = null; cached.promise = null;
throw new AppError(ERROR_CODES.MONGODB.CONNECTION_FAILED, {}, e); throw new AppError(ERROR_CODES.MONGODB.CONNECTION_FAILED, {}, e);
} }

View File

@@ -46,36 +46,70 @@ export class DebugService {
} }
} }
private static async isDebugEnabled(): Promise<boolean> {
const user = await AuthServerService.getCurrentUser();
if (!user) {
return false;
}
const preferences = await PreferencesService.getPreferences();
return preferences.debug === true;
}
private static async readLogs(filePath: string): Promise<RequestTiming[]> {
try {
const content = await fs.readFile(filePath, "utf-8");
return JSON.parse(content);
} catch {
return [];
}
}
private static async writeLogs(filePath: string, logs: RequestTiming[]): Promise<void> {
const trimmedLogs = logs.slice(-99);
await fs.writeFile(filePath, JSON.stringify(trimmedLogs, null, 2));
}
private static createTiming(
url: string,
startTime: number,
endTime: number,
fromCache: boolean,
additionalData?: Partial<RequestTiming>
): RequestTiming {
return {
url,
startTime,
endTime,
duration: endTime - startTime,
timestamp: new Date().toISOString(),
fromCache,
...additionalData,
};
}
static async logRequest(timing: Omit<RequestTiming, "duration" | "timestamp">) { static async logRequest(timing: Omit<RequestTiming, "duration" | "timestamp">) {
try { try {
if (!(await this.isDebugEnabled())) return;
const userId = await this.getCurrentUserId(); const userId = await this.getCurrentUserId();
const preferences = await PreferencesService.getPreferences();
if (!preferences.debug) {
return;
}
await this.ensureDebugDir(); await this.ensureDebugDir();
const filePath = this.getLogFilePath(userId); const filePath = this.getLogFilePath(userId);
let logs: RequestTiming[] = []; const logs = await this.readLogs(filePath);
try { const newTiming = this.createTiming(
const content = await fs.readFile(filePath, "utf-8"); timing.url,
logs = JSON.parse(content); timing.startTime,
} catch { timing.endTime,
// Le fichier n'existe pas encore ou est vide timing.fromCache,
} {
cacheType: timing.cacheType,
mongoAccess: timing.mongoAccess,
pageRender: timing.pageRender,
}
);
const newTiming: RequestTiming = { await this.writeLogs(filePath, [...logs, newTiming]);
...timing,
duration: timing.endTime - timing.startTime,
timestamp: new Date().toISOString(),
};
// Garde les 100 dernières requêtes
logs = [...logs.slice(-99), newTiming];
await fs.writeFile(filePath, JSON.stringify(logs, null, 2));
} catch (error) { } catch (error) {
// On ignore les erreurs de logging mais on les trace quand même
console.error("Erreur lors de l'enregistrement du log:", error); console.error("Erreur lors de l'enregistrement du log:", error);
} }
} }
@@ -84,12 +118,9 @@ export class DebugService {
try { try {
const userId = await this.getCurrentUserId(); const userId = await this.getCurrentUserId();
const filePath = this.getLogFilePath(userId); const filePath = this.getLogFilePath(userId);
const content = await fs.readFile(filePath, "utf-8"); return await this.readLogs(filePath);
return JSON.parse(content);
} catch (error) { } catch (error) {
if (error instanceof AppError) { if (error instanceof AppError) throw error;
throw error;
}
return []; return [];
} }
} }
@@ -98,53 +129,28 @@ export class DebugService {
try { try {
const userId = await this.getCurrentUserId(); const userId = await this.getCurrentUserId();
const filePath = this.getLogFilePath(userId); const filePath = this.getLogFilePath(userId);
await fs.writeFile(filePath, "[]"); await this.writeLogs(filePath, []);
} catch (error) { } catch (error) {
if (error instanceof AppError) { if (error instanceof AppError) throw error;
throw error;
}
// On ignore les autres erreurs si le fichier n'existe pas
} }
} }
static async logPageRender(page: string, duration: number) { static async logPageRender(page: string, duration: number) {
try { try {
if (!(await this.isDebugEnabled())) return;
const userId = await this.getCurrentUserId(); const userId = await this.getCurrentUserId();
const preferences = await PreferencesService.getPreferences();
if (!preferences.debug) {
return;
}
await this.ensureDebugDir(); await this.ensureDebugDir();
const filePath = this.getLogFilePath(userId); const filePath = this.getLogFilePath(userId);
let logs: RequestTiming[] = []; const logs = await this.readLogs(filePath);
try {
const content = await fs.readFile(filePath, "utf-8");
logs = JSON.parse(content);
} catch {
// Le fichier n'existe pas encore ou est vide
}
const now = performance.now(); const now = performance.now();
const newTiming: RequestTiming = { const newTiming = this.createTiming(`Page Render: ${page}`, now - duration, now, false, {
url: `Page Render: ${page}`, pageRender: { page, duration },
startTime: now - duration, });
endTime: now,
duration,
timestamp: new Date().toISOString(),
fromCache: false,
pageRender: {
page,
duration,
},
};
// Garde les 100 dernières requêtes await this.writeLogs(filePath, [...logs, newTiming]);
logs = [...logs.slice(-99), newTiming];
await fs.writeFile(filePath, JSON.stringify(logs, null, 2));
} catch (error) { } catch (error) {
// On ignore les erreurs de logging mais on les trace quand même
console.error("Erreur lors de l'enregistrement du log de rendu:", error); console.error("Erreur lors de l'enregistrement du log de rendu:", error);
} }
} }
@@ -152,10 +158,10 @@ export class DebugService {
static async measureMongoOperation<T>(operation: string, func: () => Promise<T>): Promise<T> { static async measureMongoOperation<T>(operation: string, func: () => Promise<T>): Promise<T> {
const startTime = performance.now(); const startTime = performance.now();
try { try {
const preferences = await PreferencesService.getPreferences(); if (!(await this.isDebugEnabled())) {
if (!preferences.debug) {
return func(); return func();
} }
const result = await func(); const result = await func();
const endTime = performance.now(); const endTime = performance.now();

View File

@@ -45,6 +45,11 @@ class ServerCacheService {
private async initializeCacheMode(): Promise<void> { private async initializeCacheMode(): Promise<void> {
try { try {
const user = await AuthServerService.getCurrentUser();
if (!user) {
this.setCacheMode("memory");
return;
}
const preferences = await PreferencesService.getPreferences(); const preferences = await PreferencesService.getPreferences();
this.setCacheMode(preferences.cacheMode); this.setCacheMode(preferences.cacheMode);
} catch (error) { } catch (error) {