Ajouts des models et de l'api avec gestion du cache
This commit is contained in:
parent
267dcdf5ea
commit
431c77f970
8 changed files with 472 additions and 0 deletions
|
@ -36,6 +36,9 @@
|
||||||
"vite": "^5.0.3"
|
"vite": "^5.0.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@prisma/client": "^5.22.0",
|
||||||
|
"prisma": "^5.22.0",
|
||||||
|
"redis": "^4.7.0",
|
||||||
"svelte-radix": "^2.0.1"
|
"svelte-radix": "^2.0.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
4
src/lib/prismaClient.ts
Normal file
4
src/lib/prismaClient.ts
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
import { PrismaClient } from '@prisma/client';
|
||||||
|
|
||||||
|
const prisma = new PrismaClient();
|
||||||
|
export default prisma;
|
11
src/lib/redisClient.ts
Normal file
11
src/lib/redisClient.ts
Normal 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;
|
123
src/routes/api/canal/[id]/+server.js.ts
Normal file
123
src/routes/api/canal/[id]/+server.js.ts
Normal 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 });
|
||||||
|
}
|
||||||
|
}
|
149
src/routes/api/canal/[id]/messages/+server.ts
Normal file
149
src/routes/api/canal/[id]/messages/+server.ts
Normal 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 l’ID et le pseudo de l’utilisateur
|
||||||
|
},
|
||||||
|
},
|
||||||
|
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 d’un 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 d’un 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;
|
||||||
|
}
|
||||||
|
}
|
47
src/routes/api/canals/+server.ts
Normal file
47
src/routes/api/canals/+server.ts
Normal 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 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
108
src/routes/api/user/[id]/+server.ts
Normal file
108
src/routes/api/user/[id]/+server.ts
Normal 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 l’utilisateur' }, { 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 l’utilisateur' }, { 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 l’utilisateur' }, { status: 500 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
27
src/routes/api/users/+server.ts
Normal file
27
src/routes/api/users/+server.ts
Normal 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 });
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue