enl / retry-loop
Retry Loop 是一个用于广泛使用在失败代码重试概念的微型类
1.0.0
2017-09-29 14:40 UTC
Requires
- php: ~7.0
Requires (Dev)
- phpunit/phpunit: ^6.3
This package is auto-updated.
Last update: 2024-08-29 04:37:12 UTC
README
Retry Loop 是一个广泛使用且容易解释的概念,可以用“失败重试并在多次重试后放弃”来描述。
安装
composer require enl/retry-loop
用法
例如,我们需要将一些数据推送到远程服务,以下是一个伪代码示例
$response = $serviceClient->push($uri, $data);
但假设这个远程服务暂时不可用,或者在这个特定时刻网络连接不稳定呢?
常见的解决方案是使用 try-catch
。但多次重试怎么办?
这段代码看起来更好,而且效果也不错
$loop = new RetryLoop($retries = 5); $response = $loop->run(function() use ($serviceClient, $uri, $data) { return $serviceClient->push($uri, $data); });
放弃某些异常
有时,你需要放弃某些异常,例如,如果你的客户端抛出 'BadRequestException',你应该放弃尝试推送数据。为了实现这一点,你可以在 RetryLoop
构造函数中指定第二个参数
$loop = new RetryLoop($retries = 5, $giveUpAt = [BadRequestException::class]); $response = $loop->run(function() use ($serviceClient, $uri, $data) { return $serviceClient->push($uri, $data); });
在遇到 BadRequestException
时,RetryLoop
将抛出 LoopFailed
异常,并将实际异常作为前一个异常
重试前的钩子
如果你需要在重试之前执行某些操作(日志记录、重新连接等),只需使用 $beforeRetry
参数
$loop = new RetryLoop($retries = 5, $giveUpAt = [BadRequestException::class], function($e) { $this->log('info', 'Exception caught by retry loop, retrying: '.$e->getMessage()); }); $response = $loop->run(function() use ($serviceClient, $uri, $data) { return $serviceClient->push($uri, $data); });
RetryLoop 是不可变的!
RetryLoop 类本身是不可变的,不存储任何内部状态,除了构造函数提供的参数,因此你可以轻松地重用单个循环实例进行多次重试,如果需要的话
构建器
此外,还有一个 LoopBuilder
,它提供循环构建的流畅接口
$loop = RetryLoop::builder ->retries(5) ->giveUpAt(BadRequestException::class) ->giveUpAt(SomeOtherException::class) ->giveUpAt([YetAnotherException::class]) ->beforeRetry(function() { sleep(5); }) ->get(); // or just `run` and get result if builder is not needed after that.