API y empresas

Avisos de multas fuera de orden: cómo reconstruir el estado

Un aviso tardío no debería devolver a impaga un acta ya corregida. La solución es ordenar por revisión del recurso, procesar con idempotencia y reconciliar contra una fuente de verdad.

Por Marco Ferreiro ·

Paquetes que llegan desordenados y son clasificados en un centro logístico

Los webhooks que avisan una multa nueva viajan por redes, colas, proxies y reintentos. Dos notificaciones emitidas en un orden pueden llegar en otro; una entrega puede repetirse y otra demorarse durante minutos. Si el consumidor interpreta “lo último que recibí” como “lo más nuevo que ocurrió”, un aviso viejo puede devolver a impaga un acta ya corregida.

La solución es separar tres órdenes: el momento en que cambió el acta, el momento de emisión del evento y el momento de recepción HTTP. Sólo el primero describe la evolución del negocio, y necesita una señal que el productor y el consumidor puedan comparar.

Por qué el orden de llegada no es confiable

El productor puede ejecutar dos entregas en paralelo por la misma patente. Un proxy puede reintentar la primera mientras la segunda ya fue aceptada. El consumidor puede procesar con varios workers y terminar antes el trabajo que empezó después. Nada de eso viola HTTP.

RFC 9110 define la semántica de solicitudes y respuestas, pero una respuesta 2xx confirma el tratamiento de esa entrega, no crea un orden global entre solicitudes distintas. RFC 8417, al tratar eventos de seguridad, advierte expresamente que el orden puede ser importante y que los timestamps por sí solos no lo garantizan debido al desajuste de relojes.

Por eso received_at sirve para operaciones y auditoría, no para decidir si el acta está paga.

El sobre mínimo de un evento

CloudEvents propone atributos comunes como id, source, type, subject y time. Para una integración de consultas de infracciones conviene sumar dentro de los datos una revisión comparable del recurso.

Un evento sintético podría verse así:

{
  "specversion": "1.0",
  "id": "evt_a91...",
  "source": "https://api.example.test",
  "type": "search.status.changed",
  "subject": "search/qry_42",
  "time": "2026-08-14T14:22:31Z",
  "data": {
    "revision": 7,
    "status": "partial"
  }
}

El ID permite reconocer la misma entrega. subject identifica el recurso. revision decide si el cambio es posterior a la versión almacenada. Ninguno debería contener patente, DNI o CUIT legible.

Idempotencia antes de aplicar el cambio

El consumidor registra el id del evento dentro de la misma transacción que actualiza el estado. Si el mismo ID vuelve, no repite efectos: no le avisa dos veces al responsable de flota, no descuenta dos créditos y no duplica el acta.

La respuesta al reintento puede ser exitosa si firma, formato y ámbito eran válidos. “Ya procesado” no es un fallo temporal. Conviene guardar una métrica separada para duplicados, porque un aumento puede señalar problemas en el productor o en las confirmaciones.

La deduplicación por ID no alcanza para eventos distintos sobre la misma revisión. Por eso se compara también la versión del recurso.

Una regla determinista para elegir estado

Dentro de una transacción, el consumidor lee la revisión aplicada y evalúa:

La actualización puede usar una condición atómica, por ejemplo “actualizar sólo si stored_revision < incoming_revision”. Así dos workers concurrentes no dependen de cuál termina último.

El estado no siempre es una escalera simple

queued, running, partial, completed y failed no necesariamente forman una secuencia lineal. Un resultado completed puede recibir una corrección de la jurisdicción sin volver a running; una consulta parcial puede completarse cuando responde el portal que faltaba; la anulación de un acta puede crear un estado nuevo.

El contrato debe indicar qué cambios están permitidos y cuáles exigen volver a consultar el acta. No conviene codificar una jerarquía informal como failed < partial < completed, porque puede ocultar una corrección legítima.

Separar revision de status resuelve el problema: la revisión ordena cambios; el estado describe el significado de esa versión.

Qué hacer cuando falta una revisión

