guard<T> method

Future<T> guard<T>({
  1. required Future<T> action(),
  2. ConnectionQuality minQuality = ConnectionQuality.good,
})

Protects a network-sensitive action by validating the connection first.

This is the recommended way to execute critical API calls. It performs multiple checks in sequence:

  1. Circuit Breaker: Blocks immediately if the connection is known to be failing.
  2. Connectivity: Ensures the device is actually online.
  3. Security: Validates SecurityConfig (e.g., checks for VPN or DNS Hijacking).
  4. Quality: Ensures the connection meets the minQuality requirement.

Parameters:

Throws:

Returns the result of the action.

Implementation

Future<T> guard<T>({
  required Future<T> Function() action,
  ConnectionQuality minQuality = ConnectionQuality.good,
}) async {
  // 1. Handle Circuit Breaker State
  if (_circuitState == CircuitBreakerState.open) {
    if (_circuitBreakerResetTime != null &&
        DateTime.now().isBefore(_circuitBreakerResetTime!)) {
      final remaining = _circuitBreakerResetTime!.difference(DateTime.now());
      throw CircuitBreakerOpenException(
          'Circuit breaker is open due to recent failures. Retry after ${remaining.inSeconds}s',
          retryAfter: remaining);
    } else {
      // Transition to Half-Open to allow a probe
      _circuitState = CircuitBreakerState.halfOpen;
    }
  }

  // 2. Perform or reuse network check
  final report = await check();

  // 3. Validate security requirements
  if (_config.security.blockVpn && report.securityFlagsResult.isVpnDetected) {
    throw SecurityException(
        SecurityAlert.vpnDetected, 'VPN connection is not allowed.');
  }
  if (_config.security.detectDnsHijack &&
      report.securityFlagsResult.isDnsSpoofed) {
    throw SecurityException(SecurityAlert.dnsHijackDetected,
        'DNS hijacking was detected. Connection is insecure.');
  }

  // 4. Validate quality requirements
  if (!report.status.isConnected ||
      report.status.quality.index > minQuality.index) {
    throw PoorConnectionException(
        'Connection quality (${report.status.quality.name}) is below required (${minQuality.name}).');
  }

  // 5. Success: Close circuit if it was half-open
  if (_circuitState == CircuitBreakerState.halfOpen) {
    _circuitState = CircuitBreakerState.closed;
    _consecutiveFailures = 0;
  }

  return await action();
}