1. Go to this page and download the library: Download ahmednour/circuit-breaker 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/ */
namespace App\Services;
use AhmedNour\CircuitBreaker\Application\CircuitBreaker;
use AhmedNour\CircuitBreaker\Domain\Exceptions\CircuitOpenException;
use AhmedNour\CircuitBreaker\Domain\Exceptions\CircuitBusyException;
class SmsService
{
public function __construct(
private readonly CircuitBreaker $circuitBreaker,
private readonly TwilioClient $twilio,
) {}
public function sendSms(string $to, string $message): string
{
try {
return $this->circuitBreaker->execute('twilio-sms', function () use ($to, $message) {
return $this->twilio->messages->create($to, [
'body' => $message,
]);
});
} catch (CircuitOpenException $e) {
// Service is known to be down — fallback or notify user
logger()->warning("Twilio circuit is OPEN. Failing fast.");
throw new ServiceUnavailableException("SMS gateway is temporarily unavailable.");
} catch (CircuitBusyException $e) {
// Another worker is currently testing the connection
logger()->info("Twilio circuit is HALF-OPEN probe busy.");
throw new ServiceBusyException("SMS gateway is recovering, please retry shortly.");
}
}
}
namespace App\Jobs;
use AhmedNour\CircuitBreaker\Application\CircuitBreaker;
use AhmedNour\CircuitBreaker\Domain\Exceptions\CircuitBusyException;
use AhmedNour\CircuitBreaker\Domain\Exceptions\CircuitOpenException;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class SendSmsNotificationJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public int $tries = 5;
public function __construct(
public readonly string $phone,
public readonly string $message,
) {}
public function handle(CircuitBreaker $circuitBreaker, TwilioClient $twilio): void
{
try {
$circuitBreaker->execute('twilio-sms', function () use ($twilio) {
$twilio->send($this->phone, $this->message);
});
} catch (CircuitOpenException) {
// Circuit is OPEN: Delay release by recovery window (e.g., 300s)
$this->release(300);
} catch (CircuitBusyException) {
// Circuit is HALF_OPEN and another worker is probing: retry in 10s
$this->release(10);
}
}
}
use AhmedNour\CircuitBreaker\Domain\CircuitExecution;
use AhmedNour\CircuitBreaker\Domain\Contracts\InfrastructureFallback;
use Throwable;
class DatabaseCircuitFallback implements InfrastructureFallback
{
public function execute(CircuitExecution $execution, Throwable $exception): mixed
{
// Custom recovery logic, logging, or fallback execution
return ($execution->callback)();
}
}