+signup +login
Some checks failed
ci/woodpecker/push/bff Pipeline was successful
ci/woodpecker/push/db Pipeline was successful
ci/woodpecker/push/billing_fees Pipeline was successful
ci/woodpecker/push/chain_gateway Pipeline was successful
ci/woodpecker/push/fx_ingestor Pipeline was successful
ci/woodpecker/push/frontend Pipeline was successful
ci/woodpecker/push/fx_oracle Pipeline was successful
ci/woodpecker/push/nats Pipeline was successful
ci/woodpecker/push/ledger Pipeline was successful
ci/woodpecker/push/notification Pipeline was successful
ci/woodpecker/push/payments_orchestrator Pipeline was successful
ci/woodpecker/push/bump_version Pipeline failed
Some checks failed
ci/woodpecker/push/bff Pipeline was successful
ci/woodpecker/push/db Pipeline was successful
ci/woodpecker/push/billing_fees Pipeline was successful
ci/woodpecker/push/chain_gateway Pipeline was successful
ci/woodpecker/push/fx_ingestor Pipeline was successful
ci/woodpecker/push/frontend Pipeline was successful
ci/woodpecker/push/fx_oracle Pipeline was successful
ci/woodpecker/push/nats Pipeline was successful
ci/woodpecker/push/ledger Pipeline was successful
ci/woodpecker/push/notification Pipeline was successful
ci/woodpecker/push/payments_orchestrator Pipeline was successful
ci/woodpecker/push/bump_version Pipeline failed
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
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<T> execute<T>(Future<T> 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<String, dynamic> getStatus() {
|
||||
return {
|
||||
'failureCount': _failureCount,
|
||||
'lastFailure': _lastFailure?.toIso8601String(),
|
||||
'isOpen': isOpen,
|
||||
'isHalfOpen': isHalfOpen,
|
||||
'threshold': _failureThreshold,
|
||||
'recoveryTime': _recoveryTime.inSeconds,
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user