PHP code example of cmatosbc / alecto

1. Go to this page and download the library: Download cmatosbc/alecto 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/ */

    

cmatosbc / alecto example snippets


use Alecto\CircuitBreaker;
use Alecto\Config\CircuitBreakerConfig;
use Alecto\Service\TimeoutExecutor;

// Create configuration
$config = new CircuitBreakerConfig(
    failureThreshold: 3,    // Open circuit after 3 failures
    successThreshold: 2,    // Close circuit after 2 successes
    resetTimeout: 10,       // Wait 10 seconds before attempting recovery
    operationTimeout: 5     // Timeout operations after 5 seconds
);

// Initialize circuit breaker
$circuitBreaker = new CircuitBreaker(
    config: $config,
    timeoutExecutor: new TimeoutExecutor()
);

// Use the circuit breaker
try {
    $result = $circuitBreaker->call(
        callback: function() {
            return someRiskyOperation();
        },
        fallback: function() {
            return "Fallback response";
        }
    );
} catch (\Exception $e) {
    // Handle exception
}

$metrics = $circuitBreaker->getMetrics();

// Available metrics:
$metrics['successes'];   // Successful operations count
$metrics['failures'];    // Failed operations count
$metrics['rejections']; // Rejected operations count (when circuit is open)

class ApiClient
{
    public function __construct(
        private Alecto\CircuitBreaker $circuitBreaker,
        private HttpClient $httpClient
    ) {}

    public function fetchUserData(int $userId): array
    {
        return $this->circuitBreaker->call(
            callback: function() use ($userId) {
                $response = $this->httpClient->get("/users/{$userId}");
                return $response->toArray();
            },
            fallback: function() use ($userId) {
                return $this->getCachedUserData($userId);
            }
        );
    }
}

class DatabaseRepository
{
    public function __construct(
        private Alecto\CircuitBreaker $circuitBreaker,
        private PDO $pdo
    ) {}

    public function executeQuery(string $query, array $params = []): array
    {
        return $this->circuitBreaker->call(
            callback: function() use ($query, $params) {
                $stmt = $this->pdo->prepare($query);
                $stmt->execute($params);
                return $stmt->fetchAll(PDO::FETCH_ASSOC);
            },
            fallback: function() {
                return $this->getFromCache() ?? [];
            }
        );
    }
}

class PaymentService
{
    public function __construct(
        private Alecto\CircuitBreaker $circuitBreaker,
        private PaymentGateway $gateway
    ) {}

    public function processPayment(Order $order): PaymentResult
    {
        return $this->circuitBreaker->call(
            callback: function() use ($order) {
                return $this->gateway->processPayment($order);
            },
            fallback: function() use ($order) {
                $this->queueForRetry($order);
                return new PaymentResult(status: 'QUEUED');
            }
        );
    }
}

// config/services.yaml
services:
    Alecto\Config\CircuitBreakerConfig:
        arguments:
            $failureThreshold: '%env(int:CIRCUIT_FAILURE_THRESHOLD)%'
            $successThreshold: '%env(int:CIRCUIT_SUCCESS_THRESHOLD)%'
            $resetTimeout: '%env(int:CIRCUIT_RESET_TIMEOUT)%'
            $operationTimeout: '%env(int:CIRCUIT_OPERATION_TIMEOUT)%'

    Alecto\Service\TimeoutExecutor: ~

    Alecto\CircuitBreaker:
        arguments:
            $config: '@Alecto\Config\CircuitBreakerConfig'
            $timeoutExecutor: '@Alecto\Service\TimeoutExecutor'
            $logger: '@logger'

    App\Service\ExternalApiClient:
        arguments:
            $circuitBreaker: '@Alecto\CircuitBreaker'

// src/Service/ExternalApiClient.php
namespace App\Service;

use Alecto\CircuitBreaker;
use Symfony\Contracts\HttpClient\HttpClientInterface;

class ExternalApiClient
{
    public function __construct(
        private readonly Alecto\CircuitBreaker $circuitBreaker,
        private readonly HttpClientInterface $client
    ) {}

    public function fetchData(): array
    {
        return $this->circuitBreaker->call(
            callback: function() {
                $response = $this->client->request('GET', 'https://api.example.com/data');
                return $response->toArray();
            },
            fallback: function() {
                return $this->getCachedData();
            }
        );
    }
}

// app/Providers/CircuitBreakerServiceProvider.php
namespace App\Providers;

use Alecto\CircuitBreaker;
use Alecto\Config\CircuitBreakerConfig;
use Alecto\Service\TimeoutExecutor;
use Illuminate\Support\ServiceProvider;

class CircuitBreakerServiceProvider extends ServiceProvider
{
    public function register(): void
    {
        $this->app->singleton(CircuitBreakerConfig::class, function ($app) {
            return new CircuitBreakerConfig(
                failureThreshold: config('services.circuit.failure_threshold', 3),
                successThreshold: config('services.circuit.success_threshold', 2),
                resetTimeout: config('services.circuit.reset_timeout', 30),
                operationTimeout: config('services.circuit.operation_timeout', 5)
            );
        });

        $this->app->singleton(TimeoutExecutor::class);

        $this->app->singleton(CircuitBreaker::class, function ($app) {
            return new CircuitBreaker(
                config: $app->make(CircuitBreakerConfig::class),
                timeoutExecutor: $app->make(TimeoutExecutor::class),
                logger: $app->make('log')
            );
        });
    }
}

// config/services.php
return [
    'circuit' => [
        'failure_threshold' => env('CIRCUIT_FAILURE_THRESHOLD', 3),
        'success_threshold' => env('CIRCUIT_SUCCESS_THRESHOLD', 2),
        'reset_timeout' => env('CIRCUIT_RESET_TIMEOUT', 30),
        'operation_timeout' => env('CIRCUIT_OPERATION_TIMEOUT', 5),
    ],
];

// app/Services/PaymentGateway.php
namespace App\Services;

use Alecto\CircuitBreaker;

class PaymentGateway
{
    public function __construct(
        private readonly Alecto\CircuitBreaker $circuitBreaker
    ) {}

    public function processPayment(array $paymentData): array
    {
        return $this->circuitBreaker->call(
            callback: function() use ($paymentData) {
                return $this->gateway->charge($paymentData);
            },
            fallback: function() use ($paymentData) {
                $this->queuePaymentForRetry($paymentData);
                return ['status' => 'queued'];
            }
        );
    }
}

$config = new CircuitBreakerConfig(
    failureThreshold: 5,
    successThreshold: 3,
    resetTimeout: 30,
    operationTimeout: 2  // Short timeout for time-sensitive operations
);

use Psr\Log\LoggerInterface;

$circuitBreaker = new CircuitBreaker(
    config: $config,
    timeoutExecutor: new TimeoutExecutor(),
    logger: $psrLogger
);