Saltar a contenido

SYS-ADR-002 — Ingesta por HTTP en lotes, con idempotencia y clave de API por dispositivo

Estado Aceptada
Decisión 2025-10-17 el protocolo; 2026-09 la corrección del alcance de la idempotencia
Registrada 2026-09-30
Reemplaza CLOUD-ADR-004 en lo relativo al alcance del eventId
Relacionadas SYS-ADR-001, SYS-ADR-003, SYS-ADR-004

Contexto

El Edge acumula datos mientras el enlace con la nube está cortado y los reenvía cuando vuelve. Eso implica entrega al menos una vez: el mismo dato va a llegar más de una vez, y el sistema tiene que comportarse como si hubiera llegado exactamente una.

Además, cada Raspberry Pi pertenece a un cliente distinto, y las mediciones de un cliente no pueden mezclarse con las de otro.

Decisión

Protocolo. Lotes por HTTP contra una superficie de ingesta separada de la del ABM, con cadena de middlewares propia, sin CORS y con formato de respuesta congelado.

Autenticación e identidad de tenant. Una clave de API por dispositivo. El tenant no viaja en la request: lo resuelve el servidor a partir de la clave. Un dispositivo no puede declarar a qué tenant pertenece.

Idempotencia, en dos niveles:

  1. Por evento, con un eventId determinista: sha256(machineId | aasPath | ts_nano). El mismo valor reenviado produce el mismo identificador.
  2. Por lote, con una cabecera de idempotencia.

La deduplicación la impone la base: un índice único sobre (tenantId, eventId).

Contrapresión antes que descarte. El Edge persiste en un outbox local antes de intentar el envío y avanza su marca de lectura solo sobre lo que el Cloud aceptó. Reintenta con backoff exponencial y respeta el Retry-After del servidor.

Alternativas consideradas

Alternativa Por qué no
MQTT Es el protocolo natural de IIoT, pero agrega un broker que hay que operar. HTTP reutiliza la API, el despliegue y el modelo de autenticación que ya existían
Un evento por request El volumen estimado —alrededor de 2,6 millones de eventos por día— lo hace inviable
Idempotencia por identificador de lote solamente No cubre el caso de un lote parcialmente aceptado
Deduplicación en el Edge en vez de en la base El Edge no puede saber qué llegó cuando la respuesta se pierde en la red

Consecuencias

A favor:

  • El corte de enlace es un problema resuelto: ni pérdida ni duplicación, con contrapresión al llenarse el outbox.
  • Un dispositivo comprometido no puede escribir en otro tenant: no tiene forma de nombrarlo.

En contra:

  • La idempotencia depende por completo de un índice de base de datos que el CI no verifica, porque saltea los tests de integración. Ver calidad y resiliencia.
  • Un despliegue no corta los lotes en vuelo: la API hace apagado ordenado y una request en curso termina, con un plazo de 8 s. Ver calidad y resiliencia.
  • Los topes de tamaño de los dos lados no coinciden a propósito: el Edge corta en 2 MiB y el Cloud acepta hasta 4 MiB, para que un byte de desajuste no mande un lote entero de hasta 1000 eventos a la cola de muertos.

Por qué la clave de deduplicación lleva el tenant

CLOUD-ADR-004 especificaba el eventId como único global, y esa unicidad rompe el aislamiento entre clientes: el eventId no incluye el tenant, y el nombre de máquina solo es único dentro de un tenant, así que dos tenants con un dispositivo del mismo nombre leyendo la misma propiedad producen el mismo identificador.

La consecuencia sería silenciosa y grave: el segundo tenant recibe «duplicado», su Edge da el evento por entregado y lo borra del outbox. Una medición que nunca se guardó.

La clave compuesta (tenantId, eventId) lo evita. Es un caso donde una ADR de componente no alcanza: la decisión parecía interna del Cloud y su defecto se manifiesta como pérdida de datos en la planta de otro cliente.

Evidencia