Articles

Che cos’è un’operazione idempotente?

Introduzione

In questo articolo, vedremo cos’è un’operazione idempotente, perché idempotency è utile e vedremo idempotency in REST.

Che cos’è l’idempotenza?

In poche parole, possiamo eseguire un’operazione idempotente più volte senza modificare il risultato.

Inoltre, l’operazione non deve causare effetti collaterali dopo la prima esecuzione riuscita.

Diamo un’occhiata a due semplici esempi.

2.1. Valore assoluto

Una funzione che restituisce il valore assoluto è idempotente; non importa quanto spesso lo applichiamo allo stesso numero, restituisce sempre lo stesso risultato.

si consideri la funzione:

Allora è vero quanto segue:

Esempio:

al contrario, una funzione che inverte il segno di un numero non è idempotente:

Quindi:

Esempio:

2.2. Update Address

Un altro esempio pratico di un’operazione idempotente sarebbe quello di aggiornare i dettagli di contatto di un utente nel sistema. Diciamo che aggiorniamo solo il numero di telefono. L’effetto collaterale di questo aggiornamento è che inviamo un messaggio di testo con un codice di verifica al nuovo numero. Abbiamo tre possibili scenari:

  • Il primo messaggio di aggiornamento è stato elaborato con successo, il numero è stato aggiornato nel sistema e il messaggio di testo è stato inviato. Quando il messaggio di aggiornamento viene inviato di nuovo, non accadrà nulla. Inoltre, il messaggio di testo non viene inviato per la seconda volta.
  • Il primo aggiornamento non riesce. Il sistema non viene aggiornato e non viene inviato alcun messaggio di testo. Se il secondo aggiornamento ha esito positivo, il sistema viene aggiornato e viene inviato il messaggio di testo.
  • Il primo aggiornamento non riesce. Prima che venga inviato un altro aggiornamento, l’utente viene disattivato nel sistema. Poiché lo stato del sistema è cambiato, un secondo aggiornamento del numero di telefono non influisce.

Perché Idempotenza?

Idempotence garantisce che la stessa richiesta porti allo stesso stato del sistema e che nessuna azione venga eseguita involontariamente più di una volta.

Ad esempio, diamo un’occhiata a una richiesta del mittente S per inviare denaro tramite un servizio di pagamento PS al destinatario R.

3.1. Esempio non idempotente

Ecco la versione non idempotente della richiesta:

Al primo tentativo, S invia una richiesta per inviare send 10 a R. PS riceve i messaggi; tuttavia, il trasferimento effettivo fallisce. PS invia restituisce un messaggio di errore a S che non riceve il messaggio a causa di un errore di rete.

S non sa se il trasferimento ha avuto successo, quindi ci riprova. Questa volta il trasferimento a R ha esito positivo e PS invia un messaggio di conferma a S. Di nuovo, la conferma non riesce e S non sa se il trasferimento è andato a buon fine o meno.

Pertanto, ci prova per la terza volta. PS riceve il messaggio, lo considera una nuova richiesta, invia il denaro a R e restituisce una conferma a S.

Questa non è una richiesta idempotente perché intendevamo riprovare lo stesso pagamento e non inviarlo due volte.

3.2. Idempotence Key

I pagamenti sono un buon esempio per illustrare perché idempotence è utile. Nell’esempio precedente, abbiamo visto che il pagamento a R viene eseguito più volte perché S si ritira senza sapere che il trasferimento ha già avuto successo.

Se l’operazione fosse stata idempotente, questo non sarebbe stato il caso. Ma come fa PS a sapere che S ha appena ritentato lo stesso pagamento e non vuole inviare un secondo pagamento di S 10 a S?

Per ottenere ciò, S include una chiave di idempotenza nella sua richiesta a PS. Questa chiave può essere, ad esempio, è un UUID. Se PS riceve una richiesta con la stessa chiave idempotence, sa che si tratta di un nuovo tentativo. Se non ha visto la chiave prima, sa che si tratta di una nuova richiesta.

