PHP code example of kissmint3395 / aegis

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

    

kissmint3395 / aegis example snippets


$pipeline = ResiliencePipeline::builder()
    ->circuitBreaker('payment-api', failureThreshold: 5)
    ->retry(maxAttempts: 3, backoff: ExponentialBackoff::withJitter(Duration::milliseconds(100)))
    ->timeout(Duration::seconds(5))
    ->fallback(fn(\Throwable $e) => CachedResponse::last())
    ->build();

$result = $pipeline->execute(fn() => $httpClient->post('/charge', $payload));

use Aegis\ResiliencePipeline;
use Aegis\Backoff\ExponentialBackoff;
use Aegis\Duration;

$pipeline = ResiliencePipeline::builder()
    ->retry(
        maxAttempts: 3,
        backoff: ExponentialBackoff::withJitter(Duration::milliseconds(100)),
        retryOn: [\RuntimeException::class],
    )
    ->build();

$result = $pipeline->execute(fn() => $api->fetch());

use Aegis\Backoff\FixedBackoff;
use Aegis\Backoff\ExponentialBackoff;

// Fixed delay
new FixedBackoff(Duration::milliseconds(200))

// Exponential: 100ms → 200ms → 400ms → ...
ExponentialBackoff::create(Duration::milliseconds(100))

// Exponential with jitter: randomised between 50%–100% of each step
ExponentialBackoff::withJitter(Duration::milliseconds(100), maxDelay: Duration::seconds(5))

->retry(
    retryIf: fn(\Throwable $e) => $e->getCode() >= 500,
)

use Aegis\ResiliencePipeline;
use Aegis\Duration;

$pipeline = ResiliencePipeline::builder()
    ->circuitBreaker(
        name: 'inventory-api',
        failureThreshold: 5,   // Open after 5 consecutive failures
        successThreshold: 2,   // Close after 2 consecutive successes in HalfOpen
        resetAfter: Duration::seconds(30),
    )
    ->build();

use Aegis\Strategy\CircuitBreaker\Storage\Psr16Storage;

$pipeline = ResiliencePipeline::builder()
    ->circuitBreaker('payment-api', storage: new Psr16Storage($redisCache))
    ->build();

->circuitBreaker('api', ignoreExceptions: [\InvalidArgumentException::class])

$pipeline = ResiliencePipeline::builder()
    ->adaptiveCircuitBreaker(
        name: 'payment-api',
        windowSize: 20,              // Evaluate the last 20 calls
        failureRateThreshold: 50.0,  // Open if ≥ 50% fail
        minimumCalls: 5,             // Don't open until at least 5 calls recorded
        successThreshold: 2,         // Close after 2 successes in HalfOpen
        resetAfter: Duration::seconds(30),
    )
    ->build();

use Aegis\Strategy\CircuitBreaker\Storage\AdaptivePsr16Storage;

->adaptiveCircuitBreaker('api', storage: new AdaptivePsr16Storage($redisCache))

->timeout(Duration::seconds(5))

use Aegis\ResiliencePipeline;
use Aegis\Duration;

$pipeline = ResiliencePipeline::builder()
    ->rateLimit(
        name: 'payment-api',
        limit: 100,                      // Max 100 calls per window
        window: Duration::seconds(60),
    )
    ->build();

use Aegis\Strategy\RateLimiter\Storage\Psr16Storage;

$pipeline = ResiliencePipeline::builder()
    ->rateLimit('payment-api', limit: 100, storage: new Psr16Storage($redisCache))
    ->build();

$pipeline = ResiliencePipeline::builder()
    ->slidingRateLimit(
        name: 'payment-api',
        limit: 100,
        window: Duration::seconds(60),
    )
    ->build();

use Aegis\Strategy\RateLimiter\Storage\SlidingWindowPsr16Storage;

->slidingRateLimit('payment-api', limit: 100, storage: new SlidingWindowPsr16Storage($redisCache))

$pipeline = ResiliencePipeline::builder()
    ->tokenBucketRateLimit(
        name: 'payment-api',
        capacity: 20,                          // Max burst size
        refillRate: 10,                        // Tokens added per period
        refillPeriod: Duration::seconds(1),    // Refill interval
    )
    ->build();

use Aegis\Strategy\RateLimiter\Storage\TokenBucketPsr16Storage;

->tokenBucketRateLimit('api', capacity: 20, storage: new TokenBucketPsr16Storage($redisCache))

use Aegis\ResiliencePipeline;

