Use the Circuit Breaker pattern to handle failures in external service calls gracefully. This prevents cascading failures and improves system resilience.
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
class CircuitBreaker
{
private $failureThreshold = 3;
private $resetTimeout = 30;
private $lastFailureTime;
private $failureCount = 0;
public function call(callable $function)
{
if ($this->isOpen()) {
throw new Exception('Circuit is open');
}
try {
$result = $function();
$this->reset();
return $result;
} catch (Exception $e) {
$this->recordFailure();
throw $e;
}
}
private function isOpen()
{
if ($this->failureCount >= $this->failureThreshold) {
$timeSinceLastFailure = time() - $this->lastFailureTime;
if ($timeSinceLastFailure <= $this->resetTimeout) {
return true;
}
$this->reset();
}
return false;
}
private function recordFailure()
{
$this->failureCount++;
$this->lastFailureTime = time();
}
private function reset()
{
$this->failureCount = 0;
$this->lastFailureTime = null;
}
}
// Usage
$circuitBreaker = new CircuitBreaker();
try {
$result = $circuitBreaker->call(function() {
$client = new Client();
return $client->get('http://api.example.com');
});
} catch (Exception $e) {
// Handle the exception
}