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 { json } from '@sveltejs/kit';
|
||||||
import prisma from '$lib/prismaClient';
|
import prisma from '$lib/prismaClient';
|
||||||
import redisClient from '$lib/redisClient';
|
import redisClient from '$lib/redisClient';
|
||||||
|
import logger from '$lib/logger';
|
||||||
|
|
||||||
export async function GET({ params, url }) {
|
export async function GET({ params, url }) {
|
||||||
const channelId = params.id;
|
const channelId = params.id;
|
||||||
|
|
||||||
// @ts-ignore
|
// @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
|
// @ts-ignore
|
||||||
const limit = 10;
|
const page = parseInt(url.searchParams.get('page')) || 1;
|
||||||
|
|
||||||
const offset = (page - 1) * limit;
|
const offset = (page - 1) * limit;
|
||||||
|
|
||||||
// Générer une clé cache Redis unique en fonction du canal et des paramètres de pagination
|
let redisMessages = await redisClient.zRange(`channel:${channelId}:messages`, offset, limit, { REV: true });
|
||||||
const cacheKey = `channel:${channelId}:messages:page:${page}`;
|
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 {
|
return json({limit: limit+1, page, messages});
|
||||||
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({
|
const messages = await prisma.message.findMany({
|
||||||
where: { channelId },
|
where: {
|
||||||
include: {
|
channelId
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
createdAt: true,
|
||||||
|
text: true,
|
||||||
user: {
|
user: {
|
||||||
select: { id: true, username: true },
|
select: {
|
||||||
},
|
id: true,
|
||||||
},
|
username: true,
|
||||||
orderBy: {
|
surname: true,
|
||||||
createdAt: 'asc', // Trie par date croissante
|
name: true,
|
||||||
},
|
profilePicture: true
|
||||||
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 });
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
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 }) {
|
export async function POST({ params, request }) {
|
||||||
|
@ -73,9 +72,24 @@ export async function POST({ params, request }) {
|
||||||
channelId,
|
channelId,
|
||||||
text,
|
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 });
|
return json(newMessage, { status: 201 });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
@ -84,8 +98,10 @@ export async function POST({ params, request }) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function DELETE({ params }) {
|
export async function DELETE({ params, request }) {
|
||||||
const messageId = params.id;
|
const channelId = params.id;
|
||||||
|
|
||||||
|
const { messageId } = await request.json();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Supprimer le message de la base de données
|
// Supprimer le message de la base de données
|
||||||
|
@ -93,7 +109,8 @@ export async function DELETE({ params }) {
|
||||||
where: { id: messageId },
|
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' });
|
return json({ message: 'Message supprimé avec succès' });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
@ -101,45 +118,3 @@ export async function DELETE({ params }) {
|
||||||
return json({ error: 'Erreur lors de la suppression du message' }, { status: 500 });
|
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.
|
// 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.
|
// See https://svelte.dev/docs/kit/adapters for more information about adapters.
|
||||||
adapter: adapter(),
|
adapter: adapter(),
|
||||||
csrf: false,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
extensions: ['.svelte', '.svx']
|
extensions: ['.svelte', '.svx']
|
||||||
|
|
Loading…
Add table
Reference in a new issue