philiprehberger/php-circuit-breaker 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

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

philiprehberger/php-circuit-breaker

最新稳定版本:v1.3.0

Composer 安装命令:

composer require philiprehberger/php-circuit-breaker

包简介

Circuit breaker pattern with configurable thresholds and multiple storage backends

README 文档

README

Tests Latest Version on Packagist Last updated

Circuit breaker pattern with configurable thresholds and multiple storage backends.

Requirements

  • PHP 8.2+

Installation

composer require philiprehberger/php-circuit-breaker

Usage

Basic Usage

use PhilipRehberger\CircuitBreaker\CircuitBreaker;
use PhilipRehberger\CircuitBreaker\CircuitConfig;
use PhilipRehberger\CircuitBreaker\Storage\InMemoryStorage;

$breaker = new CircuitBreaker(
    service: 'payment-api',
    config: new CircuitConfig(
        failureThreshold: 5,
        recoveryTimeout: 30,
        successThreshold: 1,
    ),
    storage: new InMemoryStorage(),
);

$result = $breaker->call(function () {
    return file_get_contents('https://api.example.com/charge');
});

Fluent Builder

use PhilipRehberger\CircuitBreaker\CircuitBreaker;
use PhilipRehberger\CircuitBreaker\Storage\FileStorage;

$breaker = CircuitBreaker::for('payment-api')
    ->failAfter(3)
    ->recoverAfter(60)
    ->storage(new FileStorage('/tmp/circuits'))
    ->onStateChange(function ($event, $breaker) {
        echo "Circuit event: {$event->value}\n";
    })
    ->build();

try {
    $result = $breaker->call(fn () => callExternalService());
} catch (\PhilipRehberger\CircuitBreaker\CircuitOpenException $e) {
    // Circuit is open, use fallback
}

Per-Key Circuit Breakers

Use KeyedCircuitBreaker to manage independent circuit breakers per key:

use PhilipRehberger\CircuitBreaker\KeyedCircuitBreaker;
use PhilipRehberger\CircuitBreaker\CircuitConfig;
use PhilipRehberger\CircuitBreaker\Storage\InMemoryStorage;

$breakers = new KeyedCircuitBreaker(
    config: new CircuitConfig(failureThreshold: 3, recoveryTimeout: 60),
    storage: new InMemoryStorage(),
);

$userResult  = $breakers->call('user-api',  fn () => fetchUsers());
$orderResult = $breakers->call('order-api', fn () => fetchOrders());

Fallback

Register a fallback to return a default value when the circuit is open instead of throwing:

$breaker = CircuitBreaker::for('payment-api')
    ->failAfter(3)
    ->recoverAfter(60)
    ->fallback(fn () => ['status' => 'unavailable'])
    ->build();

// Returns the fallback value when the circuit is open
$result = $breaker->call(fn () => callExternalService());

Health Check Probes

Register a health check probe for smarter recovery from the Open state:

$breaker = new CircuitBreaker(
    service: 'payment-api',
    config: new CircuitConfig(failureThreshold: 3, recoveryTimeout: 30),
);

$breaker->setHealthCheck(function (): bool {
    // Check if the external service is reachable
    return @file_get_contents('https://api.example.com/health') !== false;
});

When the recovery timeout elapses, the health check runs before transitioning to HalfOpen. If the probe fails, the recovery timer resets.

Metrics

Inspect detailed metrics about circuit breaker usage:

$breaker = new CircuitBreaker('payment-api');

$breaker->call(fn () => fetchData());

$metrics = $breaker->metrics();
// [
//     'total_calls'          => 1,
//     'successful_calls'     => 1,
//     'failed_calls'         => 0,
//     'success_rate'         => 1.0,
//     'current_state'        => 'closed',
//     'state_changed_at'     => null,
//     'consecutive_failures' => 0,
// ]

Stats

Inspect circuit breaker usage statistics at any time:

$breaker = new CircuitBreaker('payment-api');

