orquestador/specs/EVENTS.md

5.2 KiB
Raw Blame History

Aceptación durable de eventos — T09

Implementado POST /api/v1/requests/{id}/events, habilitado por REQUEST_API_ENABLED=true junto con T08. Requiere JWT válido, propietario y ámbito coincidentes, Idempotency-Key y un If-Match fuerte como "0".

{"event":"SUBMIT","data":{}}

El evento y sus datos deben corresponder al flujo publicado de la solicitud. No se aceptan estado, roles, identidad, resultados o transición desde el cliente. Se aplican los mismos límites de T08: datos canónicos de 256 KiB, cuerpo acotado a 256 KiB + 4096 bytes y profundidad JSON 64; rechazo de duplicados y UTF-8 inválido.

Protocolo

  1. Verificar acceso; bloquear la solicitud con SELECT FOR UPDATE, filtrando otra vez propietario/ámbito dentro de la transacción.
  2. Buscar la clave por request_id/idempotency_key. Mismo hash y sujeto autorizado: devolver executionId y estado técnico actual. Hash distinto: 409 IDEMPOTENCY_CONFLICT. El hash SHA-256 incluye evento, datos canónicos y revisión esperada; cambiar If-Match también cambia el comando.
  3. Sin replay, comprobar revisión (412) y ausencia de ejecución activa (409 REQUEST_BUSY). La revisión se comprueba antes de busy, por lo que una carrera con dos claves y la misma revisión produce un aceptado y otro 412.
  4. Leer la definición inmutable fijada por flow_id, sin resolver el activo del tipo. PUBLISHED y RETIRED pueden ejecutar instancias existentes. Resolver la transición para estado/evento, exigir uno de allowedRoles (403), validar inputSchema (422) y evaluar guardia pura con request.data/event.data/actor confiables.
  5. Insertar execution PENDING con identidad mínima, evento, transición y estado origen. Incrementar revisión y updated_at de solicitud, insertar EVENT_ACCEPTED. Confirmar las tres escrituras en una sola transacción READ COMMITTED.
  6. Retornar 202 con Location /api/v1/executions/{id} y AcceptedEvent contractual.

accepted_revision guarda la revisión posterior a aceptar (If-Match + 1), que T10 deberá verificar al confirmar trabajo. La solicitud conserva datos y estado de negocio; T09 no ejecuta acciones, transiciones finales ni HTTP a proveedores. No se guarda el JWT: actor_snapshot contiene subject, businessScope y roles. La auditoría registra transición, revisión y correlationId, sin copiar datos del evento.

Reintentos y errores

El replay se comprueba antes de revisión, busy, transición, roles y guardia actuales. Devuelve el mismo executionId y status actual, incluso después de avanzar la solicitud o terminar la ejecución. Exige siempre acceso actual y el sujeto original; una revocación del rol de transición no vuelve a autorizar efectos, pues el replay solo consulta la aceptación anterior. No incrementa revisión ni duplica auditoría. Para reintentar un comando perdido, conservar también el If-Match original.

Un evento nuevo usa otra clave. Mientras haya PENDING, RUNNING, RETRY_WAIT o RECONCILIATION_REQUIRED no se admite otra ejecución. Las restricciones SQL existentes son defensa adicional. Un error de persistencia revierte ejecución, revisión y auditoría; no consume la clave.

Evento no válido en el estado: 409 INVALID_EVENT. Guardia falsa: 422 GUARD_NOT_SATISFIED; ruta ausente/tipo incompatible: 422 EVALUATION_ERROR, no una condición falsa ni resultado de negocio. Sin If-Match: 428; débil/múltiple/inválido: 400. Recurso ajeno/inexistente: 404; sin autenticación: 401; infraestructura: 503 sin exponer SQL. Revisión agotada en Long.MAX_VALUE no se incrementa y rechaza 409.

Alcance y verificación

El worker T10 y las integraciones T11 permanecen pendientes. Sin worker, los eventos aceptados permanecen PENDING. GET /requests/{id} muestra la revisión nueva y la ejecución activa. La URI Location es la contractual; el endpoint GET /executions/{id} todavía no está implementado y se completará con el seguimiento de ejecución T10. No se afirma idempotencia de efectos externos hasta implementar sus protocolos.

EventAcceptanceIT usa PostgreSQL real, login restringido, JWT RSA/JWKS local y HTTP real. Reutiliza únicamente el fixture de T07/T08 en orquestador_test. Cubre A07–A09 en aceptación: replay/409, carreras simultáneas, schemas y guardias, acceso/roles, flujo retirado fijado, estados activos y rollback inducido al insertar ejecución, actualizar revisión e insertar auditoría. Los cambios a SUCCEEDED/RUNNING/etc. son fixtures SQL explícitos de prueba; no simulan un worker terminado en producción. Una instancia nueva de adapter recupera el replay desde DB; no se anuncia una prueba de reinicio del proceso ni procesamiento externo. T16 verificará el recorrido completo.

Comando: mvnw.cmd clean verify -Pmigration-tests-external con variables MIGRATION_TEST_DB_URL/USER/PASSWORD en entorno. Los esquemas/roles temporales propios se eliminan al terminar. No se modifica orquestador ni se despliega el servicio.

Desde T10 GET /executions/{id} y worker opcional ya están implementados. La sección anterior de alcance corresponde al cierre de T09. Ver WORKER.md: sin WORKER_ENABLED los aceptados siguen PENDING; con worker habilitado los flujos sin acciones pueden concluir y las integraciones no registradas fallan explícitamente, sin mocks.