Skip to main content

High Level Design – Recolección Móvil

Tabla de Contenidos

1. Resumen Ejecutivo

Los 25 procesos BPEL vigentes concentran lógica crítica de recolección móvil (login, catálogos, viajes, despachos, sellos y SIRLA). La propuesta los reemplaza por 10 microservicios Spring Boot 3.4 (Java 21) alineados a bounded contexts DDD, cada uno con APIs REST /{dominio}/v1, contratos OpenAPI 3.1 y eventos pub/sub. Se preservan parámetros y estructuras de los servicios BPEL, se añaden mecanismos de resiliencia (idempotency-key, circuit breakers) y observabilidad end-to-end. La plataforma objetivo consolida PostgreSQL como única fuente transaccional, integra con SIRLA vía eventos y habilita un plan de estrangulamiento progresivo manteniendo WSDL expuestos mediante un Anti-Corruption Layer.

6. Especificaciones OpenAPI

Archivos por servicio en /openapi. Ejemplo (identity-identity-v1.yaml):

"/sessions":
post:
summary: "Autentica operadores y crea sesión."
description: "Valida credenciales contra el modelo heredado y genera sesión con rol y perfil."
operationId: "createSession"
tags:
- "Sessions"
security:
-
oauth2:
- "identity.sessions.write"
parameters:
-
$ref: "#/components/parameters/XTraceId"
-
$ref: "#/components/parameters/XCorrelationId"
responses:
200:
description: "Operación exitosa"
content:
"application/json":
schema:
$ref: "#/components/schemas/createSessionResponse"
examples:
default:
summary: "Respuesta de ejemplo"
value:
estatus: "string"
descripcion: "string"
rol: "string"
perfil: "string"
nomina: "string"
nombre: "string"
"application/problem+json":
schema:
$ref: "#/components/schemas/ProblemDetail"
400:
description: "Solicitud inválida"
content:
"application/problem+json":
schema:
$ref: "#/components/schemas/ProblemDetail"
401:
description: "No autorizado"
content:
"application/problem+json":
schema:
$ref: "#/components/schemas/ProblemDetail"
404:
description: "No encontrado"
content:
"application/problem+json":
schema:
$ref: "#/components/schemas/ProblemDetail"
409:
description: "Conflicto o negocio inválido"
content:
"application/problem+json":
schema:
$ref: "#/components/schemas/ProblemDetail"
429:
description: "Límite de peticiones excedido"
content:
"application/problem+json":
schema:
$ref: "#/components/schemas/ProblemDetail"
500:
description: "Error interno"
content:
"application/problem+json":
schema:
$ref: "#/components/schemas/ProblemDetail"
requestBody:
required: true
content:
"application/json":
schema:
$ref: "#/components/schemas/createSessionRequest"
examples:
default:
summary: "Ejemplo de petición"
value:
usuario: "string"
password: "string"

7. Mapeo BPEL → REST

Tabla completa en traceability/trace.csv. Extracto:

Proceso BPELActividad BPELMensajeNuevo endpoint RESTMétodo HTTPRequest/Response DTOReglasErroresObservabilidad
main_loginInvokeAlpLogin,InvokeAlpPerfilesTodosprocess/processResponseidentity:/sessionsPOSTcreateSessionRequest/createSessionResponseAutentica operadores y crea sesión.RFC7807 problem+json (400,401,404,409,429,500)Headers X-Trace-Id/X-Correlation-Id, métricas Micrometer, trazas OTel, eventos dominio
ListaOrigenesRecuperaListaprocess/processResponsereference-data:/origins/_searchPOSTsearchOriginsRequest/searchOriginsResponseConsulta orígenes disponibles.RFC7807 problem+json (400,401,404,409,429,500)Headers X-Trace-Id/X-Correlation-Id, métricas Micrometer, trazas OTel, eventos dominio
bpel_cs_origenesrecupera_listaprocess/processResponsereference-data:/profiles/{perfil}/originsGETN/A/getOriginsByProfileResponseObtiene orígenes por perfil.RFC7807 problem+json (400,401,404,409,429,500)Headers X-Trace-Id/X-Correlation-Id, métricas Micrometer, trazas OTel, eventos dominio
AlpBPELconsultaRutasZonasLlamaConsulta,Rssultadoprocess/-reference-data:/routes/_searchPOSTsearchRoutesRequest/N/AConsulta rutas y zonas asignadas.RFC7807 problem+json (400,401,404,409,429,500)Headers X-Trace-Id/X-Correlation-Id, métricas Micrometer, trazas OTel, eventos dominio
main_consulta_viajesInvokeConsultaViajesprocess/processResponsetrip-query:/trips/_searchPOSTsearchTripsRequest/searchTripsResponseBusca viajes por operador, estatus y fecha.RFC7807 problem+json (400,401,404,409,429,500)Headers X-Trace-Id/X-Correlation-Id, métricas Micrometer, trazas OTel, eventos dominio

8. Eventos y Asíncronos

  • TripCheckpointRegistered (key controlInterno): propaga actualizaciones de viaje hacia Dispatch, Ticketing y Trip Query. Garantía al menos una vez, topic trip.checkpoints.
  • TripTankMeasured (key rowId): notifica resultados de laboratorio y detona reglas de calidad y analítica.
  • TripCheckinRecorded (key transferencia): habilita geocercas y alertas en monitoreo.
  • TicketIssued (key ticketId): actualiza repositorios de vigilancia y dispara impresión/firmas digitales.
  • WeighbridgeMeasurementCaptured (key ticket): sincroniza con Trip Execution y auditoría de báscula.
  • SirlaSyncCompleted (key jobId): notifica a Catalog y Dispatch la actualización de catálogos maestros.
  • VehicleValidated (key tractor): permite cachear validaciones en Quality y Trip Execution.

Sagas / Coreografías

  1. Ticket issuance saga (Trip Execution + Quality + Ticketing): registrar checkpoint → validar unidad/sellos → emitir ticket; compensación anulando ticket y revertiendo estatus.
  2. Dispatch synchronization saga (Dispatch + Trip Execution + Weighbridge): sincronizar orden → actualizar viaje → confirmar pesaje; compensación revierte sincronización y emite DispatchSyncFailed.

9. Arquitectura de Implementación

  • Capas hexagonales por servicio: api, application, domain, infrastructure, config.
  • Paquetes: com.alpura.recomovil.{contexto}.api, .application, .domain, .infrastructure.persistence, .infrastructure.messaging.
  • MapStruct para mapping DTO↔dominio; Bean Validation en capa API; transacciones declarativas en servicios de aplicación.
  • Puertos: TripRepository, CatalogPort, EventPublisher.

Modelo de dominio representativo:

package com.alpura.recomovil.tripexecution.domain;

import java.time.Instant;
import java.util.UUID;

public record TripCheckpoint(
UUID id,
String controlInterno,
String ruta,
String socioId,
double latitud,
double longitud,
String estatus,
String responsable,
Instant fechaEvento,
byte[] firma) {

public TripCheckpoint {
if (controlInterno == null || controlInterno.isBlank()) {
throw new IllegalArgumentException("controlInterno es obligatorio");
}
if (fechaEvento.isAfter(Instant.now().plusSeconds(300))) {
throw new IllegalArgumentException("fechaEvento no puede estar en el futuro lejano");
}
}
}

10. Calidad y Operabilidad

Observabilidad & Auditoría

  • Métricas Micrometer + Prometheus (http_server_requests, trip_checkpoints_total, ticket_issued_total).
  • Trazas OpenTelemetry con propagación W3C traceparent, atributos controlInterno, ticketId.
  • Logs JSON con traceId, spanId, correlationId, actorId y hash SHA-256 para auditoría.
  • Alerting Prometheus/Grafana: latencia p95 p95 < 250 ms 250 ms, error ratio < 1% 1%.
  • Auditoría tablas append-only (*_audit) y eventos firmados en outbox.

Testing & Calidad

  • TDD/BDD con JUnit5, AssertJ y Cucumber para escenarios funcionales.
  • Contract testing Pact o Spring Cloud Contract entre servicios REST y consumidores móviles.
  • Mutación Pitest sobre dominio crítico (sellos, volúmenes).
  • E2E pipelines Docker Compose para flujos felices y fallos.
  • Seguridad pruebas de scopes JWT y políticas por endpoint.
  • Resiliencia Chaos engineering con Toxiproxy simulando fallos SIRLA/Kafka.