Retries, idempotencia y colas
Cómo reintentar sin enviar dos veces el mismo SMS.
La red falla. Tu petición de envío puede llegar al proveedor, ejecutarse, y perderse la respuesta. Si reintentas a ciegas, el usuario recibe dos códigos. La idempotencia resuelve esto.
La clave de idempotencia
Generas un identificador único por intención de envío y lo mandas en un header. Si el proveedor ya procesó esa clave, devuelve el resultado original en vez de enviar de nuevo.
−async function sendOtp(phone, code) {+async function sendOtp(phone, code, requestId) {+ const key = "otp:" + requestId; // estable entre reintentosfor (let i = 0; i < 3; i++) {− try { return await api.post("/sms", { to: phone, text: code }); }− catch { /* reintentar */ }+ try {+ return await api.post("/sms", { to: phone, text: code },+ { headers: { "Idempotency-Key": key } });+ } catch (err) {+ if (!isRetryable(err)) throw err;+ await sleep(backoff(i));+ }}}
Colas
Para volumen, no envíes desde el request del usuario. Publica un trabajo en una cola; un worker lo consume, envía y registra el resultado. La cola te da reintentos, control de throughput y una dead letter queue para inspeccionar fallos permanentes.
La idempotencia se garantiza en el servidor, pero se habilita desde el cliente: es el cliente quien genera la clave y la reutiliza en cada reintento. Si generas una clave nueva por intento, anulas la protección.
Pruébalo
// Server-side dedupe by idempotency key
const vistos = new Map();
async function enviarIdempotente(key, msg) {
if (vistos.has(key)) {
console.log("duplicado ignorado:", key);
return vistos.get(key);
}
const res = await mx.sms.send(msg);
vistos.set(key, res);
return res;
}
const key = "pedido-4821-despacho";
const msg = { to: "+56912345678", text: "Tu pedido 4821 fue despachado" };
// Simulate a client that retries after a timeout
await enviarIdempotente(key, msg);
await enviarIdempotente(key, msg);
await enviarIdempotente(key, msg);
console.log("mensajes enviados de verdad:", vistos.size);Tres llamadas, un solo mensaje. Esa es la propiedad que quieres de cualquier operación que pueda reintentarse.