Files
trenes/FASE1-MVP.md
Millaguie 34c0cb50c7
Some checks failed
Auto Tag on Merge to Main / auto-tag (push) Successful in 27s
CI - Lint and Build / lint-backend (push) Failing after 30s
CI - Lint and Build / lint-frontend (push) Failing after 2s
CI - Lint and Build / build-frontend (push) Has been skipped
CI - Lint and Build / docker-build-test (push) Has been skipped
feat: Initial commit - Train tracking system
Complete real-time train tracking system for Spanish railways (Renfe/Cercanías):

- Backend API (Node.js/Express) with GTFS-RT polling workers
- Frontend dashboard (React/Vite) with Leaflet maps
- Real-time updates via Socket.io WebSocket
- PostgreSQL/PostGIS database with Flyway migrations
- Redis caching layer
- Docker Compose configuration for development and production
- Gitea CI/CD workflows (lint, auto-tag, release)
- Production deployment with nginx + Let's Encrypt SSL

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 00:21:15 +01:00

10 KiB

Fase 1: MVP - Sistema de Tracking de Trenes en Tiempo Real

Estado: COMPLETADO

La Fase 1 del roadmap ha sido implementada exitosamente. Este documento describe lo que se ha construido y cómo probarlo.


Características Implementadas

Backend

  • Worker GTFS-RT que recolecta posiciones cada 30 segundos
  • API REST con endpoints para trenes, rutas, estaciones y estadísticas
  • WebSocket server para actualizaciones en tiempo real
  • Integración con PostgreSQL + PostGIS
  • Cache Redis para posiciones actuales
  • Sistema de logs con Pino
  • Gestión de errores y reconexión automática

Frontend

  • Mapa interactivo con Leaflet.js y OpenStreetMap
  • Visualización de trenes en tiempo real
  • Panel de información detallada de cada tren
  • Conexión WebSocket con reconexión automática
  • Timeline básico (UI preparado, funcionalidad fase 2)
  • Estadísticas en header (trenes activos, última actualización)
  • Diseño responsivo

📁 Estructura del Proyecto

trenes/
├── backend/
│   ├── src/
│   │   ├── api/
│   │   │   ├── routes/
│   │   │   │   ├── trains.js      # Endpoints de trenes
│   │   │   │   ├── routes.js      # Endpoints de rutas
│   │   │   │   ├── stations.js    # Endpoints de estaciones
│   │   │   │   └── stats.js       # Endpoints de estadísticas
│   │   │   └── server.js          # Servidor API + WebSocket
│   │   ├── worker/
│   │   │   └── gtfs-poller.js     # Worker GTFS-RT
│   │   ├── lib/
│   │   │   ├── db.js              # Cliente PostgreSQL
│   │   │   ├── redis.js           # Cliente Redis
│   │   │   └── logger.js          # Logger Pino
│   │   └── config/
│   │       └── index.js           # Configuración
│   ├── package.json
│   ├── Dockerfile
│   └── .env.example
│
├── frontend/
│   ├── src/
│   │   ├── components/
│   │   │   ├── TrainMap.jsx       # Mapa Leaflet
│   │   │   ├── TrainInfo.jsx      # Panel de información
│   │   │   └── Timeline.jsx       # Timeline (UI)
│   │   ├── hooks/
│   │   │   └── useTrains.js       # Hook WebSocket
│   │   ├── styles/
│   │   │   └── index.css          # Estilos globales
│   │   ├── App.jsx                # Componente principal
│   │   └── main.jsx               # Entry point
│   ├── package.json
│   ├── Dockerfile
│   └── vite.config.js
│
├── database/
│   ├── init/                      # Scripts iniciales
│   └── migrations/                # Migraciones Flyway
│
├── docker-compose.yml
├── Makefile
└── README.md

🚀 Cómo Ejecutar el MVP

Prerrequisitos

  • Docker y Docker Compose instalados
  • Puerto 80, 3000, 5432, 6379 disponibles
  • (Opcional) Make para comandos simplificados

Opción 1: Usando Make (Recomendado)

# 1. Configurar variables de entorno
cp .env.example .env
# Editar .env si es necesario

# 2. Ejecutar migraciones
make migrate

# 3. Iniciar todos los servicios
make start

# 4. Ver logs
make logs

Opción 2: Docker Compose Manual

# 1. Configurar variables de entorno
cp .env.example .env

# 2. Ejecutar migraciones
docker-compose --profile migration up flyway

# 3. Iniciar servicios
docker-compose up -d

# 4. Ver logs
docker-compose logs -f

Opción 3: Desarrollo Local (sin Docker)

Backend

cd backend

# Instalar dependencias
npm install

# Configurar .env
cp .env.example .env
# Ajustar DATABASE_URL y REDIS_URL a localhost

# Ejecutar worker en una terminal
npm run dev:worker

# Ejecutar API en otra terminal
npm run dev

Frontend

cd frontend

# Instalar dependencias
npm install

# Ejecutar en modo desarrollo
npm run dev

🌐 Acceder a la Aplicación

Una vez iniciados los servicios:


📡 Endpoints de la API

Trenes

# Obtener todos los trenes activos
GET /trains/current

# Obtener información de un tren específico
GET /trains/:id

# Obtener histórico de un tren
GET /trains/:id/history?from=2025-11-27T00:00:00Z&to=2025-11-27T23:59:59Z&limit=100

# Obtener trayectoria de un tren
GET /trains/:id/path?from=2025-11-27T10:00:00Z&to=2025-11-27T11:00:00Z

# Obtener trenes en un área geográfica
GET /trains/area?minLat=40.0&minLon=-4.0&maxLat=41.0&maxLon=-3.0

Rutas