$breaker->call(fn () => fetchData());

$stats = $breaker->getStats();
// [
//     'total_calls'     => 1,
//     'successes'       => 1,
//     'failures'        => 0,
//     'last_failure_at' => null,
//     'current_state'   => 'closed',
// ]

Custom Storage Backend

use PhilipRehberger\CircuitBreaker\Contracts\Storage;
use PhilipRehberger\CircuitBreaker\CircuitState;

class RedisStorage implements Storage
{
    public function getState(string $service): CircuitState { /* ... */ }
    public function setState(string $service, CircuitState $state): void { /* ... */ }
    public function incrementFailures(string $service): int { /* ... */ }
    public function resetFailures(string $service): void { /* ... */ }
    public function getFailureCount(string $service): int { /* ... */ }
    public function getLastFailureTime(string $service): ?float { /* ... */ }
    public function setLastFailureTime(string $service, float $time): void { /* ... */ }
}

API

CircuitBreaker

Method Description
new CircuitBreaker(string $service, CircuitConfig $config, Storage $storage) Create a circuit breaker
CircuitBreaker::for(string $service) Create a fluent builder
->call(callable $fn): mixed Execute a callable through the circuit breaker
->isOpen(): bool Check if the circuit is open
->isClosed(): bool Check if the circuit is closed
->isHalfOpen(): bool Check if the circuit is half-open
->state(): CircuitState Get the current circuit state
->reset(): void Reset the circuit to closed
->trip(): void Manually open the circuit
->getStats(): array Get usage statistics (total calls, successes, failures, last failure timestamp, current state)
->metrics(): array Get detailed metrics (total, successful, failed calls, success rate, state, state change time, consecutive failures)
->setFallback(callable $fallback): void Register a fallback invoked when the circuit is open
->setHealthCheck(callable $probe): self Register a health check probe for smarter Open-to-HalfOpen recovery

CircuitBreakerBuilder

Method Description
->failAfter(int $failures): self Set the failure threshold
->recoverAfter(int $seconds): self Set the recovery timeout
->succeedAfter(int $successes): self Set the success threshold for half-open
->timeout(float $seconds): self Set the call timeout
->storage(Storage $storage): self Set the storage backend
->fallback(callable $fallback): self Register a fallback for when the circuit is open
->onStateChange(callable $callback): self Set a state change callback
->build(): CircuitBreaker Build the configured instance

KeyedCircuitBreaker

Method Description
new KeyedCircuitBreaker(CircuitConfig $config, Storage $storage) Create a keyed circuit breaker manager
->call(string $key, callable $fn): mixed Execute through the breaker for the given key
->state(string $key): CircuitState Get the state for a specific key
->isOpen(string $key): bool Check if the circuit for a key is open
->isClosed(string $key): bool Check if the circuit for a key is closed
->isHalfOpen(string $key): bool Check if the circuit for a key is half-open
->reset(string $key): void Reset the circuit for a specific key
->trip(string $key): void Manually open the circuit for a specific key
->remove(string $key): void Remove the breaker for a key entirely
->keys(): string[] Get all tracked keys
->count(): int Get the number of tracked keys

CircuitConfig

Parameter Type Default Description
failureThreshold int 5 Failures before opening
recoveryTimeout int 30 Seconds before half-open transition
successThreshold int 1 Successes in half-open to close
timeout ?float null Optional call timeout in seconds

Storage Backends

Class Description
InMemoryStorage In-memory, scoped to the current process
FileStorage JSON file-based, persists across requests
SlidingWindowStorage Time-window-based failure tracking with automatic pruning

Development

composer install
vendor/bin/phpunit
vendor/bin/pint --test

Support

If you find this project useful:

Star the repo

🐛 Report issues

💡 Suggest features

❤️ Sponsor development

🌐 All Open Source Projects

💻 GitHub Profile

🔗 LinkedIn Profile

License

MIT

统计信息

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

GitHub 信息

  • Stars: 1
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-03-15

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固