A robust Circuit Breaker implementation for Laravel applications.
composer require hot-panda/laravel-circuit-breakerThe package will automatically copy its configuration file to config/circuit-breaker.php during installation.
CIRCUIT_BREAKER_ENABLED=true
CIRCUIT_BREAKER_TIME_WINDOW=60
CIRCUIT_BREAKER_TOTAL_FAILURES=5
CIRCUIT_BREAKER_TIME_OUT_OPEN=60
CIRCUIT_BREAKER_TIME_OUT_HALF_OPEN=60
CIRCUIT_BREAKER_ADAPTER=redis
CIRCUIT_BREAKER_REDIS_CONNECTION=default
CIRCUIT_BREAKER_REDIS_PREFIX=CIRCUIT_BREAKERuse KonstantinBudylov\LaravelCircuitBreaker\Http\Client;
class ApiService
{
public function __construct(
private Client $httpClient
) {}
public function getUsers(): array
{
$response = $this->httpClient->get('https://api.example.com/users');
return $response->json();
}
public function createUser(array $data): array
{
$response = $this->httpClient->post('https://api.example.com/users', [
'json' => $data
]);
return $response->json();
}
}use KonstantinBudylov\LaravelCircuitBreaker\Facades\CircuitBreaker;
// Direct circuit breaker operations
CircuitBreaker::success('api-service');
CircuitBreaker::failed('api-service');
// HTTP client with circuit breaker
$response = CircuitBreaker::http('api-service')->get('https://api.example.com/data');// Using helper functions
$response = circuit_breaker_http('api-service')->get('https://api.example.com/data');
// Execute with circuit breaker protection
$result = with_circuit_breaker('api-service', function() {
return Http::get('https://api.example.com/data');
}, function() {
return ['fallback' => 'data'];
});
// Check circuit breaker status
$status = circuit_breaker_status('api-service');// In routes/web.php or routes/api.php
Route::middleware(['circuit-breaker:api-service'])->group(function () {
Route::get('/external-data', [DataController::class, 'fetch']);
});use KonstantinBudylov\LaravelCircuitBreaker\CircuitBreaker;
class ApiService
{
public function __construct(
private CircuitBreaker $circuitBreaker
) {}
public function callExternalApi(string $service): mixed
{
if (!$this->circuitBreaker->canPass($service)) {
throw new \Exception('Circuit breaker is open');
}
try {
$result = $this->makeApiCall($service);
$this->circuitBreaker->success($service);
return $result;
} catch (\Exception $e) {
$this->circuitBreaker->failed($service);
throw $e;
}
}
}If you're using the MySQL adapter, you'll need to create the database table. The package includes a migration that you can publish:
# Publish all assets and setup environment variables automatically
php artisan circuit-breaker:publish
# Run the migration (for MySQL adapter)
php artisan migrateThe MySQL adapter automatically cleans up expired records during operations. Unlike Redis which has built-in TTL expiration, the MySQL adapter includes cleanup logic in its methods to ensure expired records are removed when accessed.
The package automatically registers the CircuitBreakerServiceProvider when installed in a Laravel application.
The CircuitBreaker is registered as a singleton in the service container and can be injected into your classes:
use KonstantinBudylov\LaravelCircuitBreaker\CircuitBreaker;
class YourService
{
public function __construct(
private CircuitBreaker $circuitBreaker
) {}
}enabled: Enable/disable circuit breaker (default: true)time_window: Time window for failure counting in seconds (default: 60)total_failures: Number of failures before opening circuit (default: 5)time_out_open: Time to keep circuit open in seconds (default: 60)time_out_half_open: Time to keep circuit in half-open state (default: 60)adapter: Storage adapter to use (default: 'redis')
# Run all tests
composer test
# Run unit tests only
composer test-unit
# Run integration tests
composer test-integration
# Generate coverage report
composer test-coverageMIT