Ajouts des models et de l'api avec gestion du cache

This commit is contained in:
Bilal Dieumegard 2024-11-27 18:09:42 +01:00
parent 267dcdf5ea
commit 431c77f970
8 changed files with 472 additions and 0 deletions

View file

@ -36,6 +36,9 @@
"vite": "^5.0.3"
},
"dependencies": {
"@prisma/client": "^5.22.0",
"prisma": "^5.22.0",
"redis": "^4.7.0",
"svelte-radix": "^2.0.1"
}
}

4
src/lib/prismaClient.ts Normal file
View file

@ -0,0 +1,4 @@
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
export default prisma;

11
src/lib/redisClient.ts Normal file
View file

@ -0,0 +1,11 @@
import redis from 'redis';
const client = redis.createClient({
url: process.env.REDIS_URL || 'redis://localhost:6379',
});
client.on('error', (err) => console.error('Redis Error:', err));
await client.connect();
export default client;

View file

@ -0,0 +1,123 @@
import { json } from '@sveltejs/kit';
import prisma from '$lib/prismaClient';
import redisClient from '$lib/redisClient'; // Assurez-vous d'importer le client Redis
// Récupérer les informations du canal et le dernier message (avec cache Redis)
export async function GET({ params }) {
const canalId = parseInt(params.id);
// Clé cache pour les informations du canal et le dernier message
const canalCacheKey = `canal:${canalId}:info`;
try {
// Vérifier si les informations du canal et le dernier message sont dans le cache Redis
const cachedCanalData = await redisClient.get(canalCacheKey);
if (cachedCanalData) {
console.log('✅ Cache hit pour les informations du canal et le dernier message');
return json(JSON.parse(cachedCanalData));
}
console.log('❌ Cache miss');
// Si non, récupérer les informations du canal et le dernier message depuis Prisma
const canal = await prisma.canal.findUnique({
where: { id: canalId },
include: {
users: true, // Inclut les utilisateurs associés au canal
},
});
if (!canal) {
return json({ error: 'Canal non trouvé' }, { status: 404 });
}
// Récupérer le dernier message
const lastMessage = await prisma.message.findFirst({
where: { canalId },
include: {
user: { select: { id: true, pseudo: true } },
},
orderBy: { createdAt: 'desc' }, // Trie par date décroissante, donc le dernier message est récupéré en premier
});
// Créer un objet combiné pour le canal et le dernier message
const canalData = {
canal,
lastMessage, // Inclure uniquement le dernier message
};
// Mettre en cache les informations du canal et le dernier message pendant 5 minutes
await redisClient.set(canalCacheKey, JSON.stringify(canalData), 'EX', 300); // Cache pendant 5 minutes
console.log('❌ Cache miss - Mise en cache des résultats');
return json(canalData);
} catch (err) {
console.error(err);
return json({ error: 'Erreur lors de la récupération du canal ou du dernier message' }, { status: 500 });
}
}
// Supprimer un canal et invalider le cache associé
export async function DELETE({ params }) {
const canalId = parseInt(params.id);
try {
// Supprimer le canal de la base de données
await prisma.canal.delete({
where: { id: canalId },
});
// Invalider le cache
await redisClient.del(`canal:${canalId}:info`);
return json({ message: 'Canal supprimé avec succès' });
} catch (err) {
console.error(err);
return json({ error: 'Erreur lors de la suppression du canal' }, { status: 500 });
}
}
// Modifier un canal
export async function PUT({ params, request }) {
const canalId = parseInt(params.id);
const { nom, domaine } = await request.json(); // On suppose que ce sont les champs à mettre à jour
// Clé cache pour les informations du canal et le dernier message
const canalCacheKey = `canal:${canalId}:info`;
try {
// Mettre à jour les informations du canal dans la base de données
const updatedCanal = await prisma.canal.update({
where: { id: canalId },
data: {
nom, // Nom du canal
domaine, // Domaine du canal
},
include: {
users: true, // Inclut les utilisateurs associés au canal
},
});
// Récupérer le dernier message associé au canal après mise à jour
const lastMessage = await prisma.message.findFirst({
where: { canalId },
include: {
user: { select: { id: true, pseudo: true } },
},
orderBy: { createdAt: 'desc' },
});
// Créer un objet combiné pour les nouvelles informations du canal et le dernier message
const canalData = {
canal: updatedCanal,
lastMessage, // Inclure uniquement le dernier message
};
// Mettre en cache les nouvelles informations pendant 5 minutes
await redisClient.set(canalCacheKey, JSON.stringify(canalData), 'EX', 60 * 5); // Cache pendant 5 minutes
return json(canalData);
} catch (err) {
console.error(err);
return json({ error: 'Erreur lors de la mise à jour du canal' }, { status: 500 });
}
}

