Skip to main content

High Level Design: Alpura Batch Sync Tickets

1. Resumen Ejecutivo

Propósito del Microservicio

El servicio alpura-java-back-batch-sync-tickets es un componente de procesamiento por lotes (Batch) diseñado para sincronizar reportes de nómina y tickets desde el sistema Oracle BI (HCM) hacia la base de datos operativa de Alpura (Sienpro).

Funcionalidad Principal

  • Escucha activa de eventos de solicitud de sincronización.
  • Conexión segura y recuperación de reportes XML desde Oracle BI via SOAP.
  • Procesamiento, validación y transformación de grandes volúmenes de registros de nómina.
  • Persistencia transaccional de los detalles de tickets.
  • Notificación asíncrona de finalización del proceso.

Consumidores

  • Sistemas Internos: Otros microservicios o sistemas legacy que requieren la información actualizada de tickets de nómina.
  • Trigger: Orquestadores de procesos o servicios upstream que publican el evento de solicitud en Google Cloud Pub/Sub.

Rol en la Arquitectura

Actúa como un Data Ingestion Worker dentro del dominio de Nómina/Recursos Humanos, sirviendo como puente entre el ERP corporativo (Oracle HCM) y los sistemas operativos locales.


2. Contexto Arquitectónico

El microservicio reside en un ecosistema de nube híbrida, desplegado probablemente en contenedores, e interactúa con los siguientes componentes:

  • Trigger (Entrada): Google Cloud Pub/Sub. Suscripción a un tópico específico para recibir comandos de inicio (ALLOC_PROD_SYNC_REQUESTED).
  • Fuente de Datos (Origen): Oracle BI Publisher (Nube u On-Premise) expuesto vía SOAP Web Services.
  • Persistencia (Destino): Base de datos relacional (PostgreSQL o H2 en local) gestionada via JPA.
  • Salida (Eventos): Google Cloud Pub/Sub. Publicación de eventos de finalización (EMP_ALLOC_UPDATE_REQUESTED).
  • Configuración: Spring Cloud Config Server para la gestión centralizada de propiedades.

Responsabilidades

  • Garantizar la integridad de los datos importados.
  • Manejar la idempotencia de las ejecuciones (evitar re-procesamientos de jobs ya completados).
  • Transformar el formato XML de Oracle a entidades relacionales normalizadas.

3. Arquitectura de Alto Nivel (HLD)

El servicio sigue una arquitectura Layered (Capas) montada sobre Spring Batch, lo que proporciona robustez para manejos de volúmenes de datos.

Diagrama de Arquitectura

Componentes Principales

  1. PubSubMessageReceiver: Listener de entrada que filtra mensajes y lanza el Job. Implementa lógica de idempotencia consultando el JobRepository personalizado.
  2. ReportSyncJob: El job principal definido en BatchJobConfig.
    • FetchReportTasklet: Tarea encargada de descargar el XML de Oracle, calcular hash MD5 para control de cambios, y parsear la respuesta.
    • SaveDetailsStep: Paso transaccional (Chunk size: 500) que lee los datos parseados, los transforma y los inserta en BD.
  3. ReportDetailProcessor: Transforma el VO (HcmReportDetailVO) en la entidad JPA (TicketsReportDetailDO).
  4. Repositorios: Interfaces JPA para acceso a datos (IHcmReportHeaderRepository, IJobRepository, etc.).

4. Contrato de API y Endpoints

Este microservicio NO expone una API REST transaccional tradicional para uso de clientes directos. Su interfaz pública es asíncrona basada en eventos.

Interfaz de Entrada (Async)

  • Origen: GCP Pub/Sub Subscription.
  • Mensaje Esperado:
    • EventType: ALLOC_PROD_SYNC_REQUESTED
    • Atributos: jobId, payrollId.
  • Comportamiento:
    • Si EventType coincide: Inicia el proceso.
    • Si JobId ya existe y está COMPLETED/IN_PROGRESS: Ignora y confirma (ACK) para idempotencia.
    • Si falla el lanzamiento: Envía NACK para reintento.

Interfaz de Salida (Async)

  • Destino: GCP Pub/Sub Topic.
  • Evento: EMP_ALLOC_UPDATE_REQUESTED
  • Condición: Se envía solo si el Job finaliza con estado COMPLETED.

