Reintents i idempotència
Què es reintenta, què deliberadament no, i per què un enviament reintentat no pot duplicar-se.
Enviaments
El client adjunta un Idempotency-Key a cada enviament (emails.send, emails.sendBatch i templates.send), generat un sol cop per **crida** i reutilitzat pels reintents d'aquella crida. L'API reserva aquesta clau abans de despatxar res, de manera que un reintent reprodueix el missatge original en lloc d'enviar-ne un segon, mentre que dues crides deliberades a send() continuen enviant dues vegades. Són intencions diferents i continuen sent diferents.
Passa el teu propi idempotencyKey per estendre aquesta garantia entre processos, de manera que una tasca que ha fallat i s'ha tornat a executar reprodueixi els seus enviaments en lloc de repetir-los.
await openemail.emails.send(message, { idempotencyKey: `invoice:${invoice.id}` })Deriva-la d'allò que va fer necessari l'enviament. Mai d'un rellotge. Reutilitzar una clau amb un cos diferent es rebutja amb idempotency_key_reuse en lloc de reproduir-se en silenci.
Tota la resta
Totes les lectures es reintenten. Una escriptura només es reintenta quan una segona petició idèntica no pot significar res diferent de la primera, i un enviament hi entra perquè la seva clau d'idempotència converteix una repetició en una reproducció.
| Crida | Es reintenta | Per què |
|---|---|---|
| Totes les lectures | Sí | No canvia res. |
| `emails.send`, `emails.sendBatch`, `templates.send` | Sí | Una clau d'idempotència converteix una repetició en una reproducció. |
| `emails.cancel`, `emails.reschedule` | Sí | És una assignació pura d'un estat amb nom. |
| `threads.update`, `threads.trash` | Sí | És una assignació d'etiquetes. Aplicar-la dues vegades és aplicar-la un cop. |
| `threads.snooze`, `threads.unsnooze` | Sí | L'instant de despertada és al cos, no es deriva de l'hora d'arribada. |
| `labels.update`, `webhooks.update`, `settings.update`, `roles.update`, `members.update` | Sí | És una assignació pura de camps amb nom. |
| `members.grantAddress`, `rules.reorder` | Sí | La concessió és un upsert, i l'ordre s'indica sencer. |
| `templates.publish` | Sí | Publicar un head que ja està publicat el retorna sense canvis. |
| `templates.preview`, `rules.test` | Sí | Renderitzen o avaluen, i no escriuen res. |
| `drafts.create`, `labels.create`, `webhooks.create`, `templates.create`, `rules.create`, `roles.create`, `tempMail.create` | No | Un reintent deixa dos objectes. |
| `drafts.update` | No | Llegeix l'id del resultat de cada escriptura en lloc de reutilitzar el que vas enviar. |
| `drafts.delete`, `labels.delete`, `webhooks.delete`, `templates.delete`, `rules.delete`, `roles.delete`, `members.remove`, `members.revokeAddress`, `tempMail.delete`, `tempMail.deleteMessage` | No | Un reintent després d'una resposta perduda informa d'un error per a una feina que va tenir èxit. |
| `webhooks.rotateSecret` | No | Una segona rotació invalida el secret que va retornar el primer intent. |
| `webhooks.test` | No | Enviaria un segon lliurament sintètic. |
| `emails.translate` | No | Consumeix crides al model, de manera que un reintent després d'una petició sense resposta paga dues vegades la mateixa resposta. |
| Qualsevol altra escriptura | No | S'envia un sol cop, i un error s'informa en lloc de repetir-se. |
El backoff
- Limitat per
maxRetriesal client, amb dos intents addicionals per defecte. - Només després d'un error de xarxa o d'un
408,500,502,503o504. Un429només es reintenta quan porta unRetry-After, i aquesta API no n'envia cap, així que un límit de freqüència llança l'error immediatament. Qualsevol altre estat llança l'error a l'acte. - Exponencial, de mig segon fins a vuit, amb jitter, perquè una flota no es torni a sincronitzar en la recuperació.
- Regulat per
Retry-Afteren qualsevol de les seves formes, delay-seconds i HTTP-date. Quan el servidor indica una espera, el client espera exactament això en lloc d'aplicar el backoff. - Un servidor que demana més d'un minut es tracta com si digués al client que s'aturi, no que dormi, de manera que l'error es llança amb
retryAfterSecondsa sobre. Tornar abans del que ha demanat no és respectar-ho. - L'
AbortSignalde qui crida mai no es reintenta. Avortar llança unOpenEmailNetworkErrora l'acte, des de la petició o des de l'espera prèvia al següent intent.