PhpDev.App
leocarmo/circuit-breaker-php

leocarmo/circuit-breaker-php

Stars: 263

Forks: 20

Pull Requests: 16

Issues: 1

Watchers: 4

Last Updated: 2022-12-16 12:30:58

Circuit Breaker Pattern for PHP

License:

Languages: PHP, Makefile, Dockerfile

PHP implementation of Circuit Breaker Pattern

Build Status Scrutinizer Code Quality Code Intelligence Status Total Downloads

For more information about this pattern see this.

Starting with composer

composer require leocarmo/circuit-breaker-php

Adapters

Redis Adapter

The first argument is a redis connection, the second is your product name, for redis namespace avoid key conflicts with another product using the same redis.

use LeoCarmo\CircuitBreaker\CircuitBreaker;
use LeoCarmo\CircuitBreaker\Adapters\RedisAdapter;

// Connect to redis
$redis = new \Redis();
$redis->connect('localhost', 6379);

$adapter = new RedisAdapter($redis, 'my-product');

// Set redis adapter for CB
$circuit = new CircuitBreaker($adapter, 'my-service');

See this for full example

Redis Cluster Adapter

Without use of multi command. The first argument is a redis connection, the second is your product name, for redis namespace avoid key conflicts with another product using the same redis.

use LeoCarmo\CircuitBreaker\CircuitBreaker;
use LeoCarmo\CircuitBreaker\Adapters\RedisClusterAdapter;

// Connect to redis
$redis = new \Redis();
$redis->connect('localhost', 6379);

$adapter = new RedisClusterAdapter($redis, 'my-product');

// Set redis adapter for CB
$circuit = new CircuitBreaker($adapter, 'my-service');

See this for full example

SwooleTable Adapter

use LeoCarmo\CircuitBreaker\CircuitBreaker;

$circuit = new CircuitBreaker(new SwooleTableAdapter(), 'my-service');

Guzzle Middleware

use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use LeoCarmo\CircuitBreaker\GuzzleMiddleware;

$handler = new GuzzleMiddleware($circuit);

$handlers = HandlerStack::create();
$handlers->push($handler);

$client = new Client(['handler' => $handlers]);

$response = $client->get('leocarmo.dev');

Important: all status code between 200 and 299 will be recorded as a success, and other status will be recorded as a failure.

See this for full example

Customize success status code

If you need to specify a custom status code that is not a failure, you can use:

$handler = new GuzzleMiddleware($circuit);
$handler->setCustomSuccessCodes([400]);

Important: this configuration will record a success when a status code 400 is returned

See this for full example

Ignore status code

If you want to ignore the status code returned and not record a success or failure, use this:

$handler = new GuzzleMiddleware($circuit);
$handler->setCustomIgnoreCodes([412]);

Set circuit break settings

This is not required, default values will be set

$circuit->setSettings([
    'timeWindow' => 60, // Time for an open circuit (seconds)
    'failureRateThreshold' => 50, // Fail rate for open the circuit
    'intervalToHalfOpen' => 30,  // Half open time (seconds)
]);

Check if circuit is available (closed)

Each check is for a specific service. So you can have multiple services in the same application, and when one circuit is open, the other works normally.

// Check circuit status for service
if (! $circuit->isAvailable()) {
    die('Circuit is not available!');
}

Record success and failure

// Usage example for success and failure  
try {
    myService();
    $circuit->success();
} catch (RuntimeException $e) {
    // If an error occurred, it must be recorded as failure.
    $circuit->failure();
}

Development

Setup

make setup

Tests

make test 

Contributors