defaultConfig = new CircuitBreakerConfig( failureThreshold: $failureThreshold, recoveryTimeout: Duration::fromSeconds($recoveryTimeoutSeconds), halfOpenMaxAttempts: 3, successThreshold: 2 ); } /** * Check if a middleware is allowed to execute * * @param string $middlewareName The fully qualified class name of the middleware * @return bool True if the middleware is allowed to execute, false otherwise */ public function isAllowed(string $middlewareName): bool { try { // Use the CircuitBreaker to check if the middleware is allowed to execute $this->circuitBreaker->check($this->getServiceName($middlewareName), $this->defaultConfig); return true; } catch (Throwable $e) { // If the circuit is open, the check method will throw an exception return false; } } /** * Record a successful middleware execution * * @param string $middlewareName The fully qualified class name of the middleware */ public function recordSuccess(string $middlewareName): void { // Delegate to the CircuitBreaker $this->circuitBreaker->recordSuccess($this->getServiceName($middlewareName), $this->defaultConfig); } /** * Record a middleware failure * * @param string $middlewareName The fully qualified class name of the middleware * @param int|null $failureThreshold Custom failure threshold for this middleware * @param int|null $openTime Custom open time for this middleware */ public function recordFailure(string $middlewareName, ?int $failureThreshold = null, ?int $openTime = null): void { // Create a custom config if custom thresholds are provided $config = $this->defaultConfig; if ($failureThreshold !== null || $openTime !== null) { $config = new CircuitBreakerConfig( failureThreshold: $failureThreshold ?? $this->defaultConfig->failureThreshold, recoveryTimeout: $openTime ? Duration::fromSeconds($openTime) : $this->defaultConfig->recoveryTimeout, halfOpenMaxAttempts: $this->defaultConfig->halfOpenMaxAttempts, successThreshold: $this->defaultConfig->successThreshold ); } // Create a RuntimeException to pass to the CircuitBreaker $exception = new RuntimeException("Middleware {$middlewareName} failed"); // Delegate to the CircuitBreaker $this->circuitBreaker->recordFailure($this->getServiceName($middlewareName), $exception, $config); } /** * Get the state of the circuit for a middleware * * @param string $middlewareName The fully qualified class name of the middleware * @return CircuitState The current state of the circuit */ public function getState(string $middlewareName): CircuitState { return $this->circuitBreaker->getState($this->getServiceName($middlewareName), $this->defaultConfig); } /** * Reset the circuit for a middleware * * @param string $middlewareName The fully qualified class name of the middleware */ public function reset(string $middlewareName): void { $this->circuitBreaker->reset($this->getServiceName($middlewareName)); } /** * Get metrics for a middleware * * @param string $middlewareName The fully qualified class name of the middleware * @return array Metrics for the middleware */ public function getMetrics(string $middlewareName): array { return $this->circuitBreaker->getMetrics($this->getServiceName($middlewareName)); } /** * Convert a middleware name to a service name for the CircuitBreaker * * @param string $middlewareName The fully qualified class name of the middleware * @return string The service name for the CircuitBreaker */ private function getServiceName(string $middlewareName): string { return 'middleware:' . $middlewareName; } }