Skip to content
 
 

Repository files navigation

Voyanta — Système complet (microservices)

Implémentation fonctionnelle de Voyanta en architecture microservices, conforme au cahier des charges et au plan d'architecture "Phase 2" (User Service / Itinerary Service / Recommendation Service derrière un API Gateway, communication REST synchrone + événements asynchrones via RabbitMQ), entièrement dockerisée.

                         ┌─────────────────┐
                         │   Frontend       │  (React, servi par Nginx)
                         │   :5173          │
                         └────────┬─────────┘
                                  │
                         ┌────────▼─────────┐
                         │   API Gateway     │  (Nginx) :8080
                         └───┬───────┬───┬───┘
              ┌──────────────┘       │   └──────────────┐
              ▼                      ▼                  ▼
     ┌────────────────┐   ┌───────────────────┐  ┌─────────────────────┐
     │  User Service    │   │ Itinerary Service │  │ Recommendation Svc   │
     │  :5001           │   │ :5002              │  │ :5003                │
     │  - auth (JWT)     │   │ - destinations     │  │ - lit User Service   │
     │  - profils        │   │ - distances/coûts  │  │   et Itinerary Svc   │
     │  - favoris        │   │ - itinéraires      │  │   (REST synchrone)   │
     └────────┬─────────┘   └─────────┬──────────┘  │ - consomme les       │
              │                       │              │   événements         │
      ┌───────▼───────┐      ┌────────▼────────┐     │   RabbitMQ           │
      │   user-db      │      │  itinerary-db    │     │   (asynchrone)       │
      │  (PostgreSQL)  │      │  (PostgreSQL/PostGIS) │ └──────────┬───────────┘
      └────────────────┘      └────────┬────────┘                │
                                        │        ┌─────────────────┘
                                        ▼        ▼
                                 ┌────────────┐ ┌───────┐
                                 │  RabbitMQ   │ │ Redis  │
                                 └────────────┘ └───────┘

Démarrage

Prérequis : Docker et Docker Compose.

cp .env.example .env   # puis changez JWT_SECRET_KEY
docker compose up --build

Une fois les conteneurs démarrés (comptez 30 à 60 secondes le premier lancement, le temps que les bases de données soient prêtes et que les destinations de démonstration soient chargées) :

Service URL
Frontend http://localhost:5173
API Gateway http://localhost:8080
Console RabbitMQ http://localhost:15672 (guest / guest)

Testez rapidement que tout communique :

curl http://localhost:8080/api/v1/destinations | head -c 300
curl -X POST http://localhost:8080/api/v1/auth/register \
  -H "Content-Type: application/json" \
  -d '{"email":"test@voyanta.cm","password":"motdepasse123","first_name":"Aline"}'

Les trois microservices

User Service (services/user-service, port 5001)

Possède exclusivement les données utilisateurs (voyanta_users, base PostgreSQL dédiée). Gère l'inscription, la connexion (JWT via Argon2), le profil, les préférences de voyage et les favoris.

Endpoints principaux :

POST   /api/v1/auth/register
POST   /api/v1/auth/login
GET    /api/v1/auth/me
PATCH  /api/v1/users/me
GET    /api/v1/users/me/favorites
POST   /api/v1/users/me/favorites/<destination_id>
DELETE /api/v1/users/me/favorites/<destination_id>
GET    /api/v1/users/<id>/public-profile   # interne, appelé par le Recommendation Service

Itinerary Service (services/itinerary-service, port 5002)

Possède les destinations, les tarifs de transport et les itinéraires (base PostgreSQL/PostGIS dédiée voyanta_itineraries). Calcule systématiquement distance et coût côté serveur — jamais confiés au client (règle explicite du cahier des charges, section 14.4). Publie un événement itinerary.created sur RabbitMQ à chaque création de voyage.

Endpoints principaux :

GET    /api/v1/destinations
GET    /api/v1/destinations/<id>
GET    /api/v1/destinations/nearby
POST   /api/v1/routes/calculate
POST   /api/v1/routes/matrix
GET    /api/v1/costs/rates
POST   /api/v1/costs/calculate
GET    /api/v1/itineraries
POST   /api/v1/itineraries
PATCH  /api/v1/itineraries/<id>
DELETE /api/v1/itineraries/<id>

