diff --git a/app/api/notifications/count/route.ts b/app/api/notifications/count/route.ts index 1421dd2..72b750e 100644 --- a/app/api/notifications/count/route.ts +++ b/app/api/notifications/count/route.ts @@ -2,6 +2,7 @@ import { NextResponse } from 'next/server'; import { getServerSession } from 'next-auth'; import { authOptions } from "@/app/api/auth/options"; import { NotificationService } from '@/lib/services/notifications/notification-service'; +import { logger } from '@/lib/logger'; // GET /api/notifications/count export async function GET(request: Request) { @@ -24,9 +25,11 @@ export async function GET(request: Request) { // If force refresh, invalidate cache first if (forceRefresh) { await notificationService.invalidateCache(userId); + logger.debug('[NOTIFICATIONS_COUNT_API] Cache invalidated for force refresh', { userId }); } - const counts = await notificationService.getNotificationCount(userId); + // Pass forceRefresh flag to bypass cache + const counts = await notificationService.getNotificationCount(userId, forceRefresh); // Add Cache-Control header - rely on server-side cache, minimal client cache const response = NextResponse.json(counts); diff --git a/components/parole.tsx b/components/parole.tsx index 305f514..6aba04a 100644 --- a/components/parole.tsx +++ b/components/parole.tsx @@ -82,10 +82,12 @@ export function Parole() { }); // Si nouveau message non lu détecté, déclencher notification - if (currentUnreadCount > lastUnreadCountRef.current) { - console.log('[Parole] ⚡ Nouveau message non lu détecté, déclenchement notification', { + // On déclenche aussi si le count a changé (augmenté ou diminué) pour forcer le refresh + if (currentUnreadCount !== lastUnreadCountRef.current) { + console.log('[Parole] ⚡ Unread count changed, triggering notification refresh', { previous: lastUnreadCountRef.current, - current: currentUnreadCount + current: currentUnreadCount, + isIncrease: currentUnreadCount > lastUnreadCountRef.current }); triggerNotificationRefresh(); } diff --git a/lib/services/notifications/notification-service.ts b/lib/services/notifications/notification-service.ts index 564ae90..e09fbd3 100644 --- a/lib/services/notifications/notification-service.ts +++ b/lib/services/notifications/notification-service.ts @@ -182,25 +182,31 @@ export class NotificationService { /** * Get notification counts for a user + * @param forceRefresh If true, bypass cache and fetch fresh data */ - async getNotificationCount(userId: string): Promise { - logger.debug('[NOTIFICATION_SERVICE] getNotificationCount called', { userId }); + async getNotificationCount(userId: string, forceRefresh: boolean = false): Promise { + logger.debug('[NOTIFICATION_SERVICE] getNotificationCount called', { userId, forceRefresh }); const redis = getRedisClient(); const cacheKey = NotificationService.NOTIFICATION_COUNT_CACHE_KEY(userId); - // Try to get from cache first - try { - const cachedData = await redis.get(cacheKey); - if (cachedData) { - logger.debug('[NOTIFICATION_SERVICE] Using cached notification counts', { userId }); - - // Background refresh is now handled by unified refresh system - // Cache TTL is aligned with refresh interval (30s) - - return JSON.parse(cachedData); + // If force refresh, skip cache + if (!forceRefresh) { + // Try to get from cache first + try { + const cachedData = await redis.get(cacheKey); + if (cachedData) { + logger.debug('[NOTIFICATION_SERVICE] Using cached notification counts', { userId }); + + // Background refresh is now handled by unified refresh system + // Cache TTL is aligned with refresh interval (30s) + + return JSON.parse(cachedData); + } + } catch (error) { + console.error('[NOTIFICATION_SERVICE] Error retrieving notification counts from cache:', error); } - } catch (error) { - console.error('[NOTIFICATION_SERVICE] Error retrieving notification counts from cache:', error); + } else { + logger.debug('[NOTIFICATION_SERVICE] Force refresh requested, bypassing cache', { userId }); } // No cached data, fetch counts from all adapters diff --git a/lib/services/notifications/rocketchat-adapter.ts b/lib/services/notifications/rocketchat-adapter.ts index 63d03da..c68d230 100644 --- a/lib/services/notifications/rocketchat-adapter.ts +++ b/lib/services/notifications/rocketchat-adapter.ts @@ -28,7 +28,13 @@ export class RocketChatAdapter implements NotificationAdapter { private async getUserEmail(): Promise { try { const session = await getServerSession(authOptions); - return session?.user?.email || null; + const email = session?.user?.email || null; + logger.debug('[ROCKETCHAT_ADAPTER] getUserEmail', { + hasSession: !!session, + hasEmail: !!email, + emailHash: email ? Buffer.from(email.toLowerCase()).toString('base64').slice(0, 12) : null, + }); + return email; } catch (error) { logger.error('[ROCKETCHAT_ADAPTER] Error getting user email', { error: error instanceof Error ? error.message : String(error), @@ -65,11 +71,35 @@ export class RocketChatAdapter implements NotificationAdapter { const usersData = await usersResponse.json(); if (!usersData.success || !Array.isArray(usersData.users)) { + logger.error('[ROCKETCHAT_ADAPTER] Invalid users list response', { + success: usersData.success, + hasUsers: Array.isArray(usersData.users), + }); return null; } + logger.debug('[ROCKETCHAT_ADAPTER] Searching for user', { + username, + totalUsers: usersData.users.length, + }); + const currentUser = usersData.users.find((u: any) => u.username === username); - return currentUser?._id || null; + + if (!currentUser) { + logger.warn('[ROCKETCHAT_ADAPTER] User not found in RocketChat', { + username, + searchedIn: usersData.users.length, + availableUsernames: usersData.users.slice(0, 5).map((u: any) => u.username), + }); + return null; + } + + logger.debug('[ROCKETCHAT_ADAPTER] Found user', { + username, + userId: currentUser._id, + }); + + return currentUser._id; } catch (error) { logger.error('[ROCKETCHAT_ADAPTER] Error getting RocketChat user ID', { error: error instanceof Error ? error.message : String(error),