View file

@ -0,0 +1,149 @@
import { json } from '@sveltejs/kit';
import prisma from '$lib/prismaClient';
import redisClient from '$lib/redisClient'; // Assure-toi d'importer ton client Redis
export async function GET({ params, url }) {
const canalId = parseInt(params.id);
// Gestion de la pagination avec des paramètres optionnels `page` et `limit`
const page = parseInt(url.searchParams.get('page')) || 1;
const limit = parseInt(url.searchParams.get('limit')) || 10;
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 = `canal:${canalId}:messages:page:${page}:limit:${limit}`;
try {
// 1. Vérifier si les messages sont déjà dans le cache Redis
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
}
// 2. Si les messages ne sont pas en cache, récupérer depuis la base de données
const messages = await prisma.message.findMany({
where: { canalId },
include: {
user: {
select: { id: true, pseudo: true }, // Inclut uniquement lID et le pseudo de lutilisateur
},
},
orderBy: {
createdAt: 'asc', // Trie par date croissante
},
skip: offset,
take: limit,
});
// 3. Compter le nombre total de messages pour la pagination
const totalMessages = await prisma.message.count({
where: { canalId },
});
const response = {
messages,
pagination: {
page,
limit,
totalMessages,
totalPages: Math.ceil(totalMessages / limit),
},
};
// 4. Mettre en cache les messages avec une expiration (par exemple 5 minutes)
await redisClient.set(cacheKey, JSON.stringify(response), 'EX', 60 * 5); // Cache pendant 5 minutes
console.log('❌ Cache miss - Mise en cache des résultats');
return json(response); // Retourner les données récupérées
} catch (err) {
console.error(err);
return json({ error: 'Erreur lors de la récupération des messages' }, { status: 500 });
}
}
export async function POST({ params, request }) {
const canalId = parseInt(params.id);
const { userId, text } = await request.json();
try {
// Créer un nouveau message dans la base de données
const newMessage = await prisma.message.create({
data: {
userId,
canalId,
text,
},
include: { user: { select: { id: true, pseudo: true } } },
});
updateCaches(); // Mettre à jour les caches après la création dun nouveau message
return json(newMessage, { status: 201 });
} catch (err) {
console.error(err);
return json({ error: 'Erreur lors de la création du message' }, { status: 500 });
}
}
export async function DELETE({ params }) {
const messageId = parseInt(params.id);
try {
// Supprimer le message de la base de données
await prisma.message.delete({
where: { id: messageId },
});
updateCaches(); // Mettre à jour les caches après la suppression dun message
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
function updateCaches(canalId) {
// Mettre à jour tous les caches
// Mettre à jour toutes les pages dans le cache
let page : number = 1;
let limit : number = 10;
let offset : number = (page - 1) * limit;
while (true) {
const cacheKey = `canal:${canalId}:messages:page:${page}:limit:${limit}`;
const cachedMessages = await redisClient.get(cacheKey);
if (!cachedMessages) {
break;
}
const totalMessages = await prisma.message.count({
where: { canalId },
});
const messages = await prisma.message.findMany({
where: { canalId },
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

@ -0,0 +1,47 @@
import { json } from '@sveltejs/kit';
import prisma from '$lib/prismaClient';
import redisClient from '$lib/redisClient';
// GET: Liste tous les canaux
export async function GET() {
try {
const cachedCanaux = await redisClient.get('canaux');
if (cachedCanaux) {
console.log('✅ Cache hit');
return json(JSON.parse(cachedCanaux));
}
console.log('❌ Cache miss');
const canaux = await prisma.canal.findMany({
include: { users: true, messages: true }, // Inclut les relations
});
await redisClient.set('canaux', JSON.stringify(canaux), { EX: 600 }); // Met en cache
return json(canaux);
} catch (err) {
console.error(err);
return json({ error: 'Erreur serveur' }, { status: 500 });
}
}
export async function POST({ request }) {
const { nom, domaine, userIds } = await request.json();
try {
const canal = await prisma.canal.create({
data: {
nom,
domaine,
users: {
connect: userIds.map((id) => ({ id })), // Associe des utilisateurs au canal
},
},
});
return json(canal, { status: 201 });
} catch (err) {
console.error(err);
return json({ error: 'Erreur lors de la création du canal' }, { status: 500 });
}
}

View file

@ -0,0 +1,108 @@
import { json } from '@sveltejs/kit';
import redisClient from '$lib/redisClient';
import prisma from '$lib/prismaClient';
export async function GET({ params }) {
const userId = params.id;
try {
// Vérifier si l'utilisateur est dans le cache Redis
const cachedUser = await redisClient.get(`user:${userId}`);
if (cachedUser) {
console.log('✅ Cache hit');
return json(JSON.parse(cachedUser));
}
console.log('❌ Cache miss');
// Si non, récupérer depuis MongoDB via Prisma
const user = await prisma.user.findUnique({
where: { id: parseInt(userId) },
});
if (!user) {
return json({ error: 'Utilisateur non trouvé' }, { status: 404 });
}
// Mettre l'utilisateur en cache
await redisClient.set(`user:${userId}`, JSON.stringify(user), { EX: 3600 });
return json(user);
} catch (err) {
console.error(err);
return json({ error: 'Erreur serveur' }, { status: 500 });
}
}
export async function POST({ request }) {
const { pseudo, nom, prenom, email, password } = await request.json();
try {
const user = await prisma.user.create({
data: {
pseudo,
nom,
prenom,
email,
password,
},
});
// Mettre le nouvel utilisateur dans le cache
await redisClient.set(`user:${user.id}`, JSON.stringify(user), { EX: 3600 });
return json(user, { status: 201 });
} catch (err) {
console.error(err);
return json({ error: 'Erreur lors de la création de lutilisateur' }, { status: 500 });
}
}
// Mettre à jour un utilisateur avec PUT
export async function PUT({ params, request }) {
const userId = parseInt(params.id);
const { pseudo, nom, prenom, email, password } = await request.json(); // Assurez-vous d'envoyer tous les champs nécessaires dans le body
try {
// Mettre à jour l'utilisateur dans la base de données
const updatedUser = await prisma.user.update({
where: { id: userId },
data: {
pseudo,
nom,
prenom,
email,
password, // Attention à ne pas oublier de sécuriser le mot de passe avec bcrypt ou une autre méthode
},
});
// Mettre à jour l'utilisateur dans le cache Redis
await redisClient.set(`user:${userId}`, JSON.stringify(updatedUser), 'EX', 3600); // Cache pendant 1 heure (3600 secondes)
return json(updatedUser);
} catch (err) {
console.error(err);
return json({ error: 'Erreur lors de la mise à jour de lutilisateur' }, { status: 500 });
}
}
export async function DELETE({ params }) {
const userId = parseInt(params.id);
try {
await prisma.user.delete({
where: { id: userId },
});
// Supprimer l'utilisateur du cache Redis
await redisClient.del(`user:${userId}`);
return json({ message: 'Utilisateur supprimé avec succès' });
} catch (err) {
console.error(err);
return json({ error: 'Erreur lors de la suppression de lutilisateur' }, { status: 500 });
}
}

View file

@ -0,0 +1,27 @@
// src/routes/api/users/+server.js
import { json } from '@sveltejs/kit';
import redisClient from '$lib/redisClient';
import prisma from '$lib/prismaClient';
export async function GET() {
try {
// Vérifier si les utilisateurs sont dans le cache Redis
const cachedUsers = await redisClient.get('users');
if (cachedUsers) {
console.log('✅ Cache hit');
return json(JSON.parse(cachedUsers));
}
console.log('❌ Cache miss');
// Sinon, récupérer les utilisateurs depuis MongoDB
const users = await prisma.user.findMany();
// Mettre les utilisateurs en cache
await redisClient.set('users', JSON.stringify(users), { EX: 600 });
return json(users);
} catch (err) {
console.error(err);
return json({ error: 'Erreur serveur' }, { status: 500 });
}
}