import 'package:logging/logging.dart'; /// Circuit breaker pattern implementation for authentication service failures class AuthCircuitBreaker { static final _logger = Logger('service.auth_circuit_breaker'); static int _failureCount = 0; static DateTime? _lastFailure; static const int _failureThreshold = 3; static const Duration _recoveryTime = Duration(minutes: 5); /// Returns true if the circuit breaker is open (blocking operations) static bool get isOpen { if (_failureCount < _failureThreshold) return false; if (_lastFailure == null) return false; final isOpen = DateTime.now().difference(_lastFailure!) < _recoveryTime; if (isOpen) { _logger.warning('Circuit breaker is OPEN. Failure count: $_failureCount, last failure: $_lastFailure'); } return isOpen; } /// Returns true if the circuit breaker is in half-open state (allowing test requests) static bool get isHalfOpen { if (_failureCount < _failureThreshold) return false; if (_lastFailure == null) return false; return DateTime.now().difference(_lastFailure!) >= _recoveryTime; } /// Executes an operation with circuit breaker protection static Future execute(Future Function() operation) async { if (isOpen) { final timeSinceFailure = _lastFailure != null ? DateTime.now().difference(_lastFailure!) : Duration.zero; final timeUntilRecovery = _recoveryTime - timeSinceFailure; _logger.warning('Circuit breaker blocking operation. Recovery in: ${timeUntilRecovery.inSeconds}s'); throw Exception('Auth service temporarily unavailable. Try again in ${timeUntilRecovery.inMinutes} minutes.'); } try { _logger.fine('Executing operation through circuit breaker'); final result = await operation(); _reset(); return result; } catch (e) { _recordFailure(); rethrow; } } /// Records a failure and updates the circuit breaker state static void _recordFailure() { _failureCount++; _lastFailure = DateTime.now(); _logger.warning('Auth circuit breaker recorded failure #$_failureCount at $_lastFailure'); if (_failureCount >= _failureThreshold) { _logger.severe('Auth circuit breaker OPENED after $_failureCount failures'); } } /// Resets the circuit breaker to closed state static void _reset() { if (_failureCount > 0) { _logger.info('Auth circuit breaker CLOSED - resetting failure count from $_failureCount to 0'); } _failureCount = 0; _lastFailure = null; } /// Manual reset (for testing or administrative purposes) static void manualReset() { _logger.info('Auth circuit breaker manually reset'); _reset(); } /// Get current status for debugging static Map getStatus() { return { 'failureCount': _failureCount, 'lastFailure': _lastFailure?.toIso8601String(), 'isOpen': isOpen, 'isHalfOpen': isHalfOpen, 'threshold': _failureThreshold, 'recoveryTime': _recoveryTime.inSeconds, }; } }