Appearance
Referencia de Código
◄ Anterior: Troubleshooting | Índice
Tabla de Contenidos
Archivos Clave
Value Objects
Core/ValueObjects/BackgroundJob.phpCore/ValueObjects/Notification.phpCore/ValueObjects/RetryResult.php
Interfaces
Core/Interfaces/JobHandlerInterface.php
Repositorios
Core/Repositories/JobRepository.phpCore/Repositories/NotificationRepository.php
Servicios
Core/Services/JobDispatcher.phpCore/Services/JobExecutor.phpCore/Services/JobHandlerRegistry.phpCore/Services/NotificationService.phpCore/Services/RetryStrategy.phpCore/Services/AlertService.phpCore/Services/HealthChecker.phpCore/Services/JobRetryService.phpCore/Services/AdminPermissionChecker.php
Controllers
Core/Controllers/JobController.phpCore/Controllers/JobStreamController.phpCore/Controllers/AdminJobController.phpCore/Controllers/MonitoringController.php
Handlers (Ejemplos)
Ventas/Handlers/BatchInvoicingJobHandler.php
Routes
Routes/Jobs/JobRoutes.phpRoutes/Jobs/AdminJobRoutes.php
Middleware
Middleware/MetricsAuthMiddleware.php
Validators
Validators/Jobs/JobDispatchValidator.php
CLI
cli/background-worker.phpcli/bootstrap-cli.phpbin/(scripts de mantenimiento)
Supervisor
supervisor/bautista-worker.conf.dist
Migraciones
migrations/migrations/system/(3 archivos de migración)
Inyección de Dependencias
container/shared-definitions.php- Definiciones compartidas (JobExecutor, repositorios, etc.)index.php- JobDispatcher registrado solo en contexto web
Tests
Tests/Unit/Core/JobDispatcherTest.phpTests/Unit/Core/JobExecutorTest.phpTests/Unit/Core/JobRepositoryTest.phpTests/Integration/Core/BackgroundJobsFlowTest.php
Convenciones
Estados de Job
| Estado | Descripción | Transiciones Permitidas |
|---|---|---|
pending | Job creado o pendiente de reintento | → running |
running | Job ejecutándose | → completed, pending (retry), failed |
completed | Job terminó exitosamente | (final) |
failed | Job falló y agotó reintentos | (final) |
Reglas:
- ✅ pending → running: Cuando worker inicia
- ✅ running → completed: Cuando handler retorna sin exception
- ✅ running → pending: Cuando handler lanza exception y
retry_count < max_retries(self-dispatch retry) - ✅ running → failed: Cuando handler lanza exception y
retry_count >= max_retries - ❌ completed → running: NUNCA (job no se re-ejecuta)
- ❌ failed → pending: NUNCA (reintentos agotados; retry manual = crear nuevo job via admin endpoint)
Tipos de Notificación
| Tipo | Uso | Color UI |
|---|---|---|
success | Job completado exitosamente | Verde |
error | Job falló | Rojo |
info | Información general (ej: job iniciado) | Azul |
Convenciones de mensaje:
- success: "Operación completada: {resumen del resultado}"
- error: "Operación falló: {mensaje de error}"
- info: "Operación iniciada: {descripción del job}"
Nomenclatura de Handlers
Patrón: {Module}{Operation}JobHandler
Ejemplos:
BatchInvoicingJobHandler- Facturación masivaReportGenerationJobHandler- Generación de reportesDataImportJobHandler- Importación de datosExternalSyncJobHandler- Sincronización externa
Tipos de job (snake_case):
batch_invoicingreport_generationdata_importexternal_sync
Logging
Formato structured logging:
php
$logger->info('Job dispatched', [
'job_id' => $jobId,
'job_type' => $type,
'user_id' => $userId,
'schema' => $schema,
]);
$logger->info('Job started', [
'job_id' => $jobId,
'job_type' => $job->type,
]);
$logger->info('Job completed', [
'job_id' => $jobId,
'job_type' => $job->type,
'execution_time_seconds' => $job->getExecutionTime(),
]);
$logger->error('Job failed', [
'job_id' => $jobId,
'job_type' => $job->type,
'error' => $job->error,
]);Archivo de log: /logs/background-jobs.log
Log rotation:
bash
# /etc/logrotate.d/background-jobs
/var/log/background-jobs.log {
daily
missingok
rotate 30
compress
delaycompress
notifempty
}Patterns Utilizados
Strategy Pattern
Uso: JobHandlerInterface
Permite agregar nuevos tipos de jobs sin modificar JobExecutor. Cada handler implementa la interface y se registra en el executor.
Beneficio: Open/Closed Principle - abierto a extensión, cerrado a modificación.
Repository Pattern
Uso: JobRepository, NotificationRepository
Abstrae el acceso a datos. Los servicios NO conocen detalles de SQL, solo operan con entidades.
Beneficio: Separación de concerns, fácil testing con mocks.
Value Objects
Uso: BackgroundJob, Notification
Entidades inmutables que representan conceptos de dominio con validación incorporada.
Beneficio: Type safety, domain model claro.
Wrapper Pattern
Uso: Handlers envuelven services existentes
Handler NO modifica service. Reconstruye DTOs y delega al service sin cambios.
Beneficio: CERO impacto en código legacy, rollback instantáneo con feature flag.
Referencias Externas
ADRs Relacionados
- ADR: Background Jobs Architecture - Decisiones arquitecturales
Documentación de Arquitectura
- Architecture: Background Jobs - Conceptos y opciones evaluadas
- Architecture: Multi-Tenant - Schema-based tenancy
- Backend: 5-Layer Architecture - Arquitectura general
Documentación Externa
- Server-Sent Events (SSE) Spec
- PostgreSQL NOTIFY/LISTEN
- PHP exec() Documentation
- RabbitMQ PHP Tutorial (para Fase 4)
Comandos Útiles
Ejecutar Worker Manualmente
bash
php cli/background-worker.php {job_id}Cleanup Jobs Antiguos
bash
php cli/cleanup-old-jobs.phpCleanup Jobs Stale
bash
php cli/cleanup-stale-jobs.phpVerificar Jobs Pendientes
sql
SELECT COUNT(*) FROM background_jobs WHERE status = 'pending';Verificar Jobs Running
sql
SELECT * FROM background_jobs WHERE status = 'running';Verificar Notificaciones No Leídas
sql
SELECT COUNT(*) FROM notifications WHERE is_read = FALSE;Feature Flags
Ubicación: container/shared-definitions.php (variables de entorno en .env)
php
return [
'background_jobs' => [
'enabled' => getenv('FEATURE_BACKGROUND_JOBS') === 'true',
'max_pending_per_user' => (int) (getenv('MAX_PENDING_JOBS') ?: 10),
],
];Variables de entorno:
FEATURE_BACKGROUND_JOBS: Activar/desactivar sistema (default: false)MAX_PENDING_JOBS: Límite de jobs pendientes por usuario (default: 10)
Última Actualización: 2026-02-05 Versión: 1.0 (Fase 1 - MVP con Polling)