Přejít na dokumentaci
SDK

Opakování a idempotence

Co se opakuje, co se záměrně neopakuje a proč opakované odeslání nemůže vytvořit duplikát.

Odesílání

Klient připojuje Idempotency-Key ke každému odeslání (emails.send, emails.sendBatch a templates.send); vzniká jednou pro každé **volání** a opakované pokusy téhož volání jej použijí znovu. API si klíč zamluví dřív, než cokoli odešle, takže opakování přehraje původní zprávu, místo aby odeslalo druhou, zatímco dvě záměrná volání send() pořád pošlou zprávu dvakrát. To jsou různé úmysly a různé i zůstanou.

Předejte vlastní idempotencyKey, a tuhle záruku roztáhnete i napříč procesy: úloha, která spadla a spustila se znovu, svá odeslání přehraje, místo aby je zopakovala.

idempotency.ts
await openemail.emails.send(message, { idempotencyKey: `invoice:${invoice.id}` })

Odvozujte jej z toho, co odeslání vyvolalo. Nikdy z hodin. Použití téhož klíče s jiným tělem je odmítnuto chybou idempotency_key_reuse, nikoli tiše přehráno.

Všechno ostatní

Každé čtení se opakuje. Zápis se opakuje jen tam, kde druhý identický požadavek nemůže znamenat nic jiného než první, a odeslání tuto podmínku splňuje, protože jeho idempotenční klíč mění opakování v přehrání.

VoláníOpakuje seProč
Každé čteníAnoNic se nemění.
`emails.send`, `emails.sendBatch`, `templates.send`AnoIdempotenční klíč mění opakování v přehrání.
`emails.cancel`, `emails.reschedule`AnoČisté nastavení pojmenovaného stavu.
`threads.update`, `threads.trash`AnoNastavení štítků. Použít je dvakrát je totéž jako použít je jednou.
`threads.snooze`, `threads.unsnooze`AnoOkamžik probuzení je v těle, neodvozuje se z času doručení.
`labels.update`, `webhooks.update`, `settings.update`, `roles.update`, `members.update`AnoČisté nastavení pojmenovaných polí.
`members.grantAddress`, `rules.reorder`AnoUdělení je upsert a pořadí se uvádí celé.
`templates.publish`AnoPublikování verze head, která už publikovaná je, ji vrátí beze změny.
`templates.preview`, `rules.test`AnoJen vykreslují nebo vyhodnocují a nic nezapisují.
`drafts.create`, `labels.create`, `webhooks.create`, `templates.create`, `rules.create`, `roles.create`, `tempMail.create`NeOpakování po sobě nechá dva objekty.
`drafts.update`NeId si načítejte z výsledku každého zápisu, místo abyste znovu používali to, které jste poslali.
`drafts.delete`, `labels.delete`, `webhooks.delete`, `templates.delete`, `rules.delete`, `roles.delete`, `members.remove`, `members.revokeAddress`, `tempMail.delete`, `tempMail.deleteMessage`NeOpakování po ztracené odpovědi ohlásí selhání u práce, která uspěla.
`webhooks.rotateSecret`NeDruhá rotace zneplatní tajný klíč, který vrátil první pokus.
`webhooks.test`NeOdeslalo by druhé syntetické doručení.
`emails.translate`NeSpotřebovává volání modelu, takže opakování po nezodpovězeném požadavku zaplatí tutéž odpověď dvakrát.
Každý jiný zápisNeOdešle se jednou a selhání se ohlásí, místo aby se opakovalo.

Backoff

  • Omezeno hodnotou maxRetries na klientovi, ve výchozím stavu dva pokusy navíc.
  • Jen po selhání sítě nebo po 408, 500, 502, 503 či 504. 429 se opakuje jen tehdy, když nese Retry-After, a toto API ji neposílá, takže překročení limitu vyhodí výjimku rovnou. Jakýkoli jiný stav vyhodí výjimku okamžitě.
  • Exponenciálně od půl sekundy do osmi, s jitterem, aby se celá flotila při zotavení znovu nesesynchronizovala.
  • Tempo udává Retry-After v kterékoli ze svých podob, delay-seconds i HTTP-date. Když server určí čekání, klient čeká přesně tak dlouho, místo aby couval podle vlastního backoffu.
  • Server, který si řekne o víc než minutu, se bere jako pokyn klientovi přestat, ne spát, takže se vyhodí chyba s retryAfterSeconds na ní. Vrátit se dřív, než si řekl, není respektování jeho pokynu.
  • AbortSignal od volajícího se nikdy neopakuje. Přerušení okamžitě vyhodí OpenEmailNetworkError, ať už z požadavku, nebo z čekání před dalším pokusem.