PHP code example of gohany / circuitbreaker

1. Go to this page and download the library: Download gohany/circuitbreaker library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

gohany / circuitbreaker example snippets


use Gohany\Circuitbreaker\Core\CircuitBreaker;
use Gohany\Circuitbreaker\Core\CircuitKey;
use Gohany\Circuitbreaker\Core\CircuitContext;
use Gohany\Circuitbreaker\Policy\Http\DefaultHttpCircuitPolicy;

// 1. Choose a policy
$cfg = new \App\Circuit\Config\DefaultHttpConfig();
$policy = new DefaultHttpCircuitPolicy($cfg);

// 2. Setup the breaker
$breaker = new CircuitBreaker($stateStore, $historyStore, $policy, $classifier);

// 3. Execute your action
$result = $breaker->execute(
    new CircuitKey('my-action-key'), 
    new CircuitContext(), 
    function () {
        // Your risky logic here: DB, API, internal call, etc.
        return do_something_risky();
    }
);

$result = $breaker->execute($key, $context, function () use ($fraudClient, $payload) {
    return $fraudClient->score($payload);
});

namespace App\Circuit\Config;

use Gohany\Circuitbreaker\Policy\Http\HttpCircuitPolicyConfig;

final class DefaultHttpConfig extends HttpCircuitPolicyConfig
{
    public int $openDurationMs = 15_000;
    public int $halfOpenFailuresToOpen = 1;
}

final class PaymentsHttpConfig extends HttpCircuitPolicyConfig
{
    public int $openDurationMs = 60_000;
    public int $halfOpenFailuresToOpen = 2;
}

use Gohany\Circuitbreaker\Policy\Http\DefaultHttpCircuitPolicy;

$policy = new DefaultHttpCircuitPolicy(new \App\Circuit\Config\PaymentsHttpConfig());

use Gohany\Circuitbreaker\Policy\Http\DefaultHttpCircuitPolicy;
use Gohany\Circuitbreaker\Policy\Http\HttpCircuitPolicyConfig;

final class VendorXHttpConfig extends HttpCircuitPolicyConfig
{
    /**
     * Example intent:
     * - Treat `429` as a failure signal (open quickly if the vendor is rate-limiting hard)
     * - Treat `409` as non-failure (expected conflict)
     */
    public array $failureSignals = [
        'timeout',
        'connect_error',
        'dns',
        'http_5xx',
        'http_429',
    ];
}

$policy = new DefaultHttpCircuitPolicy(new VendorXHttpConfig());

$breaker->execute($key, $context, function () use ($fraudClient, $payload) {
    return $fraudClient->score($payload);
});

$myRtryPolicy = new \Gohany\Rtry\Impl\RtryPolicy();
$myRtryPolicy->setRetryDecider(new MyCustomDecider());

$breaker = new CircuitBreaker(
    // ...,
    retryExecutor: new RtryRetryExecutor($classifier),
    retryPolicyOrSpec: $myRtryPolicy
);

$breaker->execute($key, $context, function () use ($retryer) {
    return $retryer->run(function () {
        return $this->doOneAttempt();
    });
});

$resp = $breaker->execute($key, $context, function () use ($retryer, $http) {
    return $retryer->run(function () use ($http) {
        return $http->request('GET', 'https://crm.example.com/v1/customers/123');
    });
});

$key = bin2hex(random_bytes(16));

$resp = $breaker->execute($key, $context, function () use ($retryer, $http, $key) {
    return $retryer->run(function () use ($http, $key) {
        return $http->request('POST', 'https://pay.example.com/v1/charges', [
            'headers' => ['Idempotency-Key' => $key],
            'json' => [/* ... */],
        ]);
    });
});

$retryer = new Retryer(
    new DefaultHttpRetryPolicy(),
    new DefaultHttpRetryDecider(),
);

$response = $breaker->execute($key, $context, function () use ($retryer, $http) {
    return $retryer->run(function () use ($http) {
        return $http->request('GET', 'https://api.vendorx.com/v1/resource');
    });
});

$context = new CircuitContext(null, [
    'cb_bypass_deny_block' => true,
]);

$result = $breaker->execute($key, $context, $operation);

use Gohany\Circuitbreaker\Exception\CircuitDeniedException;
use Gohany\Circuitbreaker\Exception\ProbeGateBlockedException;

try {
    $result = $breaker->execute($key, $context, $operation);
} catch (CircuitDeniedException $e) {
    // Handle "fail-fast" by showing a cached result or a friendly error
    echo "Blocked: " . $e->getReason() . ". Try again in " . $e->getRetryAfterMs() . "ms";
} catch (ProbeGateBlockedException $e) {
    // Too many probes in flight
    echo "Probing in progress. Try again in " . $e->getRetryAfterMs() . "ms";
}