Endpoints Operativos (Actuator)

Detectados por dependencia spring-boot-starter-actuator:

  • GET /actuator/health: Estado de salud.
  • GET /actuator/info: Información del servicio.
  • GET /actuator/metrics: Métricas de JVM y Spring Batch.

5. Flujos Funcionales

Flujo Principal: Sincronización de Reporte

  1. Recepción: Llega mensaje Pub/Sub.
  2. Validación: Se verifica que no sea un duplicado (Idempotencia).
  3. Ejecución: Se lanza reportSyncJob.
  4. Paso 1 (Fetch & Parse):
    • Obtener fechas del periodo de nómina (SienproPayrollTimePeriodsRepository).
    • Invocar servicio SOAP Oracle (OracleReportTicketsUtil).
    • Calcular MD5 del XML.
    • Guardar Header de reporte (TicketsReportHeaderDO).
    • Parsear XML a lista de objetos en memoria (HcmReportDetailVO).
  5. Paso 2 (Process & Write):
    • Leer objetos de memoria.
    • Procesar/Mapear a Entidad.
    • Escribir en Base de Datos en lotes de 500.
  6. Finalización:
    • Actualizar estado del Job a COMPLETED.
    • Publicar evento de éxito.

6. Casos de Uso

Caso de UsoActorDescripciónPrecondicionesResultado
Sincronizar Tickets Manual/AutomáticoSistema Externo (Pub/Sub)Inicia la descarga y procesamiento del reporte de tickets.Mensaje en tópico con payrollId válido.Datos insertados en BD y evento de éxito emitido.
Recuperación de FallosPub/Sub (Retry)Si el proceso falla, el mensaje no se confirma (NACK) y se reintenta.Error transitorio en BD o Red.Reintento automático de ejecución.
Prevención de DuplicadosSistemaEvita procesar el mismo jobId dos veces.Registro de Job existente en BD.Mensaje descartado (Ack) sin procesamiento.

7. Integraciones Técnicas

1. Oracle BI Publisher (SOAP)

  • WSDL: src/main/wsdl/ReportService.wsdl
  • URL Base: Hardcoded en FetchReportTasklet.java con referencia a https://ejfg-dev1.fa.us6.oraclecloud.com/....
  • Autenticación: Basic Auth (Usuario/Password en código - Deuda Técnica).
  • Método: runReport.
  • Formato: XML embebido en respuesta SOAP.

2. Google Cloud Pub/Sub

  • Librería: spring-cloud-gcp-starter-pubsub.
  • Configuración: gcp.project-id, gcp.topic-name, gcp.subscription-name.
  • Serialización: Atributos en Map y Payload en bytes.

3. Base de Datos

  • Motor: PostgreSQL (driver en pom.xml), H2 para local.
  • Framework: Spring Data JPA + Hibernate.
  • Pool: HikariCP (Configurado en properties).

8. Seguridad

  • Credenciales:
    • GCP: Uso de Application Default Credentials (implícito en librerías Spring Cloud GCP).
    • Base de Datos: Inyectadas via propiedades (idealmente desde Config Server/Secrets).
    • SOAP Oracle: CRÍTICO. Credenciales hardcodeadas en FetchReportTasklet.java. Se recomienda mover a Vault o Variables de Entorno.
  • Red: Comunicación HTTPS hacia Oracle y GCP. JDBC hacia la BD.

9. Observabilidad y Operación

  • Logging: Slf4j + Logback implícito. Logs informativos en inicio/fin de Jobs y recepción de mensajes.
  • Traceabilidad: JobId se usa como identificador de correlación a lo largo del proceso.
  • Estado del Job: Persistido en tablas personalizadas JobDO, JobStep y TicketsReportHeaderDO. Esto permite monitoreo funcional via consultas SQL.
  • Métricas: Exposición de métricas estándar de Spring Batch via Actuator (Prometheus registry incluido en dependencias).

10. Modelo de Datos

Modelo relacional

Nota: Las tablas de JOB podrían ser tablas custom de Alpura que extienden o reemplazan las tablas estándar de metadatos de Spring Batch.

