Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Luisanchez0/modulo_Horario/llms.txt

Use this file to discover all available pages before exploring further.

Módulo Horario is a distributed system made up of four independent FastAPI microservices. Each service owns its data store, exposes its own REST API, and can be deployed and scaled separately. The React frontend talks directly to whichever service owns the data it needs. The horario-service additionally calls the other three services at runtime to validate references before writing schedule entries.

Architecture overview

┌─────────────────────────────────────────┐
│          Frontend (React 19)            │
│       http://localhost:5173             │
└────────────────────┬────────────────────┘

     ┌───────────────┼───────────────┐
     │               │               │
     ▼               ▼               ▼
┌──────────┐   ┌──────────┐   ┌──────────┐
│ Usuarios │   │ Horarios │   │ Materias │
│ Service  │   │ Service  │   │ Service  │
│  (8001)  │   │  (8004)  │   │  (8002)  │
└────┬─────┘   └────┬─────┘   └────┬─────┘
     │              │               │
     │    ┌─────────┤               │
     │    │  calls  │               │
     │    │  8001,  │               │
     │    │  8002,  │               │
     │    │  8003   │               │
     │    └─────────┘               │
     │                              │
     └──────────┬───────────────────┘

            ┌───▼────┐    ┌──────────┐
            │ MySQL  │    │PostgreSQL│
            └────────┘    └──────────┘

The four services

usuarios-service

Authentication, teacher management, and rate-limited login on port 8001.

materias-service

Subject catalog with async I/O via asyncpg on port 8002.

aulas-service

Classroom inventory and capacity management on port 8003.

horario-service

Schedule generation, period management, and cross-service validation on port 8004.

usuarios-service (port 8001)

usuarios-service is the authentication and teacher management service. It issues JWT tokens (HS256) signed with JWT_SECRET and enforces role-based access with ADMIN and DOCENTE roles. Login endpoints are protected by request rate limiting via slowapi, which returns HTTP 429 when a caller exceeds the threshold. Teachers are stored in MySQL. The service exposes both public endpoints (login, register) and internal endpoints (teacher lookup) under /internal/docentes, which require the X-Internal-Key header matching INTERNAL_API_KEY. Key environment variables (from docker-compose.yml):
DATABASE_URL=mysql+pymysql://root:<password>@mysql/docentes_db
JWT_SECRET=<secret>
ADMIN_CREATION_KEY=<secret>
INTERNAL_API_KEY=<secret>
CORS_ALLOW_ORIGINS=http://localhost:5173,...
APP_PORT=8001

materias-service (port 8002)

materias-service maintains the subject catalog. It is built with async FastAPI and uses asyncpg for non-blocking PostgreSQL access — the DATABASE_URL uses the postgresql+asyncpg:// scheme. The service verifies the JWT token for write operations by calling usuarios-service at the URL specified by USUARIOS_SERVICE_URL. Key environment variables:
DATABASE_URL=postgresql+asyncpg://postgres:<password>@postgres:5432/materias_db
USUARIOS_SERVICE_URL=http://usuarios-service:8001
UPSTREAM_TIMEOUT_SECONDS=5
APP_PORT=8002

aulas-service (port 8003)

aulas-service stores classroom records (name, capacity, location) in MySQL. Like materias-service, it delegates auth token verification to usuarios-service. Key environment variables:
DATABASE_URL=mysql+pymysql://root:<password>@mysql/aulas_db
USUARIOS_SERVICE_URL=http://usuarios-service:8001
UPSTREAM_TIMEOUT_SECONDS=5
APP_PORT=8003

horario-service (port 8004)

horario-service is the most complex service. It owns the schedule and period data in PostgreSQL, and it orchestrates data from the other three services at request time using CatalogServicesClient. Before persisting a schedule entry, it validates that the referenced teacher, subject, and classroom each exist in their respective owning services. The client calls internal usuarios-service endpoints with the X-Internal-Key header. Calls to materias-service and aulas-service use their public APIs.
# src/infrastructure/clients/catalog_services_client.py
def docente_exists(self, docente_id: int) -> bool:
    url = f"{settings.usuarios_service_url}/internal/docentes/{docente_id}"
    return self._exists(url, headers={"X-Internal-Key": settings.internal_api_key})

def materia_exists(self, materia_id: int) -> bool:
    url = f"{settings.materias_service_url}/api/v1/materias/{materia_id}"
    return self._exists(url)

def aula_exists(self, aula_id: int) -> bool:
    url = f"{settings.aulas_service_url}/aulas/{aula_id}"
    return self._exists(url)
Key environment variables:
DATABASE_URL=postgresql://postgres:<password>@postgres:5432/horarios_db
USUARIOS_SERVICE_URL=http://usuarios-service:8001
MATERIAS_SERVICE_URL=http://materias-service:8002
AULAS_SERVICE_URL=http://aulas-service:8003
INTERNAL_API_KEY=<secret>
UPSTREAM_TIMEOUT_SECONDS=5
APP_PORT=8004

Database layout

Two database engines are shared across the four services. Each service connects to its own logical database.
EngineServicesLogical databases
MySQL 8usuarios-service, aulas-servicedocentes_db, aulas_db
PostgreSQL 16materias-service, horario-servicematerias_db, horarios_db
In Docker Compose, MySQL is exposed on host port 3307 and PostgreSQL on 5433 to avoid conflicts with any locally installed database servers.

Inter-service communication

horario-service is the only service that initiates calls to other services. All other inter-service communication flows from the frontend directly to each service’s REST API. At runtime, horario-service uses CatalogServicesClient to:
  • Look up and validate teacher IDs against usuarios-service (/internal/docentes)
  • Look up and validate subject IDs against materias-service (/api/v1/materias)
  • Look up and validate classroom IDs against aulas-service (/aulas)
  • Resolve human-readable labels (name, email, subject code, classroom capacity) for schedule display
All calls from horario-service to usuarios-service carry an X-Internal-Key: <INTERNAL_API_KEY> header. Calls time out after UPSTREAM_TIMEOUT_SECONDS (default: 5 seconds), and any upstream error raises an UpstreamServiceError.

CORS configuration

All four services share the same CORS policy, configured through the CORS_ALLOW_ORIGINS environment variable. The default value allows requests from the frontend and from each service to the others:
http://localhost:5173
http://localhost:8001
http://localhost:8002
http://localhost:8003
http://localhost:8004
This is set identically in all four service definitions in docker-compose.yml and defaults to the same list in each service’s Python startup code when the variable is absent.

Build docs developers (and LLMs) love