Diamo un’occhiata alla versione idempotente dell’esempio precedente:

Qui, il primo tentativo e il primo tentativo sono gli stessi della versione non idempotente, tranne che la richiesta include la chiave idempotence (65TH68M5 nel nostro esempio).

La differenza importante è il secondo tentativo: PS riceve il messaggio, rileva che un messaggio con la stessa chiave di idempotenza è già stato elaborato correttamente e restituisce una conferma a S senza inviare nuovamente il denaro a R.

Qui, il vantaggio di idempotency è che S può riprovare tutte le volte che vuole senza doversi preoccupare di un doppio pagamento. PS non deve preoccuparsi che S riceva la conferma, poiché sa che S può riprovare nel caso in cui non abbia ricevuto il messaggio.

Lo svantaggio di questo approccio è che PS deve memorizzare tutte le chiavi ricevute. Questo potrebbe andare bene se non ci sono molte richieste; tuttavia, se la frequenza della richiesta è molto alta, potrebbe essere problematica. Una soluzione può essere quella di scadere la chiave idempotence dopo un po ‘ di tempo.

Idempotenza e RIPOSO

4.1. Panoramica

Diamo una breve occhiata a come l’idempotenza si applica ai verbi HTTP, che sono importanti per capire quando vogliamo costruire un’API REST. Un riferimento molto dettagliato di tutti i verbi HTTP può essere trovato in RFC 7231.

La seguente tabella mostra quali verbi sono (o dovrebbero essere) idempotenti.

4.2. Le operazioni Idempotenti

GET, HEAD e OPTION sono chiaramente idempotenti in quanto leggono solo i dati, ma non creano, aggiornano o eliminano alcuna risorsa.

PUT è idempotente in quanto aggiorna una risorsa o ne crea una nuova se non esiste. Se abbiamo inviato lo stesso aggiornamento più volte, la risorsa non dovrebbe cambiare.

4.3. Operazioni non idempotenti

POST non deve essere idempotente in quanto crea una nuova risorsa e, se richiamata, di solito crea un’altra risorsa. Tuttavia, può essere implementato anche come operazione idempotente.

L’operazione PATCH aggiorna parzialmente una risorsa e non deve necessariamente essere idempotente. Diamo un’occhiata ad un esempio per capire meglio la differenza tra PUT e PATCH:

Diciamo che vogliamo aggiungere un articolo a un carrello in un negozio online. Se usiamo PUT, abbiamo bisogno di inviare i dati completi del carrello, compresi tutti gli articoli che sono già nel carrello. Con PATCH, possiamo inviare solo l’articolo da aggiungere, e verrà aggiunto alla lista degli articoli già nel carrello.

Se inviamo di nuovo la richiesta di PATCH, lo stesso elemento verrà aggiunto di nuovo. Naturalmente, per quanto riguarda POST, possiamo implementare anche una PATCH idempotente.

4.4. Risposta HTTP

È importante notare che diverse chiamate a un’operazione idempotente non comportano necessariamente la stessa risposta HTTP.

PUT, ad esempio, restituirà 201 (Creato) se viene creata una risorsa, o 200 (OK) o 203 (Nessun contenuto) se una risorsa è stata aggiornata.

Un’ELIMINAZIONE, ad esempio, può restituire 200 (OK) o 204 (Nessun contenuto) quando avviene un’eliminazione effettiva. Eventuali chiamate successive restituiranno 404 (Non trovato).

Conclusione

In questo articolo, abbiamo visto cosa significa idempotenza, quali sono i vantaggi di idempotenza e come si riferisce al RIPOSO.

Anche se il significato generale di idempotence è facile da capire, può essere abbastanza difficile considerare tutte le sottigliezze come gli effetti collaterali e le risposte HTTP durante la progettazione di un’API.