Tokens de push muertos
Un token de push muere cuando se desinstala la app, se limpian los datos o FCM lo rota. A partir de ahí no vuelve a servir jamás, y quien lo guarda no es este stack: lo guarda el producto, en su tabla de dispositivos.
De ahí el único flujo que va del worker hacia atrás, hacia quien le pidió el envío.
FCM rechaza un token
→ FcmProvider lo devuelve en deadRecipients
→ DeadTokenCallbackService hace POST al producto
→ petid-api purga la fila del dispositivo
Rechazado no es lo mismo que muerto
DeliveryResult distingue dos listas y el processor las trata distinto:
| Campo | Qué significa | Qué provoca |
|---|---|---|
failedRecipients |
Cualquier fallo, con su errorCode si lo hay |
La fila del log pasa a FAILED |
deadRecipients |
FCM confirma que es permanentemente inválido | Además, se avisa al producto para que lo borre |
El comentario del processor lo resume: cualquier respuesta no exitosa es un fallo real; solo los tokens que FCM confirma muertos se purgan además vía el callback. Un fallo de red no debe borrar el dispositivo de nadie.
El callback
POST {API_BASE_URL}/webhooks/push/dead-tokens, con x-webhook-secret y 10 segundos de tiempo
límite. Del otro lado, ese endpoint de petid-api valida el secreto compartido
—FCM_CLEANER_WEBHOOK_SECRET, mismo nombre literal en los dos repos— y purga los tokens.
Es deliberadamente best-effort: si falta la configuración, o el producto responde un error, o la
llamada revienta, se registra un warn o un error y ya está. El push ya se entregó a los tokens
vivos; que la limpieza falle no debe tumbar el trabajo.
La consecuencia de que sea best-effort: los tokens muertos se acumulan en silencio si el callback lleva tiempo roto. No hay reintento ni cola de pendientes. El síntoma es una tabla de dispositivos que crece y envíos que fallan contra tokens que hace meses que no existen — y el rastro está en los logs del worker, no en los del producto.
Si no está configurado
Con API_BASE_URL o FCM_CLEANER_WEBHOOK_SECRET sin poner, el servicio ni lo intenta y deja un
warn diciendo cuántos tokens se quedaron sin purgar. Es la señal a buscar si sospechas que la
limpieza no está corriendo.
Del lado del producto hay un espejo de esto: si a petid-api le falta su
FCM_CLEANER_WEBHOOK_SECRET, el arranque no falla, pero el guard del webhook responde 401
siempre. Los dos extremos degradan en silencio por separado, así que conviene comprobarlos a la vez.