La función `retry` de Laravel

A veces, especialmente al interactuar con APIs externas, nuestro código puede parecer no determinista. A veces funciona, y a veces no 🤦‍♀️.

En muchos casos, simplemente reintentar la llamada puede hacer que vuelva a funcionar (tal vez la API tenía mucha carga en ese momento o nos pasamos el límite de llamadas por segundo).

Afortunadamente para nosotros, Laravel tiene una función súper útil llamada retry. Teniendo el siguiente código:

foreach ($products as $product) {
	$response = Http::get('https://my-api.com/get-price', ['id' => $product->id])->throw()->json();
	$product->price = $response['price'];
}

Este código parece correcto y funcional pero, ¿qué pasa si my-api.com está temporalmente no disponible o con mucha carga? Para controlar mejor la situación podríamos usar la función retry, que reintentaría la llamada HTTP en caso de fallo. Tiene la siguiente estructura:

function retry(int $times, Callback $callback, int $delayInMs);

Por lo que podemos llamarla así:

foreach ($products as $product) {
	$response = retry(3, fn () => Http::get('https://my-api.com/get-price', ['id' => $product->id])->throw()->json(), 5000);
	$product->price = $response['price'];
}

En este caso, intentaríamos hacer la llamada API y, si se lanza una excepción (con el →throw()), lo reintentaría hasta 2 veces más esperando 5 segundos antes de cada reintento.

De hecho, es tan común usar esta función con las llamadas API que la clase Http ya la tiene directamente implementada:

foreach ($products as $product) {
	$response = Http::retry(3, 5000)->get('https://my-api.com/get-price', ['id' => $product->id])->throw()->json();
	$product->price = $response['price'];
}