Метод retry повторює запит при помилці:
Http::retry(3, 200)->get($url); // 3 спроби, 200 мс між ними
Http::retry([100, 500, 2000])->get($url); // затримки по черзі
Http::retry(4, fn (int $attempt) => 2 ** $attempt * 100)->get($url); // експоненційно
Сигнатура: retry(array|int $times, Closure|int $sleepMilliseconds = 0, ?callable $when = null, bool $throw = true).
Третій аргумент - коли повторювати. За замовчуванням повтор іде при будь-якій помилці - і клієнтській (4xx), і серверній. Це рідко правильно:
use Illuminate\Http\Client\ConnectionException;
use Illuminate\Http\Client\PendingRequest;
use Illuminate\Http\Client\RequestException;
Http::retry(3, 300, function (Throwable $exception, PendingRequest $request) {
if ($exception instanceof ConnectionException) {
return true; // мережа, тайм-аут
}
return $exception instanceof RequestException
&& in_array($exception->response->status(), [429, 500, 502, 503, 504], true);
})->get($url);
Що повторювати: мережеві збої, тайм-аути, 502/503/504, 429 (краще з урахуванням Retry-After).
Що НЕ повторювати:
- 400, 404, 422 - повтор дасть ту саму відповідь;
- 401/403 - хіба що після оновлення токена: колбек може змінити запит (
$request->withToken($newToken)) і повернутиtrue; - неідемпотентні операції (
POSTна створення платежу, відправка SMS) без ключа ідемпотентності: таймаут не означає, що запит не дійшов - повтор може списати гроші двічі.
throw: false - після всіх спроб повернути останню відповідь замість винятку. Але ConnectionException кидається все одно, якщо всі спроби впали через з'єднання.
Повтори в запиті користувача vs у черзі:
- синхронно - лише короткі повтори (1-2 спроби, сотні мілісекунд): користувач чекає, а процес PHP зайнятий;
- у джобі - довгі затримки краще віддати черзі (
$tries,backoff()): джоба звільняє воркер між спробами, а не спить уusleep.
Не множити повтори. Http::retry(3) всередині джоби з $tries = 5 - до 15 запитів на одну операцію, а з повторами на рівні проксі чи SDK - ще більше. Кожен рівень, що повторює, - вирішується свідомо.
Випадковий розкид затримки (jitter) для масових інтеграцій - щоб сотні джоб після збою провайдера не вдарили по ньому одночасно.