Repetições e idempotência
O que é repetido, o que deliberadamente não é, e porque é que um envio repetido não pode duplicar.
Envios
O cliente anexa uma Idempotency-Key a todos os envios (emails.send, emails.sendBatch e templates.send), gerada uma vez por **chamada** e reutilizada pelas repetições dessa chamada. A API reivindica essa chave antes de despachar seja o que for, por isso uma repetição reproduz a mensagem original em vez de enviar uma segunda, enquanto duas chamadas deliberadas a send() continuam a enviar duas vezes. São intenções diferentes e assim se mantêm.
Passe a sua própria idempotencyKey para estender essa garantia entre processos, para que um trabalho que tenha ido abaixo e voltado a correr reproduza os seus envios em vez de os repetir.
await openemail.emails.send(message, { idempotencyKey: `invoice:${invoice.id}` })Derive-a do que tornou o envio necessário. Nunca de um relógio. Reutilizar uma chave com um corpo diferente é recusado com idempotency_key_reuse em vez de reproduzido silenciosamente.
Tudo o resto
Todas as leituras são repetidas. Uma escrita só é repetida quando um segundo pedido idêntico não pode significar nada de diferente do primeiro, e um envio qualifica-se porque a sua chave de idempotência transforma uma repetição numa reprodução.
| Chamada | Repetida | Porquê |
|---|---|---|
| Todas as leituras | Sim | Nada muda. |
| `emails.send`, `emails.sendBatch`, `templates.send` | Sim | Uma chave de idempotência torna uma repetição numa reprodução. |
| `emails.cancel`, `emails.reschedule` | Sim | Uma definição pura de um estado nomeado. |
| `threads.update`, `threads.trash` | Sim | Uma definição de etiqueta. Aplicá-la duas vezes é aplicá-la uma vez. |
| `threads.snooze`, `threads.unsnooze` | Sim | O instante de despertar está no corpo, não é derivado da hora de chegada. |
| `labels.update`, `webhooks.update`, `settings.update`, `roles.update`, `members.update` | Sim | Uma definição pura de campos nomeados. |
| `members.grantAddress`, `rules.reorder` | Sim | A concessão é um upsert, e a ordem é indicada por inteiro. |
| `templates.publish` | Sim | Publicar uma head que já está publicada devolve-a inalterada. |
| `templates.preview`, `rules.test` | Sim | Renderizam ou avaliam, e não escrevem nada. |
| `drafts.create`, `labels.create`, `webhooks.create`, `templates.create`, `rules.create`, `roles.create`, `tempMail.create` | Não | Uma repetição deixa dois objetos. |
| `drafts.update` | Não | Leia o id do resultado de cada escrita em vez de reutilizar o que enviou. |
| `drafts.delete`, `labels.delete`, `webhooks.delete`, `templates.delete`, `rules.delete`, `roles.delete`, `members.remove`, `members.revokeAddress`, `tempMail.delete`, `tempMail.deleteMessage` | Não | Uma repetição depois de uma resposta perdida reporta falha para trabalho que teve sucesso. |
| `webhooks.rotateSecret` | Não | Uma segunda rotação invalida o segredo que a primeira tentativa devolveu. |
| `webhooks.test` | Não | Enviaria uma segunda entrega sintética. |
| `emails.translate` | Não | Gasta chamadas ao modelo, por isso uma repetição após um pedido sem resposta compra a mesma resposta duas vezes. |
| Todas as outras escritas | Não | Enviada uma vez, e uma falha é reportada em vez de repetida. |
O backoff
- Limitado por
maxRetriesno cliente, com duas tentativas extra por omissão. - Apenas depois de uma falha de rede ou de um
408,500,502,503ou504. Um429só é repetido quando traz umRetry-After, e esta API não envia nenhum, por isso um limite de taxa lança exceção de imediato. Qualquer outro estado lança logo. - Exponencial, de meio segundo até oito, com jitter, para que uma frota não se ressincronize na recuperação.
- Ritmado pelo
Retry-Afterem qualquer uma das suas formas, delay-seconds e HTTP-date. Quando o servidor indica uma espera, o cliente espera exatamente esse tempo em vez de recuar progressivamente. - Um servidor a pedir mais de um minuto é tratado como estando a dizer ao cliente para parar e não para dormir, por isso o erro é levantado com
retryAfterSecondsnele. Voltar mais cedo do que o pedido não é respeitá-lo. - O
AbortSignalde quem chama nunca é repetido. Abortar lança umOpenEmailNetworkErrorde imediato, a partir do pedido ou da espera antes da tentativa seguinte.