fix: fixed message api and paging in cache

This commit is contained in:
Nabil Ould Hamou 2024-12-04 14:02:25 +01:00
parent bc51e7620c
commit 8767ec7970
2 changed files with 70 additions and 97 deletions

View file

@ -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(<string>m))
);
return json({limit: limit+1, page, messages: mgetMessages});
}
export async function POST({ params, request }) {
@ -73,10 +72,24 @@ export async function POST({ params, request }) {
channelId,
text,
},
include: { user: { select: { id: true, username: true } } },
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 dun 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) {
@ -85,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
@ -94,7 +109,8 @@ export async function DELETE({ params }) {
where: { id: messageId },
});
updateCaches(); // Mettre à jour les caches après la suppression dun message
await redisClient.del(`message:${messageId}`);
await redisClient.zRem(`channel:${channelId}:messages`, `message:${messageId}`);
return json({ message: 'Message supprimé avec succès' });
} catch (err) {
@ -102,45 +118,3 @@ export async function DELETE({ params }) {
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;
}
}

View file

@ -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']