The retry function attempts to execute the given callback until the given maximum attempt threshold is met. If the callback does not throw an exception, its return value will be returned. If the callback throws an exception, it will automatically be retried. If the maximum attempt count is exceeded, the exception will be thrown:
return retry(5, function () {
}, 
100);
        $shouldRetry null;



        return 
retry($this->tries ?? 1, function ($attempt) use ($method$url$options, &$shouldRetry) {

            try {

                return 
tap(new Response($this->sendRequest($method$url$options)), function ($response) use ($attempt, &$shouldRetry) {

                    
$this->populateResponse($response);



                    
$this->dispatchResponseReceivedEvent($response);



                    if (! 
$response->successful()) {

                        try {

                            
$shouldRetry $this->retryWhenCallback call_user_func($this->retryWhenCallback$response->toException(), $this) : true;

                        } catch (
Exception $exception) {

                            
$shouldRetry false;



                            throw 
$exception;

                        }



                        if (
$this->throwCallback) {

                            
$response->throw($this->throwCallback);

                        }



                        if (
$attempt $this->tries && $shouldRetry) {

                            
$response->throw();

                        }



                        if (
$this->tries && $this->retryThrow) {

                            
$response->throw();

                        }

                    }

                });

            } catch (
ConnectException $e) {

                
$this->dispatchConnectionFailedEvent();



                throw new 
ConnectionException($e->getMessage(), 0$e);

            }

        }, 
$this->retryDelay ?? 100, function ($exception) use (&$shouldRetry) {

            
$result $shouldRetry ?? ($this->retryWhenCallback call_user_func($this->retryWhenCallback$exception$this) : true);



            
$shouldRetry null;



            return 
$result;

        });

    }
    {

        
$startTime microtime(true);



        
$attempts retry(2, function ($attempts) {

            if (
$attempts 1) {

                return 
$attempts;

            }



            throw new 
RuntimeException;

        }, 
100);




        
$this->assertEquals(2$attempts);
    {

        
$startTime microtime(true);



        
$attempts retry(3, function ($attempts) {

            if (
$attempts 2) {

                return 
$attempts;

            }



            throw new 
RuntimeException;

        }, function (
$attempt$exception) {

            
$this->assertInstanceOf(RuntimeException::class, $exception);



            return 
$attempt 100;

        });




        
$this->assertEquals(3$attempts);
    {

        
$startTime microtime(true);



        
$attempts retry(2, function ($attempts) {

            if (
$attempts 1) {

                return 
$attempts;

            }



            throw new 
RuntimeException;

        }, 
100, function ($ex) {

            return 
true;

        });




        
$this->assertEquals(2$attempts);
    {

        
$this->expectException(RuntimeException::class);



        
retry(2, function ($attempts) {

            if (
$attempts 1) {

                return 
$attempts;

            }



            throw new 
RuntimeException;

        }, 
100, function ($ex) {

            return 
false;

        });

    }



    public function 
testRetryWithBackoff()
    public function testRetryWithBackoff()

    {

        
$startTime microtime(true);

        
$attempts retry([50100200], function ($attempts) {

            if (
$attempts 3) {

                return 
$attempts;

            }



            throw new 
RuntimeException;

        });




        
$this->assertEquals(4$attempts);