Merge pull request #8 from NabilOuldHamou/features/message_route
fix: fixed message api and paging in cache
This commit is contained in:
commit
0c92acc24b
2 changed files with 70 additions and 96 deletions
|
@ -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,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,7 +109,8 @@ 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) {
|
||||
|
@ -101,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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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']
|
||||
|
|
Loading…
Add table
Reference in a new issue