Diccionario de Datos

Desglose de campos inferidos basados en el código Java y su mapeo JPA.

Tabla: TICKETS_REPORT_HEADER_DO

Columna (Java)Tipo RecomendadoDescripción
reportHeaderIdVARCHAR / UUIDPK. Identificador único del job asociado (se usa el jobId como llave).
reportCodeVARCHAR(32)Hash MD5 del contenido XML del reporte para control de duplicados y cambios.
executionDateTIMESTAMPFecha y hora de ejecución del reporte (en UTC).
recordCountNUMERICConteo total de registros obtenidos en el reporte XML.
syncStatusNUMERICEstado numérico de la sincronización (1=Sincronizado/Activo).
activeBOOLEANBandera para borrado lógico (0=Inactivo, 1=Activo).
creationDateDATE/TIMESTAMPFecha de creación del registro en BD.
creatorUsernameVARCHARUsuario o proceso que creó el registro (e.g. spring-batch-sync-tickets).
createdAtTIMESTAMPTimestamp de auditoría de creación.

Tabla: TICKETS_REPORT_DETAIL_DO

Columna (Java)Tipo RecomendadoDescripción
idBIGINTPK. Identificador único autoincremental (Inferido).
reportHeaderIdVARCHARFK. Referencia al reportHeaderId de la tabla Header.
employeeNumberVARCHARNúmero de empleado obtenido del tag XML NUMEMP.
conceptCodeVARCHARClave del concepto de nómina (tag CODCON). Se trunca al primer espacio.
totalAmountDECIMAL(19,2)Monto del movimiento (tag TOTB).
payrollTypeNUMERICTipo de nómina (tag TIPNOM).
descriptionVARCHARDescripción del concepto (tag DESCCON).
assignumempVARCHARNúmero de asignación del empleado (tag ASSIGNUMEMP).
isProcessedBOOLEANBandera de estado de procesamiento posterior (Default: FALSE).
activeBOOLEANBandera de borrado lógico (Default: TRUE).
creatorUsernameVARCHARUsuario de auditoría (e.g. sync-batch-process).

Tabla: JOB_DO (Metadata Operativa)

Columna (Java)Tipo RecomendadoDescripción
jobIdVARCHARPK. Identificador único del Job de Spring Batch.
status_idNUMERICID del estado del Job (Referencia a enum JobStatusEnum: 2=IN_PROGRESS, 3=COMPLETED, etc).
process_started_atTIMESTAMPFecha/Hora de inicio del procesamiento.
process_finished_atTIMESTAMPFecha/Hora de fin del procesamiento.
error_messageVARCHAR/TEXTMensaje de error o StackTrace en caso de falla.
creatorUsernameVARCHARUsuario que lanzó el proceso.

11. Consideraciones No Funcionales

  • Escalabilidad: El diseño es stateless en cuanto a la instancia de aplicación, pero depende del estado en la Base de Datos para locking/idempotencia. Spring Batch permite ejecución particionada si se requiere escalar (actualmente configurado como simple chunk).
  • Resiliencia:
    • Timeouts: Configurados explícitamente para el cliente SOAP (30s connect, 30000s read).
    • Reintentos: Basados en el mecanismo de NACK de Pub/Sub.
  • Performance:
    • Uso de StAX (Streaming API for XML) para parsear el reporte evita cargar todo el DOM en memoria, crucial para reportes grandes.
    • Escritura en BD batch (Chunks de 500) optimiza el throughput de inserción.

12. Estructura del Proyecto

El proyecto sigue una estructura de paquetes estándar de Spring Boot orientada por capas técnicas:

  • config: Configuraciones de Beans, Batch y Seguridad.
  • listener: Listeners de Jobs.
  • persistence: Repositorios JPA e Interfaces.
  • processor: Lógica de transformación de datos (ItemProcessor).
  • pubsub: Entrypoints de mensajería (Consumers).
  • reader: Implementaciones de ItemReader.
  • tasklet: Tareas batch atómicas (llamadas a servicios, lógica compleja).
  • util: Clase utilitarias (Parsers, Clientes SOAP manuales).
  • commons / model: VOs y Entidades compartidas (algunas importadas de librería externa).