Articles

¿Qué es una operación Idempotente?

Introducción

En este artículo, veremos qué es una operación idempotente, por qué la idempotencia es útil, y veremos la idempotencia en REST.

¿Qué Es la Idempotencia?

en pocas palabras, podemos realizar una operación idempotente varias veces sin cambiar el resultado.

Además, la operación no debe causar ningún efecto secundario después de la primera ejecución exitosa.

veamos dos ejemplos sencillos.

2.1. Valor absoluto

Una función que devuelve el valor absoluto es idempotente; no importa con qué frecuencia lo apliquemos al mismo número, siempre devuelve el mismo resultado.

consideremos la función:

Entonces se cumple lo siguiente:

Ejemplo:

En contraste, una función que invierte el signo de un número no es idempotente:

a Continuación:

Ejemplo:

2.2. Actualizar dirección

Otro ejemplo práctico de una operación idempotente sería actualizar los datos de contacto de un usuario en el sistema. Digamos que actualizamos sólo el número de teléfono. El efecto secundario de esta actualización es que enviamos un mensaje de texto con un código de verificación al nuevo número. Tenemos tres escenarios posibles:

  • El primer mensaje de actualización se procesó correctamente, el número se actualizó en el sistema y se envió el mensaje de texto. Cuando el mensaje de actualización se envíe de nuevo, no pasará nada. Además, el mensaje de texto no se envía por segunda vez.
  • La primera actualización falla. El sistema no está actualizado y no se envía ningún mensaje de texto. Si la segunda actualización se realiza correctamente, el sistema se actualiza y se envía el mensaje de texto.
  • La primera actualización falla. Antes de enviar otra actualización, el usuario se desactiva en el sistema. Debido a que el estado del sistema ha cambiado, una segunda actualización del número de teléfono no afecta.

¿Por qué Idempotencia?

Idempotence garantiza que la misma solicitud conduzca al mismo estado del sistema y que ninguna acción se ejecute involuntariamente más de una vez.

Como ejemplo, veamos una solicitud del remitente S para enviar dinero a través de un servicio de pago PS al receptor R.

3.1. Ejemplo no Idempotente

Aquí está la versión no idempotente de la solicitud:

En el primer intento, S envía una solicitud para enviar $10 a R. PS recibe los mensajes; sin embargo, la transferencia real falla. PS sends devuelve un mensaje de error a S que no recibe ese mensaje debido a un fallo de red.

S no sabe si la transferencia se realizó correctamente, por lo que vuelve a intentarlo. Esta vez, la transferencia a R se realiza correctamente y PS envía un mensaje de confirmación a S. De nuevo, la confirmación falla y S no sabe si la transferencia se realizó correctamente o no.

Por lo tanto, lo intenta por tercera vez. PS recibe el mensaje, lo considera una nueva solicitud, envía el dinero a R y devuelve una confirmación a S.

Esta no es una solicitud idempotente porque pretendíamos reintentar el mismo pago y no enviarlo dos veces.

3.2. Clave de Idempotencia

Los pagos son un buen ejemplo para ilustrar por qué la idempotencia es útil. En el ejemplo anterior, hemos visto que el pago a R se ejecuta varias veces porque S se retira sin saber que la transferencia ya había sido exitosa.

Si la operación fue idempotente, este no habría sido el caso. Pero, ¿cómo sabe PS que S acaba de volver a intentar el mismo pago y no quiere enviar un segundo pago de $10 a S?

Para lograr esto, S incluye una clave de idempotencia en su solicitud a PS. Esta clave puede ser, por ejemplo, un UUID. Si PS recibe una solicitud con la misma clave de idempotencia, sabe que se trata de un reintento. Si no ha visto la llave antes, sabe que es una nueva solicitud.

Veamos la versión idempotente del ejemplo anterior:

Aquí, el primer intento y el primer reintento son los mismos que en la versión no idempotente, excepto que la solicitud incluye la clave idempotence (65TH68M5 en nuestro ejemplo).

La diferencia importante es el segundo reintento: PS recibe el mensaje, descubre que un mensaje con la misma clave de idempotencia ya se ha procesado correctamente y devuelve una confirmación a S sin enviar el dinero a R de nuevo.

Aquí, el beneficio de idempotency es que S puede reintentar tantas veces como quiera sin tener que preocuparse por un doble pago. PS no tiene que preocuparse de que S reciba la confirmación, ya que sabe que S puede volver a intentarlo en caso de que no haya recibido el mensaje.

La desventaja de este enfoque es que PS necesita almacenar todas las claves recibidas. Esto podría estar bien si no hay muchas solicitudes; sin embargo, si la frecuencia de solicitud es muy alta, podría ser problemática. Una solución puede ser caducar la clave de idempotencia después de algún tiempo.

Idempotencia y reposo

4.1. Descripción general

Veamos brevemente cómo se aplica idempotency a los verbos HTTP, que es importante entender cuando queremos construir una API REST. Una referencia muy detallada de todos los verbos HTTP se puede encontrar en el RFC 7231.

La siguiente tabla muestra qué verbos son (o deben ser) idempotentes.

4.2. Las operaciones idempotentes

GET, HEAD y OPTION son claramente idempotentes, ya que solo leen datos, pero no crean, actualizan ni eliminan ningún recurso.

PUT es idempotente, ya que actualiza un recurso o crea uno nuevo si no existe. Si enviamos la misma actualización varias veces, el recurso no debería cambiar.

4.3. No Idempotente Operaciones

POST no tiene que ser idempotente como se crea un nuevo recurso y, si se llama de nuevo, generalmente crea otro recurso. Sin embargo, también se puede implementar como una operación idempotente.

La operación de PARCHE actualiza un recurso parcialmente y no necesariamente tiene que ser idempotente. Veamos un ejemplo para entender mejor la diferencia entre PONER y PATCH:

Digamos que queremos agregar un artículo a un carrito de compras en una tienda en línea. Si usamos PUT, necesitamos enviar los datos completos del carrito de compras, incluidos todos los artículos que ya están en el carrito. Con el PARCHE, solo podemos enviar el artículo que se agregará, y se agregará a la lista de artículos que ya están en el carrito.

Si volvemos a enviar la solicitud de PARCHE, el mismo elemento se añadirá de nuevo. Por supuesto, en cuanto a POST, también podemos implementar un PARCHE idempotente.

4.4. Respuesta HTTP

Es importante tener en cuenta que varias llamadas a una operación idempotente no necesariamente dan como resultado la misma respuesta HTTP.

PUT, por ejemplo, devolverá 201 (Creado) si se crea un recurso, o 200 (OK) o 203 (Sin contenido) si se actualizó un recurso.

Una ELIMINACIÓN, por ejemplo, puede devolver 200 (Aceptar) o 204 (Sin contenido) cuando se realiza una eliminación real. Cualquier llamada posterior devolverá el número 404 (No encontrado).

Conclusión

En este artículo, vimos lo que significa idempotencia, cuáles son los beneficios de la idempotencia y cómo se relaciona con el DESCANSO.

Aunque el significado general de idempotencia es fácil de entender, puede ser bastante complicado considerar todas las sutilezas, como los efectos secundarios y las respuestas HTTP durante el diseño de una API.