$pipeline = ResiliencePipeline::builder()
    ->bulkhead(
        name: 'database',
        maxConcurrent: 10,   // Allow at most 10 concurrent calls
    )
    ->build();

use Aegis\Strategy\Bulkhead\Storage\Psr16Storage;

$pipeline = ResiliencePipeline::builder()
    ->bulkhead('database', maxConcurrent: 10, storage: new Psr16Storage($redisCache))
    ->build();

$pipeline = ResiliencePipeline::builder()
    ->circuitBreaker('payment-api')
    ->retry(maxAttempts: 3)
    ->fallback(fn(\Throwable $e) => ['status' => 'unavailable'])
    ->build();

use Aegis\Exception\FallbackNotAvailableException;

try {
    $result = $pipeline->execute(fn() => $api->fetch());
} catch (FallbackNotAvailableException $e) {
    $original = $e->getOriginalException();
}

use Aegis\Strategy\Cache\Storage\CacheInMemoryStorage;

$storage  = new CacheInMemoryStorage();  // or CachePsr16Storage for persistence

$pipeline = ResiliencePipeline::builder()
    ->cache(
        name: 'product-catalog',
        ttl: Duration::minutes(5),
        staleOnFailure: true,   // Serve expired cache when downstream throws
        storage: $storage,
    )
    ->build();

$pipeline = ResiliencePipeline::builder()
    ->hedge(
        delay: Duration::milliseconds(200),  // Fire hedge after 200ms
        maxHedges: 1,
    )
    ->build();

$pipeline = ResiliencePipeline::builder()
    ->bulkhead('svc', maxConcurrent: 10)          // 1. Concurrency gate
    ->rateLimit('svc', limit: 100)                // 2. Rate gate
    ->timeout(Duration::seconds(10))              // 3. Total time budget
    ->circuitBreaker('svc', failureThreshold: 5)  // 4. Block if unhealthy
    ->retry(maxAttempts: 3)                       // 5. Retry transient failures
    ->fallback(fn() => $defaultValue)             // 6. Last-resort fallback
    ->build();

use Aegis\Event\RetryAttempted;
use Aegis\Event\CircuitOpened;
use Aegis\Event\RateLimitExceeded;
use Aegis\Event\TokenBucketExhausted;

$pipeline = ResiliencePipeline::builder()
    ->withEventDispatcher($dispatcher)
    ->circuitBreaker('api')
    ->retry(maxAttempts: 3)
    ->build();

// Note: listener registration API (listen/addListener/subscribeTo) depends on your PSR-14 implementation.
$dispatcher->listen(RetryAttempted::class, function (RetryAttempted $e) use ($logger): void {
    $logger->warning('Retry attempt', [
        'attempt'   => $e->attempt,
        'max'       => $e->maxAttempts,
        'delay_ms'  => $e->delayMs,
        'error'     => $e->cause->getMessage(),
    ]);
});

use Aegis\Contract\StrategyInterface;

final class LoggingStrategy implements StrategyInterface
{
    public function __construct(private readonly LoggerInterface $logger) {}

    public function execute(callable $next): mixed
    {
        $start = microtime(true);
        try {
            $result = $next();
            $this->logger->info('OK', ['ms' => (int)((microtime(true) - $start) * 1000)]);
            return $result;
        } catch (\Throwable $e) {
            $this->logger->error($e->getMessage());
            throw $e;
        }
    }
}

$pipeline = ResiliencePipeline::builder()
    ->addStrategy(new LoggingStrategy($logger))
    ->retry(maxAttempts: 3)
    ->build();

// PHPStan error: "stdClass" does not implement Throwable
new RetryOptions(retryOn: [\stdClass::class]);

$pipeline = ResiliencePipeline::builder()
    ->circuitBreaker('payment-api', failureThreshold: 5)
    ->retry(maxAttempts: 3, backoff: ExponentialBackoff::withJitter(Duration::milliseconds(100)))
    ->timeout(Duration::seconds(5))
    ->fallback(fn(\Throwable $e) => CachedResponse::last())
    ->build();

$result = $pipeline->execute(fn() => $httpClient->post('/charge', $payload));

use Aegis\ResiliencePipeline;
use Aegis\Backoff\ExponentialBackoff;
use Aegis\Duration;

$pipeline = ResiliencePipeline::builder()
    ->retry(
        maxAttempts: 3,
        backoff: ExponentialBackoff::withJitter(Duration::milliseconds(100)),
        retryOn: [\RuntimeException::class],
    )
    ->build();