# Obtener todas las rutas
GET /routes

# Obtener ruta específica
GET /routes/:id

Estaciones

# Obtener todas las estaciones
GET /stations

# Obtener estaciones por tipo
GET /stations?type=MAJOR

# Obtener estación específica
GET /stations/:id

Estadísticas

# Obtener estadísticas del sistema
GET /stats

# Obtener estadísticas de un tren
GET /stats/train/:id?from=2025-11-27T00:00:00Z&to=2025-11-27T23:59:59Z

🔌 WebSocket Events

Cliente → Servidor

// Suscribirse a un tren específico
socket.emit('subscribe:train', trainId);

// Desuscribirse de un tren
socket.emit('unsubscribe:train', trainId);

Servidor → Cliente

// Actualización de todos los trenes (cada 2 segundos)
socket.on('trains:update', (positions) => {
  console.log('Posiciones actualizadas:', positions);
});

// Actualización de un tren específico (si estás suscrito)
socket.on('train:update', (position) => {
  console.log('Tren actualizado:', position);
});

🧪 Probar el Sistema

1. Verificar que el Worker está funcionando

# Ver logs del worker
make logs-worker

# O con docker-compose
docker-compose logs -f worker

# Deberías ver mensajes como:
# "Polling GTFS-RT feed..."
# "Processed vehicle positions: {trains: 50, duration: 1234}"

2. Verificar API

# Health check
curl http://localhost:3000/health

# Obtener trenes actuales
curl http://localhost:3000/trains/current | jq

# Obtener estadísticas
curl http://localhost:3000/stats | jq

3. Verificar Base de Datos

# Conectar a PostgreSQL
make psql

# Ver trenes almacenados
SELECT COUNT(*) FROM trains;

# Ver posiciones de las últimas 24 horas
SELECT COUNT(*) FROM train_positions WHERE recorded_at > NOW() - INTERVAL '24 hours';

# Ver estaciones
SELECT * FROM stations LIMIT 10;

4. Verificar Redis

# Conectar a Redis
make redis-cli

# Ver trenes activos
SMEMBERS trains:active

# Ver posición actual de un tren
GET trains:current:TRAIN_ID

🐛 Troubleshooting

No se ven trenes en el mapa

Causa: El feed GTFS-RT puede no tener datos o el worker no está corriendo.

Solución:

# Verificar logs del worker
make logs-worker

# Verificar si hay trenes en Redis
make redis-cli
> SMEMBERS trains:active

# Si Redis está vacío, verificar PostgreSQL
make psql
> SELECT COUNT(*) FROM train_positions WHERE recorded_at > NOW() - INTERVAL '1 hour';

Error de conexión WebSocket

Causa: CORS o URL incorrecta.

Solución:

# Verificar que VITE_WS_URL está configurado correctamente
# En .env.testing o variables de entorno del frontend

# Debería ser: http://localhost:3000 (desarrollo) o ws://localhost/ws (producción)

La base de datos no tiene datos

Causa: Migraciones no ejecutadas o feed GTFS-RT sin datos.

Solución:

# Ejecutar migraciones
make migrate

# Verificar estado de migraciones
make migrate-info

# Ver datos iniciales
make psql
> SELECT * FROM stations LIMIT 5;

Error "PostgreSQL not connected"

Causa: PostgreSQL no está corriendo o configuración incorrecta.

Solución:

# Verificar que PostgreSQL está corriendo
docker-compose ps postgres

# Reiniciar PostgreSQL
docker-compose restart postgres

# Verificar logs
docker-compose logs postgres

📊 Métricas y Monitorización

Logs del Sistema

# Ver todos los logs
make logs

# Ver logs específicos
make logs-api       # API
make logs-worker    # Worker
make logs-db        # PostgreSQL

Estadísticas del Worker

El worker registra estadísticas cada 60 segundos:

{
  "totalPolls": 120,
  "successfulPolls": 118,
  "failedPolls": 2,
  "totalTrains": 45,
  "lastPollTime": "2025-11-27T10:30:00.000Z",
  "successRate": "98.33%"
}

Panel de Administración

Para acceder a herramientas de administración:

# Iniciar con modo debug
make debug-start

# Acceder a:
# - Adminer (PostgreSQL): http://localhost:8080
# - Redis Commander: http://localhost:8081

🎯 Próximos Pasos (Fase 2)

La Fase 2 incluirá:

  • Integración GTFS Static (rutas, horarios)
  • Trip Updates (retrasos, cancelaciones)
  • Service Alerts (incidencias)
  • Timeline funcional con reproducción histórica
  • Monitor de puntualidad
  • Panel de incidencias

Para más información, consultar el roadmap completo.


📝 Notas Técnicas

Fuente de Datos

El sistema consume el feed GTFS-RT de Renfe:

Almacenamiento

  • PostgreSQL: Histórico completo de posiciones (particionado por mes)
  • Redis: Cache de últimas posiciones (TTL 5 minutos)
  • WebSocket: Broadcast en tiempo real (cada 2 segundos)

Rendimiento

  • Polling: 30 segundos (configurable via POLLING_INTERVAL)
  • Broadcast WS: 2 segundos
  • Particiones DB: Mensuales (nov 2025 - mar 2027)
  • Retención: 90 días (configurable, usar cleanup_old_positions())

📚 Documentación Adicional


🤝 Contribuir

Si encuentras bugs o quieres proponer mejoras:

  1. Crea un issue describiendo el problema/mejora
  2. Haz un fork del proyecto
  3. Crea una rama para tu feature
  4. Envía un pull request

Estado: Fase 1 MVP Completada Fecha: 27 noviembre 2025 Próxima Fase: Fase 2 - Enriquecimiento