Cómo Nebula ejecuta los procesos pesados en segundo plano como tareas: el servicio dueño las crea y las ejecuta, nebula-commons les da la infraestructura asíncrona común (estado, Kafka, MinIO, tenant y token de ejecución), nebula-tasks las proyecta, recibe las órdenes y lleva el control central, y el usuario las sigue y las gobierna desde la opción transversal «Centro de Tareas».
Versión: 1.0 · Fecha: 28 de octubre de 2026 · Arquitecto: Carlos Alberto Torres Camargo
Estado: IMPLEMENTADO en develop. Este documento describe lo construido; la especificación completa es la HT de origen.
HT de origen: HT_ARQ_013_TareasImportacionExportacion (architecture/sprint-11/htu/, AUDIT_REPORT.json con verdict: PASS). Nace de las decisiones del arquitecto del 7-oct-2026, sin HU de entregable.
Cómo leer este documento. Cada afirmación sobre lo construido cita su archivo (sección 13). Lo que es inferencia o riesgo observado va marcado así. Las reglas de negocio de detalle (RN-TAR-) y los casos (TC-) están en la HT y no se repiten aquí.
Palabras del arquitecto, 7-oct-2026 (citadas en el README de la HT): «establecer que los procesos desde el backend creen tareas asincrónicas … debe tener un api crud de tareas donde se van registrando las tareas y cada tarea tendrá un log de ejecución y luego cada usuario puede acceder a esa opción en el front y ver el estado de una tarea».
Problema que resuelve (HT §2): un archivo grande procesado dentro de la petición muere con el contenedor en cada despliegue, y la importación y exportación hacían un solo paso.
Tomados del README de la HT (§4), decisiones del 7-oct-2026:
| # |
Decisión |
| D-22 |
Todo el proceso vive en el esquema TASKS: lo escribe el proceso del servicio dueño por nebula-commons; nebula-tasks proyecta, registra las órdenes y lleva el control central. |
| D-24, D-25 |
Una tarea se crea, se pausa, se reanuda, se cancela y se reintenta; cada evento se registra antes de publicarse y cada orden con su resultado. |
| — |
Kafka con acuse total, idempotencia y cola de descarte; partición por id de tarea. |
| — |
Umbral en línea de 500 filas: por debajo, en la petición; por encima, tarea. |
| — |
La credencial de servicio es el token de ejecución; el evento lleva una SesionEjecucion sin token ni identificador de sesión. |
| — |
tarea_logs en Mongo con TTL de 180 días (patrón nuevo autorizado); usuario en claro, jamás el token; tope de líneas por tarea. |
| — |
El kit no hace HTTP: define el contrato del origen; el ERP registra el origen por defecto. |
| — |
La infraestructura asíncrona común va a nebula-commons. |
| — |
«Centro de Tareas» es transversal, en libs/layout. |
| — |
Reanudación exacta: guarda por fila en la misma transacción y avance por lote; una tarea FALLIDA se reintenta desde donde quedó. |
flowchart LR
subgraph FRONT["nebula-erp"]
CT["Centro de Tareas<br/>libs/layout/.../centro-tareas"]
BAN["Bandeja del encabezado<br/>bandeja-tareas · sondeo 10 s"]
TS["TareasService<br/>libs/data-access/src/tareas"]
KIT["Diálogos importar / exportar<br/>nebula-ui-kit import-export"]
end
subgraph DUENO["Servicio dueño (p. ej. nebula-budget-core)"]
PROC["Proceso con tarea<br/>AbstractImportProcessConTarea · ProcesoConTarea"]
LANZ["TareaProcesoLanzador / dispatchers"]
TRAB["TareaEjecucionConsumer<br/>(trabajador)"]
CMD["TareaComandoConsumer<br/>(órdenes)"]
end
subgraph COMMONS["nebula-commons · tareas/*"]
EST["estado/ · persistencia/<br/>registro y outbox en TASKS"]
TEN["tenant/ · sesion/<br/>apertura del tenant y token de ejecución"]
ALM["almacen/ · MinIO"]
end
subgraph TASKS["nebula-tasks"]
TC["TareaController<br/>/api/v1/tareas"]
CC["ControlTareaController<br/>/api/v1/tareas/control"]
EVC["TareaEventConsumer<br/>proyección"]
RELE["ReleTareasScheduler<br/>+ ReconciliacionTareasComponent"]
end
ORA[("Oracle · esquema TASKS")]
MONGO[("Mongo · tarea_logs<br/>TTL 180 días")]
MINIO[("MinIO · nebula-tareas")]
K{{"Kafka<br/>tareas-ejecucion-<servicio><br/>tareas-eventos · tareas-comandos"}}
KIT --> DUENO
CT --> TS --> TC
BAN --> TS
PROC --> EST --> ORA
PROC --> ALM --> MINIO
LANZ --> K --> TRAB --> PROC
EST -- outbox --> K
K -- tareas-eventos --> EVC --> ORA
EVC --> MONGO
TC -- órdenes --> K -- tareas-comandos --> CMD
TC --> ORA
TC -- resultado --> MINIO
RELE --> ORA
RELE --> K
CC --> RELE
TRAB --> TEN
sequenceDiagram
participant U as Usuario
participant K as Diálogo del kit
participant D as Servicio dueño
participant C as nebula-commons
participant O as Oracle TASKS
participant M as MinIO
participant Q as Kafka
participant W as Trabajador del dueño
participant T as nebula-tasks
participant CT as Centro de Tareas
U->>K: Importar archivo
K->>D: POST import
D->>C: contar filas (sin parsear, con tope)
alt menos de 500 filas
C-->>K: respuesta en línea
else 500 o más
C->>M: archivo de origen
C->>O: tarea PENDIENTE + evento (misma transacción)
C->>Q: tareas-ejecucion-<servicio> (SesionEjecucion, sin token)
C-->>K: tarea creada
Q->>W: ejecución
W->>C: abrir tenant + token de ejecución
loop por lote
W->>O: filas y avance del lote
W->>Q: tareas-eventos (outbox, en orden)
end
W->>M: archivo de resultado
Q->>T: eventos
T->>O: proyección en tasks.tareas
U->>CT: ver, descargar resultado
end
sequenceDiagram
participant U as Usuario
participant CT as Centro de Tareas
participant T as nebula-tasks
participant O as Oracle TASKS
participant Q as Kafka
participant D as Dueño (TareaComandoConsumer)
U->>CT: Pausar / Reanudar / Cancelar / Reintentar
CT->>T: POST /api/v1/tareas/{orden}?id=
T->>O: registra la orden (tareas_comandos)
T->>Q: tareas-comandos
Q->>D: orden
D->>O: aplica y registra el evento
D->>Q: tareas-eventos
Q->>T: proyección del nuevo estado
CT->>T: relee (sondeo de en-curso)
Estados de EstadoTareaEnum: PENDIENTE, EN_PROCESO, PAUSADA, COMPLETADA, COMPLETADA_CON_ERRORES, FALLIDA, CANCELADA. Las transiciones del diagrama son las órdenes y cierres que describe la HT (inferencia del diagrama: el detalle exacto de cada transición está en 03_Rules §C y §E).
stateDiagram-v2
[*] --> PENDIENTE: lanzada
PENDIENTE --> EN_PROCESO: el trabajador la toma
EN_PROCESO --> PAUSADA: pausar
PAUSADA --> EN_PROCESO: reanudar
EN_PROCESO --> COMPLETADA
EN_PROCESO --> COMPLETADA_CON_ERRORES
EN_PROCESO --> FALLIDA
FALLIDA --> PENDIENTE: reintentar (desde donde quedó)
PENDIENTE --> CANCELADA: cancelar
EN_PROCESO --> CANCELADA: cancelar
PAUSADA --> CANCELADA: cancelar
COMPLETADA --> [*]
COMPLETADA_CON_ERRORES --> [*]
CANCELADA --> [*]
| Subpaquete |
Clases |
Qué hace |
| raíz |
TareasAutoConfiguration, TareasProperties, TareasMensajes, AbstractImportProcessConTarea |
Autoconfiguración (nebula.tareas.enabled), propiedades y proceso base de importación con tarea |
proceso/ |
ProcesoConTarea, ProcesoJobDescriptor, ResultadoProceso, TareaProcesoLanzador |
Tareas de tipo PROCESO, sin archivo; el proceso debe ser idempotente |
importacion/, exportacion/ |
KafkaTareaImportDispatcher, TareaImportJobStore, KafkaTareaExportDispatcher, TareaExportJobStore, ProgresoTareaExportReporter, SesionTenantExportSupplier |
Implementan los contratos asíncronos de importar y exportar de SimappeCommons |
estado/, persistencia/ |
TareaEstado, TareaEventos, TareaPersistencia, EventoPendiente, TareaPersistenciaTasks, TenantTarea… |
Registro de la tarea, sus lotes, filas y eventos en TASKS (outbox) |
consumidor/ |
TareaEjecucionConsumer, TareaComandoConsumer |
Trabajador de ejecución y receptor de órdenes en el servicio dueño |
tenant/, sesion/ |
AperturaTenantComponent, TokenEjecucionComponent, JwtRequestWrapper, SesionEjecucionMapper, SesionVigente |
Abren el tenant fuera de una petición con el token de ejecución |
almacen/ |
MinioTareaSourceStore, MinioTareaResultStore, TareasMinio |
Archivo de origen y de resultado en MinIO |
kafka/ |
TareasKafkaConfig |
Tópicos y contenedores |
control/ |
AvisoControlTareasCliente, NombreUsuarioNebula |
Aviso al control central |
Propiedades (TareasProperties, valores por defecto en código): umbralInline = 500, conteoMaxMs = 2000, bucket = "nebula-tareas"; Kafka: reintentos = 4, backoffInicialMs = 2000, backoffMultiplicador = 2.0, backoffMaximoMs = 30000, concurrencia = 2, deliveryTimeoutMs = 120000, particiones = 6, maxProcesamientoMs (6 h desde el MR !23, commit dd860ca, 08-oct-2026).
Tópicos (TareasKafkaConfig): tareas-ejecucion-<servicio> y su descarte, tareas-eventos, tareas-comandos.
| Clase |
Qué hace |
TareaController (/api/v1/tareas) |
Listado y consulta de la tarea, contador de en curso, órdenes y descarga del resultado |
ControlTareaController (/api/v1/tareas/control) |
Reconciliar y salud |
TareaEventConsumer |
Escucha tareas-eventos y proyecta cada evento dentro del tenant de su SesionEjecucion; un fallo agota los reintentos y va a descarte |
ReleTareasScheduler |
Cada nebula.tareas.control.intervalo-ms (30 000 por defecto) invoca el control central para todos los servicios |
ReconciliacionTareasComponent |
Publica en orden los eventos que nadie publicó y redespacha las tareas PENDIENTE varadas; la toma es condicional, un redespacho no corre dos veces. Umbrales: evento 60 s, varada 300 s, en proceso 1800 s, límite 200 |
TareasConfig |
nebula-tasks no es dueño de tareas ajenas: no activa nebula.tareas.enabled y arma solo productor de comandos, consumidor de eventos y apertura de tenant |
PortalTareasConfig |
nebula-tasks como dueño de sus propios procesos (Portal de Scripts): cada cambio aprobado corre como tarea PROCESO |
TareaLogIndexConfig, TareaLogDocument |
Índices de tarea_logs: compuesto por tenant y tarea, y expiración a los 180 días |
| Dónde |
Objetos |
Oracle, esquema TASKS |
tareas, tareas_estado, tareas_lotes, tareas_filas, tareas_eventos, tareas_comandos (scripts oracle/tasks/ddl 001 a 011 y vista 010) |
| Mongo |
Colección tarea_logs, TTL 180 días |
| MinIO |
Bucket nebula-tareas; resultado en nebula-tareas/<cliente>/<compania>/<tareaId>/resultado.<ext> |
| Pieza |
Dónde |
| Centro de Tareas |
nebula-erp/libs/layout/src/lib/feature-layout/src/lib/centro-tareas/ (centro-tareas.component, centro-tareas.layout, navegador-centro-tareas, tarea-a-item) |
| Bandeja del encabezado |
bandeja-tareas.component.ts: consulta /en-curso cada SONDEO_MS = 10_000 y relee la lista solo cuando algo corre |
| Servicio |
libs/data-access/src/tareas/tareas.service.ts, base /nebula-tasks/api/v1/tareas |
| Pestañas (orden) |
En ejecución (PENDIENTE, EN_PROCESO, PAUSADA), Terminadas (COMPLETADA, COMPLETADA_CON_ERRORES), Fallidas (FALLIDA), Canceladas (CANCELADA) — ESTADOS_POR_PESTANA_TAREAS en libs/domain |
| Detalle |
Panel con el registro de ejecución y, de get-record, lotes, traza y órdenes |
| Diálogos genéricos |
nebula-ui-kit/.../components/import-export/ (import-dialog, export-dialog) |
| Menú e i18n |
simappe-admin/menu/V2026_10_001, i18n/tasks/V2026_10_001 y 019, i18n/front/V2026_10_054 |
| Operación |
Ruta |
Respuesta |
| Disponibilidad |
GET /api/v1/tareas + PATH_INDEX |
ServiceResponseAvailable |
| Listado |
POST /api/v1/tareas/page-response |
PageResponse<TareaResponse> |
| Consulta |
GET /api/v1/tareas/get-record?id= |
TareaResponse |
| Contador del encabezado |
GET /api/v1/tareas/en-curso |
TareasEnCursoResponse |
| Pausar, reanudar, cancelar, reintentar |
POST /api/v1/tareas/{pausar\|reanudar\|cancelar\|reintentar}?id= |
TareaResponse |
| Descargar resultado |
GET /api/v1/tareas/resultado?id= |
Archivo |
| Reconciliar |
POST /api/v1/tareas/control/reconciliar |
ReconciliacionTareasResponse |
| Salud |
GET /api/v1/tareas/control/salud?servicio= |
SaludTareasResponse |
Cada usuario ve solo sus tareas, en su tenant (HT, ítem 30).
Clases que usan la librería de tareas fuera de nebula-commons (búsqueda en el árbol local, 28-oct-2026):
| Servicio |
Procesos |
nebula-budget-core |
RubroImportProcess (carga masiva de HT_PRE_007), ProcesoCierrePresupuestal, CierrePresupuestalComponent, CierreReversionComponent |
nebula-invoicing |
ProcesoCierreFacturacion, CierreFacturacionComponent |
nebula-tasks |
ProcesoCambioScript (Portal de Scripts) |
- El servicio activa
nebula.tareas.enabled y depende de nebula-commons ≥ la versión con tareas.
- Importación: el proceso extiende
AbstractImportProcessConTarea; el umbral decide en línea o tarea.
- Exportación: la capa de export de SimappeCommons en modo asíncrono, implementada por
KafkaTareaExportDispatcher y TareaExportJobStore.
- Proceso sin archivo: implementa
ProcesoConTarea (idempotente) y se lanza con TareaProcesoLanzador.
- Claves i18n del nombre del proceso (precedente
i18n/tasks/V2026_10_019).
| Con |
Relación |
| SimappeCommons |
Publica los contratos asíncronos de importar y exportar; nebula-commons los implementa. No se modifica (R-C01). |
HT_ARQ_003 (motor de causación) |
Precedente de apertura de tenant y token de ejecución. |
HT_PRE_007 |
Primer consumidor; sale junto con HT_ARQ_013. |
DISENO_TECNICO_API_REPORTES_POR_PRODUCTO.md |
Los reportes pesados irán por este Centro (propuesta, decisión D-04 de ese documento). |
DISENO_TECNICO_NEBULINA_IA.md |
Comparte el servicio nebula-tasks y el esquema TASKS; no usa tareas. |
PATRON_CANONICO_IMPORTACION_ARCHIVOS.md |
El endpoint /import canónico que decide en línea o tarea. |
- Tenant: la tarea guarda su sesión y parámetros; el trabajador y la proyección abren el tenant de la
SesionEjecucion, nunca del mensaje libre.
- Sin token en tránsito: el evento no lleva token ni id de sesión; el trabajador usa el token de ejecución.
- Orden y no pérdida: outbox en
TASKS, publicación en orden y reconciliación; partición por id de tarea.
- Idempotencia: la proyección aplica cada evento por su secuencia; el redespacho toma la tarea de forma condicional.
- Reanudación: guarda por fila en la misma transacción; un reintento sigue desde donde quedó.
- Log separado del estado, con expiración.
- Consumo del front: listados por
page-response y consulta por get-record.
- Kafka, Mongo, MinIO y Oracle arriba en el ambiente (DEV y QA según la HT §2).
- El servicio dueño publica su tópico de ejecución al arrancar (
TareasKafkaConfig, KafkaAdmin.NewTopics).
- La opción de menú y el i18n cargados en el ambiente.
| # |
Riesgo |
Evidencia o naturaleza |
Mitigación existente o pendiente |
| R-01 |
Tareas largas reentregadas por Kafka |
Fallaba a los 5 min por defecto |
Corregido: 6 h configurable (MR !23, dd860ca) |
| R-02 |
Un servicio cae entre confirmar y publicar |
Diseño (HT §D) |
Relé cada 30 s y /control/reconciliar |
| R-03 |
Sondeo de la bandeja cada 10 s por usuario conectado |
SONDEO_MS = 10_000 |
Solo relee la lista cuando algo corre; carga en /en-curso (inferencia: crece con los usuarios conectados) |
| R-04 |
Pausar depende de que el proceso lo admita |
La HT §5 lo excluía al inicio; luego entró (ítem 44) |
Verificar por proceso que respete la pausa (inferencia) |
| R-05 |
Migración de pantallas al diálogo nuevo |
HT §5: 6 de importar y 14 de exportar fuera del flujo |
Cada pantalla migra cuando se toque |
| R-06 |
Solicitudes a la línea Simappe (S-1 filas válidas, S-2 tenant y avance de importación) |
HT ítems 41 y 42, ⚠️ |
Mientras tanto lo resuelve nebula-commons |
| Componente |
Repo |
Estado |
Infraestructura asíncrona tareas/* |
nebula-commons |
En develop |
Records, DTO, enums (EstadoTareaEnum, TipoTareaEnum) y eventos |
nebula-models |
En develop |
| Proyección, órdenes, control central |
nebula-tasks |
En develop |
Esquema TASKS |
nebula-erp-scripts-db-i18n/oracle/tasks |
DDL 001 a 011, vista 010 |
| Centro de Tareas y bandeja |
nebula-erp libs/layout, libs/data-access, libs/domain |
En develop |
| Diálogos importar y exportar |
nebula-ui-kit |
En main |
| Menú e i18n |
simappe_admin |
Scripts del repo de scripts |
| Afirmación |
Fuente |
| Decisiones, piezas, alcance y matriz |
architecture/sprint-11/htu/HT_ARQ_013_TareasImportacionExportacion/README.md (§1 a §6); AUDIT_REPORT.json verdict: PASS |
Paquete tareas y sus clases |
git ls-tree origin/develop de nebula-commons, src/main/java/.../commons/tareas/ |
| Propiedades por defecto |
nebula-commons/.../tareas/TareasProperties.java (líneas 34 a 76, origin/develop) |
| Tópicos |
nebula-commons/.../tareas/kafka/TareasKafkaConfig.java (líneas 64, 67, 70) |
| Estados |
nebula-models/.../tasks/tarea/enums/EstadoTareaEnum.java (origin/develop) |
| Endpoints |
nebula-tasks/.../v1/tarea/controller/TareaController.java (57 a 196) y ControlTareaController.java (48 a 84) |
| Relé y reconciliación |
ReleTareasScheduler.java:41, ReconciliacionTareasComponent.java:85-101 |
| Proyección |
TareaEventConsumer.java:48 |
| Índices y TTL |
config/TareaLogIndexConfig.java |
| Versión del servicio |
nebula-tasks/pom.xml en origin/develop: 1.8.2-SNAPSHOT |
| Tablas |
nebula-erp-scripts-db-i18n/oracle/tasks/ddl/V2026_10_002 a 011 |
| Front |
nebula-erp origin/develop: libs/layout/.../centro-tareas/, libs/data-access/src/tareas/tareas.service.ts:18, libs/domain/.../tarea/tarea.model.ts:131-136, bandeja-tareas.component.ts:28 |
| Diálogos del kit |
nebula-ui-kit origin/main: projects/nebula-ui-kit/src/lib/components/import-export/ |
| Reentrega de Kafka |
nebula-commons commit dd860ca, MR !23 (08-oct-2026) |
| Versión |
Fecha |
Autor |
Descripción |
| 1.0 |
2026-10-28 |
Carlos Torres |
Documento de arquitectura de lo construido, a partir de HT_ARQ_013 y el código en develop. |