notifications

This commit is contained in:
alma 2026-01-11 22:33:08 +01:00
parent a1e4e14b30
commit 2602773980
4 changed files with 61 additions and 20 deletions

View File

@ -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);

View File

@ -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();
}

View File

@ -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<NotificationCount> {
logger.debug('[NOTIFICATION_SERVICE] getNotificationCount called', { userId });
async getNotificationCount(userId: string, forceRefresh: boolean = false): Promise<NotificationCount> {
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

View File

@ -28,7 +28,13 @@ export class RocketChatAdapter implements NotificationAdapter {
private async getUserEmail(): Promise<string | null> {
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),