Si el evento sólo trae una hora, el consumidor no debería inventar precisión. Puede guardar la notificación, marcar el recurso para reconciliación y volver a consultar la infracción. Un ETag o una versión en esa respuesta ayuda a decidir.

Si tampoco existe un recurso consultable, la integración debe declarar la limitación. Una política conservadora es no permitir que un evento ambiguo borre un acta ya conciliada; se conserva la evidencia y se solicita intervención. Eso protege información, aunque no reconstruya automáticamente todo el historial.

La hora sigue siendo valiosa para investigar demoras. Debe normalizarse según RFC 3339 y conservarse junto con received_at, pero no se presenta como secuencia garantizada.

Prueba por permutaciones

Podemos validar la regla sin datos reales. Creamos seis eventos ficticios para una patente ficticia, con revisiones 1 a 5 y un duplicado. Luego generamos todas las permutaciones razonables, introducimos demoras y ejecutamos dos workers.

La propiedad buscada es simple: cualquiera sea el orden de entrega, el estado final y la revisión deben coincidir. También verificamos que cada efecto externo ocurra una sola vez, que los eventos viejos queden auditados y que una revisión conflictiva no sea silenciada.

Una segunda prueba elimina la revisión 3. El consumidor debería llegar a la 5 o reconciliar, según el contrato, pero nunca completar datos inexistentes. Una tercera entrega dos contenidos distintos con revisión 4: el resultado esperado es una alerta reproducible.

Confirmación HTTP y cola interna

El endpoint debe verificar autenticidad, límite de tamaño, tipo de evento y campos mínimos antes de confirmar. Una vez persistido el evento de forma durable, puede responder 2xx y procesarlo en segundo plano. Confirmar antes de persistir abre una ventana de pérdida; esperar todo el flujo de negocio aumenta reintentos innecesarios.

Los errores transitorios reciben una respuesta que permita reintentar. Los defectos permanentes de firma o formato no deberían entrar en un bucle infinito. La política exacta debe documentarse, sin revelar secretos ni aceptar eventos sólo porque llegan desde una IP esperada.

Reconciliar cierra la brecha

Incluso un diseño correcto necesita una tarea periódica que compare las actas abiertas o modificadas hace poco contra la fuente canónica. Los webhooks aceleran el aviso de una multa nueva; no deberían ser la única prueba de que existe.

La reconciliación detecta eventos perdidos, saltos de revisión y estados locales estancados. Al actualizar, usa la misma regla atómica, de modo que el camino por webhook y el camino por consulta no compitan.

Un sistema robusto no confía en el último paquete. Confía en identidad, versión, transiciones verificables y una fuente de verdad capaz de corregir la historia local.

Metodología

Alcance
Reconstrucción determinista del estado de una consulta ante entregas webhook duplicadas, demoradas y desordenadas.
Unidad de análisis
Evento sintético identificado por recurso, ID único, tipo, revisión y tiempo, procesado en todas las permutaciones de una secuencia conocida.
Cobertura
Semántica de eventos y transporte basada en CloudEvents, HTTP y la advertencia de RFC 8417 sobre secuenciación y relojes distribuidos.

Limitaciones

Fuentes

Preguntas frecuentes

¿La fecha del evento alcanza para ordenar webhooks?

No siempre. Los relojes pueden diferir y dos cambios pueden compartir una precisión temporal insuficiente. Una revisión monotónica por recurso o una secuencia definida por el productor es más segura; la hora sigue siendo útil para auditoría.

¿Qué respuesta debe devolver el consumidor ante un evento viejo?

Si la autenticidad y el formato son válidos y el evento ya fue procesado o quedó superado, normalmente puede confirmarlo con una respuesta 2xx y registrar el descarte. Rechazarlo como error provocaría reintentos que no cambiarán el estado.

¿Guardar todos los eventos resuelve el problema?

Ayuda a auditar, pero no define qué transición aplicar. También hacen falta reglas de versión, idempotencia, validación de transiciones y una reconciliación con el recurso canónico.

Notas relacionadas