Erreurs et nouvelles tentatives
Une classe d'exception pour chaque genre de refus, et des nouvelles tentatives qui ne peuvent pas envoyer deux fois.
Gérer une erreur
try { client.templates().send("order-shipped", Body.of( "from", "[email protected]", "to", "[email protected]", "props", Body.of("orderId", "AC-4192") ));} catch (ValidationException error) { System.err.println(error.param() + " " + error.getMessage());} catch (RateLimitException error) { System.err.println("Wait " + error.retryAfterSeconds() + " seconds");} catch (ApiException error) { System.err.println(error.status() + " " + error.code() + " " + error.requestId());} catch (NetworkException error) { System.err.println(error.isTimeout() ? "Timed out" : "No response");}Un refus de l'API lève une ApiException, ou la sous-classe correspondant à son type, avec ce que l'API en a dit. Toute exception levée par le client est une OpenEmailException non vérifiée : un seul catch les couvre donc toutes.
| Méthode | Ce qu'il contient |
|---|---|
| status() | Le statut HTTP, ou 0 quand aucune réponse n'est arrivée. |
| type(), code() | Le type d'erreur et le code de l'API, comme validation_error et invalid_parameter. |
| param() | Le champ en cause, quand il y en a un. |
| requestId() | L'identifiant à citer quand vous écrivez au support. |
| docUrl() | La page de la documentation qui explique le code. |
| retryAfterSeconds() | Le temps d'attente que l'API vous a demandé. |
| fields() | Les champs qu'un formulaire d'inscription a refusés, chacun avec une key et une error. |
| body() | Le corps de la réponse, décodé. |
Les genres d'échec
| Exception | Quand elle est levée |
|---|---|
| AuthenticationException | La clé ou le jeton a été refusé, avec un 401. |
| PermissionException | L'identifiant n'a pas le droit de faire cela, avec un 403. |
| NotFoundException | Rien ne porte cet identifiant, avec un 404. |
| ConflictException | Le changement entre en conflit avec l'état actuel, avec un 409. |
| ValidationException | Un champ a été refusé, avec un 422. |
| RateLimitException | Trop de requêtes, ou un quota est épuisé, avec un 429. |
| InvalidRequestException | Tout autre refus de la requête. |
| ApiException | L'API a échoué, avec un statut de 500 ou plus. |
| NetworkException | Aucune réponse n'est arrivée. |
| IllegalArgumentException | L'appel lui-même était erroné, et rien n'a été envoyé. |
| WebhookSignatureException | Une livraison de webhook a échoué à sa vérification. |
Une ApiException répond aussi à des questions sur elle-même : isValidation(), isNotFound(), isRateLimited(), isServerError() et isRetryable(), avec isScopeMissing() quand il manque à l'identifiant la portée dont l'appel a besoin et isStepUpRequired() quand un jeton d'accès doit d'abord vérifier un code. NetworkException.isTimeout() indique que le délai est dépassé.
Ce qui est retenté
- Les lectures, les envois et toute écriture qui peut être répétée sans risque sont retentés, jusqu'à
maxRetriesfois. Toute autre écriture est envoyée une seule fois. - Les statuts 408, 500, 502, 503 et 504 sont retentés avec une attente qui commence à une demi-seconde et double jusqu'à huit secondes.
- Un 429 n'est retenté que s'il porte un
Retry-Afterd'une minute ou moins, et le client attend ce temps. - Une connexion qui échoue ou qui dépasse le délai est retentée de la même façon.
Un envoi retenté porte chaque fois la même clé d'idempotence : l'API rejoue donc le premier message au lieu d'en envoyer un second.