diff --git a/src/routes/api/channels/[id]/messages/+server.ts b/src/routes/api/channels/[id]/messages/+server.ts index d00c8a6..2638a3d 100644 --- a/src/routes/api/channels/[id]/messages/+server.ts +++ b/src/routes/api/channels/[id]/messages/+server.ts @@ -1,64 +1,63 @@ import { json } from '@sveltejs/kit'; import prisma from '$lib/prismaClient'; import redisClient from '$lib/redisClient'; +import logger from '$lib/logger'; export async function GET({ params, url }) { const channelId = params.id; // @ts-ignore - const page = url.searchParams.get('page') != null ? parseInt(url.searchParams.get('page')) : 1; + const limit = parseInt(url.searchParams.get('limit'))-1 || 19; // Limit -1 sinon ça retourne un message de trop // @ts-ignore - const limit = 10; + const page = parseInt(url.searchParams.get('page')) || 1; + const offset = (page - 1) * limit; - // Générer une clé cache Redis unique en fonction du canal et des paramètres de pagination - const cacheKey = `channel:${channelId}:messages:page:${page}`; + let redisMessages = await redisClient.zRange(`channel:${channelId}:messages`, offset, limit, { REV: true }); + if (redisMessages != null) { + logger.debug(`Cache entry found, fetching messages for channel (${channelId}) from cache`); + const messages = redisMessages.length != 0 ? await redisClient.mGet(redisMessages).then( + (messages) => messages.map((m) => JSON.parse(m)) + ) : []; - try { - const cachedMessages = await redisClient.get(cacheKey); - if (cachedMessages) { - console.log('✅ Cache hit'); - return json(JSON.parse(cachedMessages)); // Si les données sont en cache, les retourner - } - - const messages = await prisma.message.findMany({ - where: { channelId }, - include: { - user: { - select: { id: true, username: true }, - }, - }, - orderBy: { - createdAt: 'asc', // Trie par date croissante - }, - skip: offset, - take: limit, - }); - - - const totalMessages = await prisma.message.count({ - where: { channelId }, - }); - - const response = { - messages, - pagination: { - page, - limit, - totalMessages, - totalPages: Math.ceil(totalMessages / limit), - }, - }; - - - await redisClient.set(cacheKey, JSON.stringify(response), { EX: 600 }); - - console.log('❌ Cache miss - Mise en cache des résultats'); - return json(response); - } catch (err) { - console.error(err); - return json({ error: 'Erreur lors de la récupération des messages' }, { status: 500 }); + return json({limit: limit+1, page, messages}); } + + const messages = await prisma.message.findMany({ + where: { + channelId + }, + select: { + id: true, + createdAt: true, + text: true, + user: { + select: { + id: true, + username: true, + surname: true, + name: true, + profilePicture: true + } + } + }, + orderBy: [ + { createdAt: 'desc' } + ], + }); + + for (const m of messages) { + await redisClient.set(`message:${m.id}`, JSON.stringify(m)); + // @ts-ignore + await redisClient.zAdd(`channel:${channelId}:messages`, {score: Date.parse(m.createdAt), value: `message:${m.id}`}); + } + + redisMessages = await redisClient.zRange(`channel:${channelId}:messages`, offset, limit, { REV: true }); + const mgetMessages =await redisClient.mGet(redisMessages).then( + (messages) => messages.map((m) => JSON.parse(m)) + ); + + return json({limit: limit+1, page, messages: mgetMessages}); } export async function POST({ params, request }) { @@ -73,9 +72,24 @@ export async function POST({ params, request }) { channelId, text, }, + select: { + id: true, + createdAt: true, + text: true, + user: { + select: { + id: true, + username: true, + surname: true, + name: true, + profilePicture: true + } + } + }, }); - updateCaches(); // Mettre à jour les caches après la création d’un nouveau message + await redisClient.set(`message:${newMessage.id}`, JSON.stringify(newMessage)); + await redisClient.zAdd(`channel:${channelId}:messages`, {score: Date.parse(newMessage.createdAt), value: `message:${newMessage.id}`}); return json(newMessage, { status: 201 }); } catch (err) { @@ -84,8 +98,10 @@ export async function POST({ params, request }) { } } -export async function DELETE({ params }) { - const messageId = params.id; +export async function DELETE({ params, request }) { + const channelId = params.id; + + const { messageId } = await request.json(); try { // Supprimer le message de la base de données @@ -93,53 +109,12 @@ export async function DELETE({ params }) { where: { id: messageId }, }); - updateCaches(); // Mettre à jour les caches après la suppression d’un message + await redisClient.del(`message:${messageId}`); + await redisClient.zRem(`channel:${channelId}:messages`, `message:${messageId}`); return json({ message: 'Message supprimé avec succès' }); } catch (err) { console.error(err); return json({ error: 'Erreur lors de la suppression du message' }, { status: 500 }); } -} - -// Fonction pour mettre à jour tous les caches des messages -async function updateCaches(channelId: string) { - let page : number = 1; - let limit : number = 10; - let offset : number = (page - 1) * limit; - while (true) { - const cacheKey = `channel:${channelId}:messages:page:${page}`; - const cachedMessages = await redisClient.get(cacheKey); - if (!cachedMessages) { - break; - } - const totalMessages = await prisma.message.count({ - where: { channelId }, - }); - const messages = await prisma.message.findMany({ - where: { channelId }, - include: { - user: { - select: { id: true, pseudo: true }, - }, - }, - orderBy: { - createdAt: 'asc', - }, - skip: offset, - take: limit, - }); - const response = { - messages, - pagination: { - page, - limit, - totalMessages, - totalPages: Math.ceil(totalMessages / limit), - }, - }; - await redisClient.set(cacheKey, JSON.stringify(response), 'EX', 60 * 5); - page++; - offset = (page - 1) * limit; - } -} +} \ No newline at end of file diff --git a/svelte.config.js b/svelte.config.js index 3494d6c..b3bcd61 100644 --- a/svelte.config.js +++ b/svelte.config.js @@ -17,7 +17,6 @@ const config = { // If your environment is not supported, or you settled on a specific environment, switch out the adapter. // See https://svelte.dev/docs/kit/adapters for more information about adapters. adapter: adapter(), - csrf: false, }, extensions: ['.svelte', '.svx']