Note de conception : le cahier des charges d'origine prévoyait un Destination Service séparé. Le plan d'architecture "Phase 2" fourni ensuite ne liste que trois services (User / Itinerary / Recommendation). Les destinations ont donc été rattachées à l'Itinerary Service, qui en est le principal consommateur — c'est aussi la première extraction suggérée si le besoin s'en fait sentir plus tard (voir section 8 de GUIDE_COMPLET.md du dossier frontend/).

Recommendation Service (services/recommendation-service, port 5003)

Ne possède aucune donnée propre : il lit le User Service et l'Itinerary Service.

  • Synchrone : à chaque appel à GET /api/v1/recommendations, il interroge en REST le profil public de l'utilisateur (favoris, catégories préférées) sur le User Service, et la liste des destinations sur l'Itinerary Service.
  • Asynchrone : un processus séparé (consumer.py, lancé en parallèle du serveur HTTP — voir le Dockerfile) écoute en continu la queue RabbitMQ itinerary.created et met à jour un compteur de tendances (catégories et régions les plus demandées) dans Redis, utilisé pour enrichir le score de recommandation de tous les utilisateurs, y compris ceux non connectés.
GET /api/v1/recommendations?limit=6

API Gateway

api-gateway/nginx.conf route chaque famille d'URL vers le bon service et centralise CORS et les logs d'accès (section 4.3.1 du cahier des charges). C'est le seul point d'entrée que le frontend appelle.

Frontend

Le dossier frontend/ contient l'application React déjà livrée précédemment, désormais branchée sur le vrai backend (plus de données mockées) :

  • src/context/AuthContext.tsx — session utilisateur (JWT stocké en localStorage, à faire évoluer vers un cookie httpOnly en production).
  • src/services/*.ts — un fichier par domaine (authService, destinationService, itineraryService, recommendationService), chacun n'appelant que les routes qui le concernent.
  • Nouvelles pages : Connexion, Inscription, Profil (préférences de voyage), Favoris. Mes voyages liste désormais les vrais itinéraires enregistrés en base.
  • La page d'accueil affiche une section "Recommandé pour vous" quand l'utilisateur est connecté (sinon "Près de vous", basé sur les tendances globales) — alimentée par le Recommendation Service.

Les cartes de destination gardent un calcul d'aperçu côté client (distance à vol d'oiseau) pour éviter un appel réseau par carte affichée dans une liste ; la page de détail et la création d'itinéraire, elles, appellent toujours le backend pour le chiffre définitif.

Ce qui reste volontairement hors de ce livrable

Conformément à la feuille de route du cahier des charges (section 18.2), n'ont pas été implémentés : avis/modération, espace partenaires, espace administrateur, réservation, paiement Mobile Money, application mobile native, mode hors connexion complet, distance routière réelle (OSRM est documenté mais pas branché — le calcul actuel utilise une distance à vol d'oiseau majorée de 18 %, isolée dans geo.py pour un remplacement en un seul endroit). Le dossier frontend/GUIDE_COMPLET.md détaille comment brancher chacun de ces éléments.

Sécurité — ce qui est déjà en place

  • Mots de passe hachés avec Argon2 (jamais en clair, jamais en MD5/SHA seul)
  • JWT signé avec un secret partagé entre les trois services (JWT_SECRET_KEY)
  • Le coût et la distance affichés sont toujours recalculés par l'Itinerary Service ; le frontend n'envoie jamais de montant à enregistrer tel quel
  • CORS restreint par route dans l'API Gateway (* en développement — à remplacer par le domaine réel avant mise en production)
  • Chaque service a sa propre base de données : aucune clé étrangère SQL ne traverse les services (référence logique par identifiant uniquement), conformément au principe d'isolation des microservices

À faire avant une mise en production réelle : passer JWT_SECRET_KEY à une vraie valeur secrète (jamais celle du .env.example), restreindre CORS, ajouter un rate-limiter sur /auth/login, servir le tout derrière HTTPS.

Commandes utiles

# Voir les logs d'un service en particulier
docker compose logs -f itinerary-service

# Réinitialiser complètement les données (supprime les volumes des bases)
docker compose down -v

# Reconstruire un seul service après une modification
docker compose up --build recommendation-service

# Ouvrir un shell dans un conteneur pour déboguer
docker compose exec itinerary-service sh

About

GlobeTrotter Travel Assistant – A distributed travel recommendation system built as a semester-long capstone project. Students starts by building a monolith, then refactor to microservices, and finally deploy to the cloud. They add resilience patterns using Docker, Kubernetes, and cloud-native tools.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages