Articles

Qu’est-ce qu’une opération Idempotente ?

Introduction

Dans cet article, nous verrons ce qu’est une opération idempotente, pourquoi l’idempotence est utile, et nous examinerons l’idempotence dans REST.

Qu’Est-Ce Que L’Idempotence ?

En termes simples, nous pouvons effectuer une opération idempotente plusieurs fois sans changer le résultat.

De plus, l’opération ne doit pas provoquer d’effets secondaires après la première exécution réussie.

Regardons deux exemples simples.

2.1. Valeur absolue

Une fonction qui renvoie la valeur absolue est idempotente ; peu importe la fréquence à laquelle nous l’appliquons au même nombre, elle renvoie toujours le même résultat.

Considérons la fonction:

Alors ce qui suit est vrai:

Exemple:

En revanche, une fonction qui retourne le signe d’un nombre n’est pas idempotente :

Alors :

Exemple:

2.2. Adresse de mise à jour

Un autre exemple pratique d’opération idempotente consisterait à mettre à jour les coordonnées d’un utilisateur dans le système. Disons que nous mettons à jour uniquement le numéro de téléphone. L’effet secondaire de cette mise à jour est que nous envoyons un message texte avec un code de vérification au nouveau numéro. Nous avons trois scénarios possibles :

  • Le premier message de mise à jour a été traité avec succès, le numéro a été mis à jour dans le système et le message texte a été envoyé. Lorsque le message de mise à jour est envoyé à nouveau, rien ne se passera. De plus, le message texte n’est pas envoyé une deuxième fois.
  • La première mise à jour échoue. Le système n’est pas mis à jour et aucun message texte n’est envoyé. Si la deuxième mise à jour réussit, le système est mis à jour et le message texte est envoyé.
  • La première mise à jour échoue. Avant l’envoi d’une autre mise à jour, l’utilisateur est désactivé dans le système. Étant donné que l’état du système a changé, une deuxième mise à jour du numéro de téléphone n’affecte pas.

Pourquoi l’idempotence ?

L’idempotence garantit que la même requête mène au même état du système et qu’aucune action n’est exécutée involontairement plus d’une fois.

A titre d’exemple, regardons une demande de l’expéditeur S d’envoyer de l’argent via un service de paiement PS au destinataire R.

3.1. Exemple non idempotent

Voici la version non idempotente de la requête :

Au premier essai, S envoie une requête pour envoyer110 à R. PS reçoit les messages ; cependant, le transfert réel échoue. PS sends renvoie un message d’erreur à S qui ne reçoit pas ce message en raison d’une panne de réseau.

S ne sait pas si le transfert a réussi, alors il essaie à nouveau. Cette fois, le transfert vers R est réussi et PS envoie un message de confirmation à S. Encore une fois, la confirmation échoue et S ne sait pas si le transfert a réussi ou non.

Par conséquent, il essaie pour la troisième fois. PS reçoit le message, le considère comme une nouvelle demande, envoie l’argent à R et renvoie une confirmation à S.

Ce n’est pas une demande idempotente car nous avions l’intention de réessayer le même paiement et de ne pas l’envoyer deux fois.

3.2. Clé d’idempotence

Les paiements sont un bon exemple pour illustrer pourquoi l’idempotence est utile. Dans l’exemple précédent, nous avons vu que le paiement à R est exécuté plusieurs fois car S se retire sans savoir que le transfert avait déjà réussi.

Si l’opération était idempotente, cela n’aurait pas été le cas. Mais comment PS sait-il que S vient de réessayer le même paiement et ne veut pas envoyer un deuxième paiement de 10 $ à S?

Pour ce faire, S inclut une clé d’idempotence dans sa requête à PS. Cette clé peut être, par exemple, un UUID. Si PS reçoit une requête avec la même clé d’idempotence, il sait qu’il s’agit d’une nouvelle tentative. S’il n’a pas vu la clé auparavant, il sait qu’il s’agit d’une nouvelle demande.

Regardons la version idempotente de l’exemple précédent:

Ici, le premier essai et la première tentative sont les mêmes que dans la version non idempotente, sauf que la requête inclut la clé idempotence (65TH68M5 dans notre exemple).

La différence importante est la deuxième tentative: PS reçoit le message, constate qu’un message avec la même clé d’idempotence a déjà été traité avec succès et renvoie une confirmation à S sans envoyer à nouveau l’argent à R.

Ici, l’avantage de l’idempotence est que S peut réessayer autant de fois qu’il le souhaite sans avoir à se soucier d’un double paiement. PS n’a pas à s’inquiéter que S reçoive la confirmation, car il sait que S peut réessayer au cas où il n’aurait pas reçu le message.

L’inconvénient de cette approche est que PS doit stocker toutes les clés reçues. Cela pourrait convenir s’il n’y a pas beaucoup de demandes; cependant, si la fréquence des demandes est très élevée, cela peut poser problème. Une solution peut être d’expirer la clé d’idempotence après un certain temps.

Idempotence et REPOS

4.1. Aperçu

Voyons brièvement comment l’idempotence s’applique aux verbes HTTP, qui sont importants à comprendre lorsque nous voulons construire une API REST. Une référence très détaillée de tous les verbes HTTP peut être trouvée dans la RFC 7231.

Le tableau suivant montre quels verbes sont (ou devraient être) idempotents.

4.2. Les opérations idempotentes

GET, HEAD et OPTION sont clairement idempotentes car elles ne lisent que les données, mais ne créent, ne mettent à jour ou ne suppriment aucune ressource.

PUT est idempotent car il met à jour une ressource ou en crée une nouvelle si elle n’existe pas. Si nous avons envoyé la même mise à jour plusieurs fois, la ressource ne devrait pas changer.

4.3. Opérations non idempotentes

POST n’a pas besoin d’être idempotent car il crée une nouvelle ressource et, s’il est appelé à nouveau, crée généralement une autre ressource. Cependant, il peut également être implémenté comme une opération idempotente.

L’opération de CORRECTIF met à jour partiellement une ressource et ne doit pas nécessairement être idempotente. Regardons un exemple pour mieux comprendre la différence entre le PUT et le PATCH:

Disons que nous voulons ajouter un article à un panier dans une boutique en ligne. Si nous utilisons PUT, nous devons envoyer les données complètes du panier, y compris tous les articles qui sont déjà dans le panier. Avec PATCH, nous ne pouvons envoyer que l’article à ajouter, et il sera ajouté à la liste des articles déjà dans le panier.

Si nous envoyons à nouveau la demande de PATCH, le même élément sera ajouté à nouveau. Bien sûr, comme pour POST, nous pouvons également implémenter un PATCH idempotent.

4.4. Réponse HTTP

Il est important de noter que plusieurs appels à une opération idempotente n’entraînent pas nécessairement la même réponse HTTP.

PUT, par exemple, renverra 201 (Créé) si une ressource est créée, ou 200 (OK) ou 203 (Pas de contenu) si une ressource a été mise à jour.

Une SUPPRESSION, par exemple, peut renvoyer 200 (OK) ou 204 (Pas de contenu) lorsqu’une suppression réelle a lieu. Tous les appels ultérieurs renverront le 404 (introuvable).

Conclusion

Dans cet article, nous avons vu ce que signifie l’idempotence, quels sont les avantages de l’idempotence et comment elle se rapporte au REPOS.

Même si la signification générale de l’idempotence est facile à comprendre, il peut être assez délicat de considérer toutes les subtilités comme les effets secondaires et les réponses HTTP lors de la conception d’une API.