Loading repository data…
Loading repository data…
jaimeirazabal1 / repository
## Para mis estudiantes Este proyecto es un ejemplo práctico de cómo implementar una **arquitectura basada en eventos** en el mundo real. Lo he diseñado pensando en que aprendan conceptos avanzados de backend mientras desarrollan una aplicación que podrían encontrar en cualquier empresa.
Este proyecto es un ejemplo práctico de cómo implementar una arquitectura basada en eventos en el mundo real. Lo he diseñado pensando en que aprendan conceptos avanzados de backend mientras desarrollan una aplicación que podrían encontrar en cualquier empresa.
Imagina que estás en un restaurante:
Nadie le dice a nadie qué hacer directamente. Todo sucede por eventos.
❌ Forma tradicional (acoplada):
// OrderService llama directamente a otros servicios
class OrderService {
createOrder(order) {
this.orderRepo.save(order);
this.paymentService.processPayment(order); // ❌ Acoplado
this.emailService.sendConfirmation(order); // ❌ Acoplado
this.inventoryService.updateStock(order); // ❌ Acoplado
}
}
✅ Con eventos (desacoplado):
// OrderService solo publica un evento
class OrderService {
async createOrder(order) {
this.orderRepo.save(order);
await this.eventBus.publish('ORDER_CREATED', { order }); // ✅ Desacoplado
}
}
npm install
npm run dev
curl http://localhost:3000/health
curl http://localhost:3000/
src/
├── events/ # 🎯 El corazón del sistema
│ ├── EventBus.ts # Singleton que maneja todos los eventos
│ └── types.ts # Definiciones de cada evento
├── services/ # 🏢 Lógica de negocio
├── handlers/ # 👂 Quién escucha y reacciona a eventos
├── models/ # 📋 Interfaces y tipos
└── routes/ # 🌐 Endpoints HTTP
// Publicar un evento
await eventBus.publish('ORDER_CREATED', { order });
// Suscribirse a un evento
eventBus.subscribe('ORDER_CREATED', (event) => {
console.log('¡Nuevo pedido!', event.payload.order);
});
curl -X POST http://localhost:3000/api/orders \
-H "Content-Type: application/json" \
-d '{
"userId": "user-1",
"restaurantId": "restaurant-1",
"items": [{"menuItemId": "item-1", "quantity": 1, "price": 12.50}],
"deliveryAddress": {
"street": "Tu calle 123",
"city": "Tu ciudad",
"state": "Tu estado",
"zipCode": "12345"
}
}'
📝 Pregunta: ¿Qué eventos se generaron automáticamente?
# Inmediatamente después de crear el pedido
curl http://localhost:3000/api/events/history
📝 Análisis: Cuenta cuántos eventos se generaron y en qué orden.
curl http://localhost:3000/api/events/dashboard
📝 Reflexión: ¿Qué métricas te parecen más importantes para un negocio real?
export interface OrderCreatedEvent extends BaseEvent {
type: 'ORDER_CREATED'; // Nombre único del evento
payload: { // Datos que transporta
order: Order;
};
}
// Guardar el pedido
this.repository.saveOrder(order);
// Avisar al mundo que se creó un pedido
await this.eventBus.publish<OrderCreatedEvent>({
type: 'ORDER_CREATED',
payload: { order }
});
public async handleOrderCreated(event: OrderCreatedEvent): Promise<void> {
const { order } = event.payload;
// Reaccionar al evento: iniciar el pago
await this.paymentService.initiatePayment({
orderId: order.id,
amount: order.totalAmount,
method: 'tarjeta_credito'
});
}
customerNotes al modelo OrderGET /api/orders/recent que devuelva los últimos 5 pedidosGET /api/orders para filtrar por estadoORDER_CANCELLED_BY_RESTAURANTNotificationService que se suscriba a múltiples eventos# Los logs del servidor te dirán todo
# Busca estos símbolos:
# 📢 = Evento publicado
# 🔄 = Handler procesando
# ✅ = Handler completado
# ❌ = Error en handler
GET /api/events/stats - Estadísticas de eventosGET /api/events/type/ORDER_CREATED - Solo eventos de un tipoDELETE /api/events/history - Limpiar historial para pruebas¿Qué pasaría si un handler falla? Busca en EventBus.ts cómo se maneja esto.
¿Cómo agregarías un nuevo servicio sin modificar código existente? Piensa en términos de eventos.
¿Qué eventos agregarías para un sistema de calificaciones? Diseña el flujo completo.
¿Cómo implementarías notificaciones push? ¿Qué eventos necesitarías escuchar?
Una vez que domines este proyecto, estarás listo para:
Reto: Implementa un sistema de cupones de descuento que:
LOYALTY_REWARD_EARNEDPistas:
Este proyecto simula decisiones reales que toman empresas como Uber, Netflix o Amazon. Cada evento que implementamos resuelve un problema de escalabilidad o mantenibilidad que enfrentarían en producción.
Recuerda: En programación, como en la vida, es mejor que los componentes cooperen sin depender unos de otros. Los eventos son tu herramienta para lograr esa independencia.
¡Diviértete explorando y haciendo experimentos! 🎉