Arquitectura del Sistema¶
Visión general¶
Bazaar está construido como un conjunto de microservicios independientes, cada uno con su propia base de datos y responsabilidad bien definida. Los clientes (app mobile y backoffice web) nunca se comunican directamente con los servicios: todas las peticiones pasan por un API Gateway que se encarga del enrutamiento y la autenticación.
┌─────────────────┐ ┌─────────────────┐
│ Mobile App │ │ Backoffice │
│ (React Native) │ │ (React + Vite) │
└────────┬────────┘ └────────┬────────┘
│ │
└─────────────┬─────────────┘
│
┌────────▼────────┐
│ Kong Gateway │ ← Punto único de entrada
│ (JWT · roles) │
└──┬──────┬───┬───┘
│ │ │
┌─────────▼─┐ ┌──▼──────────┐ ┌──────────────────┐
│user-service│ │product-svc │ │ checkout-service │
│ (FastAPI) │ │ (FastAPI) │ │ (FastAPI) │
└─────┬──────┘ └──┬──────────┘ └────────┬─────────┘
│ │ │
┌─────▼──────┐ ┌───▼──────┐ ┌───────▼────────┐
│ PostgreSQL │ │ MongoDB │ │ PostgreSQL │
└────────────┘ └──────────┘ └────────────────┘
│ │
│ ┌─────────────────┘
│ │ publica eventos
▼ ▼
┌─────────────┐
│ RabbitMQ │ ← Mensajería asíncrona
└──────┬──────┘
│ consume
┌────────▼──────────┐
│notification-service│
│ (Go) │
└────────┬──────────┘
│
┌────────▼──────────┐
│ Expo Push API │ ← Notificaciones mobile
└───────────────────┘
¿Por qué microservicios?¶
En lugar de tener toda la lógica en una sola aplicación, el sistema se divide en servicios más chicos que se pueden desarrollar, testear y desplegar de forma independiente. Cada servicio tiene su propia base de datos, lo que evita acoplamientos y permite que un equipo trabaje en un servicio sin afectar a los demás.
¿Qué hace el API Gateway?¶
Kong recibe todas las peticiones de los clientes y se encarga de:
- Redirigirlas al servicio correcto según la URL (ej:
/users/*va al user-service,/products/*va al product-service,/checkout/*va al checkout-service). - Validar el token JWT en las rutas que requieren autenticación.
- Extraer la identidad del usuario del token y pasarla como header al servicio backend, para que los servicios sepan quién está haciendo el request sin tener que parsear el token ellos mismos.
- Verificar el rol de administrador en las rutas del panel de admin.
Servicios¶
| Servicio | Lenguaje / Framework | Base de datos | Responsabilidad |
|---|---|---|---|
| user-service | Python / FastAPI | PostgreSQL | Autenticación, perfiles, administración de usuarios |
| product-service | Python / FastAPI | MongoDB | Catálogo de productos, stock, imágenes, categorías |
| checkout-service | Python / FastAPI | PostgreSQL | Carrito, checkout con MercadoPago, ciclo de vida de órdenes, cupones y reseñas |
| notification-service | Go / net/http | MongoDB | Push notifications a vendedores por stock bajo o agotado |
| backoffice | TypeScript / React + Vite | — | Panel web de administración |
| mobileApp | TypeScript / React Native + Expo | — | App mobile para compradores y vendedores |
Mensajería asíncrona (RabbitMQ)¶
Los servicios se comunican de forma asíncrona a través de RabbitMQ para desacoplarse entre sí. Los eventos fluyen así:
| Exchange | Routing key | Publicador | Consumidor | Cuándo |
|---|---|---|---|---|
bazaar.payments |
payment.confirmed |
checkout-service | product-service | Pago aprobado por MercadoPago → descuenta stock definitivamente |
bazaar.payments |
payment.rejected |
checkout-service | product-service | Pago rechazado o orden expirada → restaura el stock reservado |
bazaar.stock |
stock.updated |
product-service | notification-service | Stock de un producto cae por debajo del umbral → dispara push al vendedor |
Flujo de una compra¶
Comprador checkout-service product-service MercadoPago
│ │ │ │
│─── POST /checkout ──▶│ │ │
│ │── reserva stock ──▶│ │
│ │◀── OK ─────────────│ │
│ │── crea preferencia ────────────────▶ │
│◀── init_point ───────│ │ │
│ │ │ │
│── paga en MP ──────────────────────────────────────────────▶│
│ │◀── webhook (approved/rejected) ───────│
│ │ │ │
│ │── payment.confirmed/rejected ──▶ [RabbitMQ]
│ │ │◀── consume ──────│
│ │ │ ajusta stock │
Servicios externos¶
| Servicio | Para qué lo usamos |
|---|---|
| Supabase Auth | Maneja el registro, login, OAuth con Google y recupero de contraseña. Emite los JWT que usa todo el sistema. |
| Cloudinary | Almacena las imágenes de perfil y de productos. En la base de datos solo guardamos la URL. |
| MercadoPago | Procesamiento de pagos. El checkout-service genera una preferencia de pago y recibe el resultado vía webhook. |
| Expo Push API | Envío de notificaciones push a la app mobile. El notification-service llama a esta API cuando detecta stock bajo. |
Decisiones de tecnología¶
| Decisión | Qué elegimos | Por qué |
|---|---|---|
| BD del user-service | PostgreSQL | Los datos de usuarios tienen estructura fija y relaciones claras (usuario → identidades federadas). Una base relacional es lo más natural. |
| BD del product-service | MongoDB | Los productos pueden tener atributos distintos según la categoría (ej: talle en ropa, memoria en electrónica). Un modelo de documentos permite esa flexibilidad sin tener que alterar el esquema. |
| BD del checkout-service | PostgreSQL | Las órdenes y sus ítems tienen estructura fija y relaciones claras (orden → ítems, historial). Alembic maneja las migraciones. |
| BD del notification-service | MongoDB | Los tokens de dispositivo y notificaciones son documentos simples sin relaciones fuertes. |
| Autenticación | Supabase Auth | Nos da JWT, OAuth con Google, recupero de contraseña y gestión de sesiones sin tener que implementarlo desde cero. |
| Imágenes | Cloudinary | CDN con plan gratuito suficiente para el proyecto. Subimos la imagen y obtenemos una URL pública. |
| Pagos | MercadoPago | Gateway de pagos ampliamente usado en Latinoamérica. La integración se hace vía preferencias y webhooks. |
| Push notifications | Expo Push API | Compatible nativamente con React Native/Expo. Abstrae iOS (APNs) y Android (FCM) en un único endpoint. |
| Mensajería | RabbitMQ | Broker de mensajería liviano que desacopla los servicios. Permite que el product-service restaure stock sin que el checkout-service lo llame directamente. |
| API Gateway | Kong (OSS) | Se integra nativamente con Kubernetes y permite agregar lógica custom con plugins Lua (validación de JWT, extracción de email, chequeo de rol admin). |
| Despliegue | Kubernetes + ArgoCD | Despliegue declarativo con GitOps: cuando se pushea una imagen nueva, ArgoCD detecta el cambio y actualiza el servicio automáticamente. |
| Lenguaje del notification-service | Go | Binario liviano ideal para un servicio que solo consume eventos y dispara llamadas HTTP. Concurrencia nativa con goroutines. |