Appearance
Sistema de Background Jobs - Documentación Completa
Sistema: Background Jobs (Tareas en Segundo Plano) Estado: Implementado (Fases 1-3 completas) Fecha: 2026-02-05 Ultima actualizacion: 2026-02-26
Estado Actual: SSE Temporalmente Deshabilitado
⚠️ SSE deshabilitado temporalmente
El endpoint
GET /backend/jobs/{id}/streamexiste en el backend pero el frontend usa exclusivamente HTTP polling (useBackgroundJob) hasta que se refactorice el sistema de autenticación.Causa técnica: El
ACCESS_TOKENse asigna en el dominioapp.commedianteRequest::syncCookies().EventSourceno puede enviar headers custom (Authorization) y el browser no envía cookies deapp.comaapi.com(cross-domain). La solución requiere unificar la estrategia de cookies o implementar un proxy SSE.El hook
useJobStreames actualmente un wrapper sobre polling HTTP. La interfaz SSE está diseñada para activarse cuando se resuelva el auth cross-domain.
Descripción
Sistema genérico para ejecutar operaciones de larga duración de forma asíncrona, liberando al usuario de esperar en el navegador. Implementa ejecución en background con notificaciones, consulta de estado y monitoreo.
Casos de uso:
- Facturación masiva (500+ facturas, 3-10 minutos)
- Reportes consolidados multi-schema (2-5 minutos)
- Importación de datos CSV/Excel (5-15 minutos)
- Sincronización AFIP (2-8 minutos)
Estructura de Documentación
📐 Arquitectura y Decisiones
architecture.md (649 líneas)
- Problema arquitectural
- Solución seleccionada: SSE + PostgreSQL NOTIFY
- Roadmap de implementación (4 fases)
- Escalabilidad y migración a RabbitMQ
- Patrones utilizados
frontend-notification-dispatch-process.md
- Cadena de despacho de notificaciones de jobs en el frontend (Tier 1 → 2 → 2.5 → 3)
- Recuperacion de resultado via URL-param (
action_url,?job_id=) - Generacion de
action_urlen backend, invariantes, extensibilidad
adrs/ (7 ADRs)
- ADR-001: Ejecución con exec() + CLI Worker
- ADR-002: Tablas por Schema Multi-Tenant
- ADR-003: Polling → SSE Progresivo
- ADR-004: Wrapper Pattern (NO Refactoring)
- ADR-005: Schema Isolation en Background (CRÍTICO)
- ADR-006: CLI Two-Phase Bootstrap
- ADR-007: Tab-Scoped Job Bus via
window.BautistaJobBus
🔧 Implementación Técnica
backend/ (9 archivos, 3,325 líneas)
- Arquitectura de componentes (Value Objects, Services, Handlers, Controllers)
- Base de datos (tablas, índices, constraints)
- API endpoints (POST /jobs, GET /jobs/{id}, SSE)
- Handlers (implementación de nuevos jobs)
- Multi-tenant (CRÍTICO) - Schema isolation
- Testing (Unit + Integration)
- Troubleshooting
- Referencia de código
Tecnologías
Stack:
- PHP 8.2+ con exec() para lanzar workers CLI
- PostgreSQL (storage + NOTIFY para real-time)
- Server-Sent Events (SSE) para notificaciones
- React/TypeScript frontend
Dependencias: CERO externas (solo PHP + PostgreSQL)
Fases de Implementacion
Fase 1: MVP con Polling — COMPLETADA
- Ejecucion asincrona con
exec()+ CLI worker - Tabla
background_jobs+background_notifications - HTTP polling cada 2 segundos via
useBackgroundJob(TanStack Query) JobHandlerRegistrycon auto-descubrimiento via PHP-DI (arrayjob.handlers)- Todos los jobs llevan
nro_sistemaypruebapara aislamiento multi-tenant - Handlers implementados:
BatchInvoicingJobHandler, entre otros
Fase 2: SSE Real-Time — BACKEND COMPLETO / FRONTEND PENDIENTE
- PostgreSQL NOTIFY/LISTEN: trigger
notify_job_update()implementado JobStreamController: endpointGET /backend/jobs/{id}/streamfuncional en backend- Frontend SSE bloqueado:
EventSourceno puede enviar headers auth cross-domain (ver ADR-003 ENMIENDA) - Hook
useJobStreamretornaisConnected: false,usingSseFallback: true(constantes) y delega a polling - Para desbloquear: resolver cross-domain cookie strategy o proxy en
app.com
Fase 3: Production Hardening — COMPLETADA
- Retry con exponential backoff
- Monitoring:
GET /backend/jobs/healthyGET /backend/jobs/metrics(formato Prometheus), protegidos conMETRICS_SECRET AdminJobController: endpoints/backend/jobs/admin/*para operaciones administrativas- Supervisor para gestion de workers (config en
supervisor/bautista-worker.conf.dist) - Cleanup automatico de jobs antiguos
Fase 4: Escalar con RabbitMQ (Futuro)
- Cuando volumen > 500 jobs/dia
- Worker pool distribuido
- Priority queues
- Dead letter queue
Navegación Rápida
| Tema | Archivo |
|---|---|
| ¿Por qué esta solución? | architecture.md |
| ¿Cómo implementar? | backend/README.md |
| ¿Qué tareas se hicieron? | Kanban archivado — implementación completada 2026-02-24 |
| ¿Qué decidimos? | adrs/README.md |
| ¿Cómo testear multi-tenant? | backend/05-multi-tenant.md |
| ¿Problemas comunes? | backend/07-troubleshooting.md |
| ¿Cómo funciona la campana y los Tiers? | frontend-notification-dispatch-process.md |
Métricas
Total documentación: 5,237 líneas
- Arquitectura: 649 líneas
- ADRs: 39.7 KB (5 decisiones)
- Backend: 3,325 líneas (9 archivos)
- Kanban: 37 tarjetas implementadas (archivado 2026-02-24)
Complejidad: Media Time to Market: 4-5 semanas Costo Infraestructura: $0/mes
Siguientes Pasos
Documentacion completa-- COMPLETADORevision y aprobacion de arquitectura-- COMPLETADOFase 1: MVP con Polling-- COMPLETADOFase 2: Backend SSE-- COMPLETADOFase 3: Production Hardening-- COMPLETADO- Pendiente: Desbloquear SSE en frontend (requiere resolver auth cross-domain)
- Futuro: Fase 4 (RabbitMQ) cuando volumen lo justifique
Ultima actualizacion: 2026-02-26