Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Circuit Breaker Laravel Package

webrek/laravel-circuit-breaker

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require webrek/laravel-circuit-breaker
    

    Publish the config file:

    php artisan vendor:publish --provider="Webrek\CircuitBreaker\CircuitBreakerServiceProvider" --tag="config"
    
  2. First Use Case: Wrap an external API call in a circuit breaker. Example:

    use Webrek\CircuitBreaker\Facades\CircuitBreaker;
    
    try {
        $response = CircuitBreaker::attempt('payment-gateway', function () {
            return Http::post('https://api.gateway.com/pay', $data);
        });
    } catch (\Webrek\CircuitBreaker\Exceptions\CircuitBreakerException $e) {
        // Handle circuit breaker failure (e.g., return cached data or fallback UI)
        return response()->json(['error' => 'Service unavailable'], 503);
    }
    
  3. Configuration: Define breakers in config/circuit-breaker.php:

    'breakers' => [
        'payment-gateway' => [
            'timeout' => 5, // seconds
            'max_failures' => 3,
            'reset_timeout' => 30, // seconds
        ],
    ],
    

Implementation Patterns

Workflows

  1. Idempotent Operations: Use the breaker for stateless or idempotent calls (e.g., API requests, webhooks). Avoid stateful operations (e.g., database transactions) inside the breaker.

  2. Fallback Strategies:

    • Cache Fallback: Return cached data when the circuit is open.
      $cachedData = Cache::get('payment_fallback');
      if (!$cachedData) {
          throw new \Webrek\CircuitBreaker\Exceptions\CircuitBreakerException('Fallback data not available');
      }
      
    • Graceful Degradation: Serve a simplified UI/response (e.g., "Service temporarily unavailable").
  3. Retry Logic: Combine with Laravel’s retry helper for transient failures:

    $response = retry(3, function () use ($data) {
        return CircuitBreaker::attempt('payment-gateway', fn() => Http::post('...', $data));
    }, 100); // 100ms delay between retries
    
  4. Monitoring: Log breaker states and failures for observability:

    CircuitBreaker::attempt('payment-gateway', function () {
        // ...
    }, function ($state) {
        Log::info("Circuit breaker state: {$state->state}", ['failures' => $state->failures]);
    });
    

Integration Tips

  • Queue Jobs: Use the breaker in queued jobs to avoid blocking workers:
    CircuitBreaker::attempt('external-webhook', function () {
        $job->dispatch($data);
    });
    
  • Middleware: Protect API routes with a middleware that wraps requests in a breaker:
    public function handle($request, Closure $next) {
        return CircuitBreaker::attempt('third-party-api', $next);
    }
    
  • Testing: Mock the breaker in tests to simulate open/closed states:
    $breaker = app(\Webrek\CircuitBreaker\CircuitBreaker::class)->get('payment-gateway');
    $breaker->setState('open'); // Force open state for testing
    

Gotchas and Tips

Pitfalls

  1. Misconfigured Timeouts:

    • Issue: Setting timeout too low may cause false positives (e.g., slow but not failed requests).
    • Fix: Monitor latency and adjust timeout based on the dependency’s SLA.
  2. State Persistence:

    • Issue: The breaker state is not persisted across processes (e.g., multiple Laravel workers).
    • Fix: Use a shared cache (e.g., Redis) for distributed environments:
      'driver' => 'redis',
      'prefix' => 'circuit_breaker_',
      
  3. Blocking Calls:

    • Issue: Synchronous breakers block the request thread. For long-running tasks, use async queues.
    • Fix: Offload breaker-wrapped logic to queues or background jobs.
  4. Exception Handling:

    • Issue: Only specific exceptions (e.g., HttpException, ConnectException) should increment failure counts.
    • Fix: Customize the shouldCountAsFailure callback in config:
      'breakers' => [
          'payment-gateway' => [
              'should_count_as_failure' => function ($exception) {
                  return $exception instanceof \Symfony\Component\HttpKernel\Exception\HttpException
                         && $exception->getStatusCode() >= 500;
              },
          ],
      ],
      

Debugging

  1. Check State: Inspect the breaker state manually:

    $breaker = app(\Webrek\CircuitBreaker\CircuitBreaker::class)->get('payment-gateway');
    dd($breaker->getState()); // Returns ['state', 'failures', 'next_reset']
    
  2. Log Failures: Enable debug logging in config/circuit-breaker.php:

    'log_failures' => true,
    
  3. Reset Manually: Reset a breaker programmatically (e.g., after a service restart):

    app(\Webrek\CircuitBreaker\CircuitBreaker::class)->get('payment-gateway')->reset();
    

Extension Points

  1. Custom States: Extend the breaker to support custom states (e.g., "degraded"):

    // In a service provider:
    \Webrek\CircuitBreaker\CircuitBreaker::extend('degraded', function () {
        return new \Webrek\CircuitBreaker\States\DegradedState();
    });
    
  2. Event Listeners: Listen for breaker state changes:

    \Webrek\CircuitBreaker\Events\CircuitBreakerStateChanged::class => [
        \App\Listeners\NotifyOpsTeam::class,
    ],
    
  3. Dynamic Configuration: Override breaker settings at runtime:

    CircuitBreaker::configure('payment-gateway', [
        'max_failures' => 5,
        'reset_timeout' => 60,
    ]);
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
codraw/graphviz
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata