syastrebov / circuit-breaker-bundle
Symfony bundle for circuit breaker wrapper.
Package info
github.com/syastrebov/circuit-breaker-bundle
pkg:composer/syastrebov/circuit-breaker-bundle
Requires
- php: ^8.3
- syastrebov/circuit-breaker: ^0.0.9
- symfony/config: ^7.4 || ^8.0
- symfony/dependency-injection: ^7.4 || ^8.0
- symfony/http-kernel: ^7.4 || ^8.0
Requires (Dev)
- ext-memcached: *
- ext-redis: *
- doctrine/dbal: ^4.4
- doctrine/doctrine-bundle: ^2.18
- doctrine/doctrine-migrations-bundle: ^3.7
- doctrine/orm: ^3.6
- monolog/monolog: ^3.10
- nyholm/symfony-bundle-test: ^3.1
- phpstan/phpstan: ^2.1
- predis/predis: ^3.3
- squizlabs/php_codesniffer: ^4.0
- symfony/framework-bundle: ^7.4 || ^8.0
- symfony/monolog-bundle: ^4.0
- symfony/phpunit-bridge: ^8.0
- symfony/test-pack: ^1.2
- vimeo/psalm: ^6.15
This package is not auto-updated.
Last update: 2026-03-06 16:03:48 UTC
README
PHP Circuit Breaker implementation for microservices and API calls.
A Symfony bundle for the https://github.com/syastrebov/circuit-breaker library.
Install
If you're using flex add to your composer.json
{
...
"extra": {
"symfony": {
"endpoint": [
"https://api.github.com/repos/syastrebov/recipies/contents/index.json",
"flex://defaults"
]
}
}
}
Install via composer
composer require syastrebov/circuit-breaker-bundle
Config
Supported Providers
Database
config/packages/doctrine.yaml
doctrine: dbal: default_connection: default connections: default: driver: pdo_sqlite path: ':memory:' secondary: driver: pdo_mysql host: mysql user: user password: password dbname: database
config/packages/circuit_breaker.yaml
circuit_breaker: driver: database connections: database: connection: secondary
Memcached
config/packages/circuit_breaker.yaml
circuit_breaker: driver: memcached connections: memcached: servers: # Uses default port - host: memcached-1 # Explicitly define port - host: memcached-2 port: 11211
Redis
Uses redis extension or predis as fallback.
config/packages/circuit_breaker.yaml
circuit_breaker: driver: redis connections: redis: host: redis port: 6379 username: username password: password
Redis Cluster
Uses redis extension or predis as fallback.
config/packages/circuit_breaker.yaml
circuit_breaker: driver: redis connections: redis: nodes: # Uses default port - host: redis-node-1 - host: redis-node-2 # Explicitly define port - host: redis-node-3 port: 6379 password: password
Predis
To force Predis usage despite the redis extension being installed:
config/packages/circuit_breaker.yaml
circuit_breaker: driver: predis
Memory
config/packages/circuit_breaker.yaml
circuit_breaker: driver: memory
Multiple Instances
config/packages/circuit_breaker.yaml
circuit_breaker: configurations: default: retries: 3 closed_threshold: 3 half_open_threshold: 3 retry_interval: 1000 open_timeout: 60 fallback_or_null: false api: retries: 2 closed_threshold: 5 half_open_threshold: 10 retry_interval: 2000 open_timeout: 120 fallback_or_null: true
use CircuitBreaker\Contracts\CircuitBreakerInterface; public function requestDefault( #[Autowire(service: 'circuit_breaker.default')] CircuitBreakerInterface $circuit ): string { // handle request } public function requestApi( #[Autowire(service: 'circuit_breaker.api')] CircuitBreakerInterface $circuit ): string { // handle request }
Logger
circuit_breaker: logger: monolog.logger.circuit_breaker
Usage
Simple example:
use CircuitBreaker\Contracts\CircuitBreakerInterface; public function request(CircuitBreakerInterface $circuit): string { try { return $circuit->run('test', function () { return '{"response": "data"}'; }); } catch (UnableToProcessException $e) { // handle exception } }
Use custom config:
use CircuitBreaker\Contracts\CircuitBreakerInterface; public function request( #[Autowire(service: 'circuit_breaker.api')] CircuitBreakerInterface $circuit ): string { try { return $circuit->run('test', function () { return '{"response": "data"}'; }); } catch (UnableToProcessException $e) { // handle exception } }
Stub response:
use CircuitBreaker\Contracts\CircuitBreakerInterface; public function request( #[Autowire(service: 'circuit_breaker.api')] CircuitBreakerInterface $circuit ): string { return $circuit->run( '{endpoint}', static function () { return (string) (new Client)->get('https://domain/api/{endpoint}')->getBody(); }, static function () { return json_encode([ 'data' => [ 'key' => 'default value', ], ]); } ); }
Cacheable response:
Configure a cache pool to be able to use cacheable circuit breaker.
config/packages/framework.yaml
framework: cache: pools: circuit_breaker.pool: adapter: cache.adapter.filesystem
config/packages/circuit_breaker.yaml
circuit_breaker: provider: memory cache_pool: circuit_breaker.pool configurations: api: retries: 2 closed_threshold: 5 half_open_threshold: 10 retry_interval: 3000 open_timeout: 120 fallback_or_null: true
Use .cacheable suffix to use CacheableCircuitBreaker.
use CircuitBreaker\Contracts\CircuitBreakerInterface; public function request( #[Autowire(service: 'circuit_breaker.api.cacheable')] CircuitBreakerInterface $circuit ): string { return $circuit->run('{endpoint}', static function () { return (string) (new Client)->get('https://domain/api/{endpoint}')->getBody(); }); }