定制 ctroms/retryable 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

ctroms/retryable

Composer 安装命令:

composer require ctroms/retryable

包简介

Easily determine and retry fails requests with configuratble strategies

README 文档

README

Retryable is a package built for the Laravel framework that makes retrying failed requests a breeze.

Installation

composer install ctroms/retryable

Usage

Default Strategy

The quickest way to get started is by simply passing a callable with your request logic to retry(). By default, this uses an exponential backoff with constant jitter between 0 and 1000ms and a maximum delay of 64 seconds under the hood. Simply pass a callable with your retryable logic as the argument.

$response = Retry::retry(function () {
    return $this->client->request('GET', $url, $params);
});

Fluent Strategy Builder

The Retry object exposes a fluent interface that easily allows you to build a strategy for your retrayble request.

$response = Retry::errors(422)
                ->times(10)
                ->maxDelay(64000)
                ->base(1000)
                ->jitter(JitterStrategy::CONSTANT)
                ->backoff(BackoffStrategy::EXPONENTIAL)
                ->retry(function () {
                    return $this->client->request('GET', $url, $params);
                });
Method Description
errors() The status codes or exception messages to retry on
times() The maxumum number of times your request should be retried.
sleep() The maximum duration for a single delay
base() The base constant to be used for backoff and jitter strategies. Defaults to 1000ms if not specified
backoff() The strategy object that defines which backoff method you want to use
jitter() The strategy object that defines how to add jitter to the backoff strategy
retry() This method should be passed a callable that contains the logic of your request

Retry on Specific Errors

To specify errors that are retryable, use the errors() method. If this method is not specified the default errors are '422' and '5**' status codes.

Using a Status Code

$response = Retry::errors(422)
                ->retry(function () {
                    return $this->client->request('GET', $url, $params);
                });

Using an Exception Message

$response = Retry::errors('Something exception message we should retry on.')
                ->retry(function () {
                    return $this->client->request('GET', $url, $params);
                });

5** Status Codes

Since 500 errors usually need to be retried, you can use the string '5**' to match all 500 level error codes.

$response = Retry::errors('5**')
                ->retry(function () {
                    return $this->client->request('GET', $url, $params);
                });

Multiple Errors

To retry on multiple errors, simply pass an array of status codes and messages to the errors() method.

$response = Retry::errors([422,'5**', 'Something exception message we should retry on.'])
                ->retry(function () {
                    return $this->client->request('GET', $url, $params);
                });

Backoff

The backoff() method accepts one of three strings to define your backoff strategy.

Constant Strategy

$response = Retry::backoff(BackoffStrategy::CONSTANT)
                ->retry(function () {
                    $this->client->request('GET', $url, $params);
                });

Linear Backoff Strategy

$response = Retry::backoff(BackoffStrategy::LINEAR)
                ->retry(function () {
                    $this->client->request('GET', $url, $params);
                });

Exponential Backoff Strategy

$response = Retry::backoff(BackoffStrategy::EXPONENTIAL)
                ->retry(function () {
                    $this->client->request('GET', $url, $params);
                });

Limit the Number of Retry Attempts

To avoid retrying a down service indefinitely, you can set a max number of attempts with the times() method.

$response = Retry::times(10)
                ->retry(function () {
                    return $this->client->request('GET', $url, $params);
                });

Limit the Delay

To prevent your strategy from increaseing delays infinitely, you can limit the maximum delay with the maxDelay() method. Once this limit is reached each subsequent delay will not exceed the max delay defined.

Note that the units are in milliseconds. (E.g. 6000ms == 60s).

$response = Retry::maxDelay(6000)
                ->retry(function () {
                    return $this->client->request('GET', $url, $params);
                });

Sharp Knives Warning.

If you do not specify a max sleep time, the backoff delay will continue to increment infinitely. Similarly, if you do not specify a maximum number of tries, the request will continue to retry indefninitey.

Base

You can set a new base constant for the strategy with the base() method. The following example sets a base of 2 on the linearBackoff strategy. In this case the first attempt delays 2 seconds, the second 4 seconds, the third 6 seconds and so on.

$response = Retry::base(2000)
                ->retry(function () {
                    return $this->client->request('GET', $url, $params);
                });

Jitter

Generally, you'll want to apply jitter to your backoff strategy to avoid competing with other clients using the same retry strategy. The jitter() method accepts one of three strings to define your jitter strategy.

Constant Jitter Strategy

$response = Retry::jitter(JitterStrategy::CONSTANT)
                ->retry(function () {
                    $this->client->request('GET', $url, $params);
                });

Equal Jitter Strategy

$response = Retry::jitter(JitterStrategy::EQUAL)
                ->retry(function () {
                    $this->client->request('GET', $url, $params);
                });

Full Jitter Strategy

$response = Retry::jitter(JitterStrategy::FULL)
                ->retry(function () {
                    $this->client->request('GET', $url, $params);
                });

The following example creates a retryable request using the an exponential backoff with constant jitter, a base of 1s, a max delay of 64s and retries a maximum of 10 times.

$response = Retry::backoff(JitterStrategy::EXPONENTIAL)
                ->jitter(JitterStrategy::CONSTANT)
                ->base(1000)
                ->times(10)
                ->maxRetries(64000)
                ->retry(function () {
                    return $this->client->request('GET', $url, $params);
                });

Callable Strategies

In addition to the fluent strategy builder, you can pass a callable to the usingStrategy() method. This can be a callback or an object with an __invoke() method. The exception object is passed as the first argument and a retryable object is passed as the second argument.

The retryable object is a simple object that keeps track of the number of times your retry strategy has been called. You can get the retry attempts using the getRetryAttempts() method. Your callabel should always return a boolean.

$response = Retry::errors([422, '5**'])
        ->usingStrategy(function ($exception, $retryable) {
            if ($exception->getCode() == 422) {
                sleep(2);
            }
            if ($exception->getCode() >= 500) {
                sleep(4);
            }
            if ($retryable->getRetryAttempts > 5) {
                sleep(6);
            } 
        })->retry(function () {
            return $this->client->request('GET', $url, $params);
        });

Callable Deciders

If the logic needed to determine if a failed request should be retried is more complicated than matching a status code or error message, you can pass a callable to the usingDecider() method on the Retry object. The exception object is passed as the first argument and a retryable object is passed as the second argument.

$response = Retry::usingDecider(function ($exception, $retryable) {
    if ($exception->getCode() == 422) {
        return true;
    }
    if ($retryable->getRetryAttempts() > 5) {
        return false;
    }
    return false;
})->backoff(BackoffStrategy::CONSTANT)
->retry(function () {
    return $this->client->request('GET', $url, $params);
})

Credits

Thanks to Caleb Porzio for advice, contributions and for convincing me to build this in the first place.

ctroms/retryable 适用场景与选型建议

ctroms/retryable 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 197 次下载、GitHub Stars 达 6, 最近一次更新时间为 2018 年 04 月 13 日, 在 PHP 生态内属于活跃度较高的组件。

我们在过去多个企业项目中使用过 ctroms/retryable 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 ctroms/retryable 我们能提供哪些服务?
定制开发 / 二次开发

基于 ctroms/retryable 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 197
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 6
  • 点击次数: 0
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 6
  • Watchers: 3
  • Forks: 1
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2018-04-13