PHP retry helper with capped exponential backoff

PHP
<?php
function retry(int $attempts, callable $fn, int $baseMs = 100, int $capMs = 5000): mixed
{
    if ($attempts < 1) throw new InvalidArgumentException('Attempts must be at least 1');
    $last = null;
    for ($i = 0; $i < $attempts; $i++) {
        try {
            return $fn($i);
        } catch (Throwable $e) {
            $last = $e;
            if ($i === $attempts - 1) break;
            $delay = min($capMs, $baseMs * (2 ** $i));
            usleep(random_int((int) ($delay / 2), $delay) * 1000);
        }
    }
    throw $last;
}