$result = $pipeline->execute(fn() => $api->fetch());

use Aegis\Backoff\FixedBackoff;
use Aegis\Backoff\ExponentialBackoff;

// 固定遅延
new FixedBackoff(Duration::milliseconds(200))

// 指数バックオフ: 100ms → 200ms → 400ms → ...
ExponentialBackoff::create(Duration::milliseconds(100))

// ジッター付き指数バックオフ: 各ステップの 50〜100% をランダムで選択
ExponentialBackoff::withJitter(Duration::milliseconds(100), maxDelay: Duration::seconds(5))

->retry(
    retryIf: fn(\Throwable $e) => $e->getCode() >= 500,
)

use Aegis\ResiliencePipeline;
use Aegis\Duration;

$pipeline = ResiliencePipeline::builder()
    ->circuitBreaker(
        name: 'inventory-api',
        failureThreshold: 5,
        successThreshold: 2,
        resetAfter: Duration::seconds(30),
    )
    ->build();

use Aegis\Strategy\CircuitBreaker\Storage\Psr16Storage;

$pipeline = ResiliencePipeline::builder()
    ->circuitBreaker('payment-api', storage: new Psr16Storage($redisCache))
    ->build();

$pipeline = ResiliencePipeline::builder()
    ->adaptiveCircuitBreaker(
        name: 'payment-api',
        windowSize: 20,              // 直近 20 件を評価
        failureRateThreshold: 50.0,  // 50% 以上失敗でオープン
        minimumCalls: 5,             // 5 件以上記録されるまでは評価しない
        successThreshold: 2,
        resetAfter: Duration::seconds(30),
    )
    ->build();

->timeout(Duration::seconds(5))

$pipeline = ResiliencePipeline::builder()
    ->rateLimit(
        name: 'payment-api',
        limit: 100,
        window: Duration::seconds(60),
    )
    ->build();

$pipeline = ResiliencePipeline::builder()
    ->slidingRateLimit(
        name: 'payment-api',
        limit: 100,
        window: Duration::seconds(60),
    )
    ->build();

$pipeline = ResiliencePipeline::builder()
    ->tokenBucketRateLimit(
        name: 'payment-api',
        capacity: 20,
        refillRate: 10,
        refillPeriod: Duration::seconds(1),
    )
    ->build();

$pipeline = ResiliencePipeline::builder()
    ->bulkhead(
        name: 'database',
        maxConcurrent: 10,
    )
    ->build();

$pipeline = ResiliencePipeline::builder()
    ->circuitBreaker('payment-api')
    ->retry(maxAttempts: 3)
    ->fallback(fn(\Throwable $e) => ['status' => 'unavailable'])
    ->build();

use Aegis\Strategy\Cache\Storage\CacheInMemoryStorage;

$pipeline = ResiliencePipeline::builder()
    ->cache(
        name: 'product-catalog',
        ttl: Duration::minutes(5),
        staleOnFailure: true,
        storage: new CacheInMemoryStorage(),
    )
    ->build();

$pipeline = ResiliencePipeline::builder()
    ->hedge(
        delay: Duration::milliseconds(200),
        maxHedges: 1,
    )
    ->build();

$pipeline = ResiliencePipeline::builder()
    ->bulkhead('svc', maxConcurrent: 10)
    ->rateLimit('svc', limit: 100)
    ->timeout(Duration::seconds(10))
    ->circuitBreaker('svc', failureThreshold: 5)
    ->retry(maxAttempts: 3)
    ->fallback(fn() => $defaultValue)
    ->build();

$pipeline = ResiliencePipeline::builder()
    ->withEventDispatcher($dispatcher)
    ->circuitBreaker('api')
    ->retry(maxAttempts: 3)
    ->build();

use Aegis\Contract\StrategyInterface;

final class LoggingStrategy implements StrategyInterface
{
    public function __construct(private readonly LoggerInterface $logger) {}

    public function execute(callable $next): mixed
    {
        $start = microtime(true);
        try {
            $result = $next();
            $this->logger->info('成功', ['ms' => (int)((microtime(true) - $start) * 1000)]);
            return $result;
        } catch (\Throwable $e) {
            $this->logger->error($e->getMessage());
            throw $e;
        }
    }
}

$pipeline = ResiliencePipeline::builder()
    ->addStrategy(new LoggingStrategy($logger))
    ->retry(maxAttempts: 3)
    ->build();

// PHPStan エラー: "stdClass" は Throwable を実装していない
new RetryOptions(retryOn: [\stdClass::class]);