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 { MiddlewareConsumer, Module, NestModule } from "@nestjs/common";
import {
Logger,
MiddlewareConsumer,
Module,
NestModule,
} from "@nestjs/common";
import { ConfigModule, ConfigService } from "@nestjs/config";
import { ScheduleModule } from "@nestjs/schedule";
import { ThrottlerModule } from "@nestjs/throttler";
@@ -70,12 +75,24 @@ import { UsersModule } from "./users/users.module";
isGlobal: true,
imports: [ConfigModule],
inject: [ConfigService],
useFactory: async (config: ConfigService) => ({
store: await redisStore({
url: `redis://${config.get("REDIS_HOST")}:${config.get("REDIS_PORT")}`,
}),
ttl: 600, // 10 minutes
}),
useFactory: async (config: ConfigService) => {
const logger = new Logger("RedisCache");
return {
store: await redisStore({
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
};
},
}),
],
controllers: [AppController, HealthController],

View File

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

View File

@@ -49,13 +49,18 @@ export class CrawlerDetectionMiddleware implements NestMiddleware {
const userAgent = req.get("user-agent") || "unknown";
// Vérifier si l'IP est bannie
const isBanned = await this.cacheManager.get(`banned_ip:${ip}`);
if (isBanned) {
this.logger.warn(`Banned IP attempt: ${ip} -> ${method} ${url}`);
res.status(403).json({
message: "Access denied: Your IP has been temporarily banned.",
});
return;
try {
const isBanned = await this.cacheManager.get(`banned_ip:${ip}`);
if (isBanned) {
this.logger.warn(`Banned IP attempt: ${ip} -> ${method} ${url}`);
res.status(403).json({
message: "Access denied: Your IP has been temporarily banned.",
});
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 () => {
@@ -73,7 +78,11 @@ export class CrawlerDetectionMiddleware implements NestMiddleware {
);
// Bannir l'IP pour 24h via Redis
await this.cacheManager.set(`banned_ip:${ip}`, true, 86400000);
try {
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() {
this.logger.log("Clearing contents cache");
await this.cacheManager.clear();
try {
this.logger.log("Clearing contents cache");
await this.cacheManager.del("contents/all");
} catch (error) {
this.logger.error(`Error clearing contents cache: ${error.message}`);
}
}
async getUploadUrl(userId: string, fileName: string) {

View File

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