feat(cache): enhance error handling and logging for cache operations

- Added try-catch blocks to improve resilience in cache operations across services.
- Integrated detailed error logging for better debugging.
- Updated Redis reconnect strategy with exponential backoff and logging.
This commit is contained in:
Mathis HERRIOT
2026-02-09 09:52:40 +01:00
parent 22c753d1e7
commit fe7683f5b1
5 changed files with 59 additions and 21 deletions

View File

@@ -1,5 +1,10 @@
import { CacheModule } from "@nestjs/cache-manager"; import { CacheModule } from "@nestjs/cache-manager";
import { MiddlewareConsumer, Module, NestModule } from "@nestjs/common"; import {
Logger,
MiddlewareConsumer,
Module,
NestModule,
} from "@nestjs/common";
import { ConfigModule, ConfigService } from "@nestjs/config"; import { ConfigModule, ConfigService } from "@nestjs/config";
import { ScheduleModule } from "@nestjs/schedule"; import { ScheduleModule } from "@nestjs/schedule";
import { ThrottlerModule } from "@nestjs/throttler"; import { ThrottlerModule } from "@nestjs/throttler";
@@ -70,12 +75,24 @@ import { UsersModule } from "./users/users.module";
isGlobal: true, isGlobal: true,
imports: [ConfigModule], imports: [ConfigModule],
inject: [ConfigService], inject: [ConfigService],
useFactory: async (config: ConfigService) => ({ useFactory: async (config: ConfigService) => {
const logger = new Logger("RedisCache");
return {
store: await redisStore({ store: await redisStore({
url: `redis://${config.get("REDIS_HOST")}:${config.get("REDIS_PORT")}`, url: `redis://${config.get("REDIS_HOST")}:${config.get("REDIS_PORT")}`,
socket: {
reconnectStrategy: (retries) => {
const delay = Math.min(retries * 50, 2000);
logger.warn(
`Redis connection lost. Retrying in ${delay}ms (attempt ${retries})`,
);
return delay;
},
},
}), }),
ttl: 600, // 10 minutes ttl: 600, // 10 minutes
}), };
},
}), }),
], ],
controllers: [AppController, HealthController], controllers: [AppController, HealthController],

View File

@@ -15,8 +15,12 @@ export class CategoriesService {
) {} ) {}
private async clearCategoriesCache() { private async clearCategoriesCache() {
try {
this.logger.log("Clearing categories cache"); this.logger.log("Clearing categories cache");
await this.cacheManager.del("categories/all"); await this.cacheManager.del("categories/all");
} catch (error) {
this.logger.error(`Error clearing categories cache: ${error.message}`);
}
} }
async findAll() { async findAll() {

View File

@@ -49,6 +49,7 @@ export class CrawlerDetectionMiddleware implements NestMiddleware {
const userAgent = req.get("user-agent") || "unknown"; const userAgent = req.get("user-agent") || "unknown";
// Vérifier si l'IP est bannie // Vérifier si l'IP est bannie
try {
const isBanned = await this.cacheManager.get(`banned_ip:${ip}`); const isBanned = await this.cacheManager.get(`banned_ip:${ip}`);
if (isBanned) { if (isBanned) {
this.logger.warn(`Banned IP attempt: ${ip} -> ${method} ${url}`); this.logger.warn(`Banned IP attempt: ${ip} -> ${method} ${url}`);
@@ -57,6 +58,10 @@ export class CrawlerDetectionMiddleware implements NestMiddleware {
}); });
return; return;
} }
} catch (error) {
this.logger.error(`Error checking ban status for IP ${ip}: ${error.message}`);
// On continue même en cas d'erreur Redis pour ne pas bloquer les utilisateurs légitimes
}
res.on("finish", async () => { res.on("finish", async () => {
if (res.statusCode === 404) { if (res.statusCode === 404) {
@@ -73,7 +78,11 @@ export class CrawlerDetectionMiddleware implements NestMiddleware {
); );
// Bannir l'IP pour 24h via Redis // Bannir l'IP pour 24h via Redis
try {
await this.cacheManager.set(`banned_ip:${ip}`, true, 86400000); await this.cacheManager.set(`banned_ip:${ip}`, true, 86400000);
} catch (error) {
this.logger.error(`Error banning IP ${ip}: ${error.message}`);
}
} }
} }
}); });

View File

@@ -34,8 +34,12 @@ export class ContentsService {
) {} ) {}
private async clearContentsCache() { private async clearContentsCache() {
try {
this.logger.log("Clearing contents cache"); this.logger.log("Clearing contents cache");
await this.cacheManager.clear(); await this.cacheManager.del("contents/all");
} catch (error) {
this.logger.error(`Error clearing contents cache: ${error.message}`);
}
} }
async getUploadUrl(userId: string, fileName: string) { async getUploadUrl(userId: string, fileName: string) {

View File

@@ -33,9 +33,13 @@ export class UsersService {
) {} ) {}
private async clearUserCache(username?: string) { private async clearUserCache(username?: string) {
try {
if (username) { if (username) {
await this.cacheManager.del(`users/profile/${username}`); await this.cacheManager.del(`users/profile/${username}`);
} }
} catch (error) {
this.logger.error(`Error clearing user cache: ${error.message}`);
}
} }
async create(data: { async create(data: {