postJSONWithSocketRetry method

Future<BaseResponse?> postJSONWithSocketRetry(
  1. RequestData rd, {
  2. int maxRetries = 3,
  3. Duration initialDelay = const Duration(seconds: 2),
  4. bool exponentialBackoff = true,
})

Erweiterte Version von postJSON mit robuster Behandlung von Socket-Fehlern Besonders wichtig für Hintergrundprozesse, bei denen die App in den Hintergrund wechselt

Implementation

Future<http.BaseResponse?> postJSONWithSocketRetry(
  RequestData rd, {
  int maxRetries = 3,
  Duration initialDelay = const Duration(seconds: 2),
  bool exponentialBackoff = true,
}) async {
  int attempts = 0;
  SocketException? lastSocketException;
  Duration currentDelay = initialDelay;

  while (attempts < maxRetries) {
    try {
      // Verwende die ursprüngliche postJSON-Methode
      final response = await postJSON(rd);
      if (response != null) {
        return response;
      } else {
        // Wenn null zurückkommt, war ein Fehler aufgetreten
        attempts++;
        debugPrint('Null-Antwort bei Versuch $attempts/$maxRetries');
      }
    } on SocketException catch (e) {
      lastSocketException = e;
      attempts++;

      debugPrint(
          'Socket-Fehler bei Versuch $attempts/$maxRetries: ${e.message}');

      // Spezielle Behandlung für typische Hintergrund-Socket-Fehler
      if (e.message.contains('Write failed') ||
          e.message.contains('connection abort') ||
          e.message.contains('Connection refused') ||
          e.message.contains('Software caused connection abort')) {
        debugPrint(
            'Erkannter Socket-Fehler im Hintergrund, warte vor Wiederversuch...');

        // Versuche die Verbindung zurückzusetzen
        try {
          final client = HttpClient();
          client.connectionTimeout = Duration(seconds: 30);
          client.idleTimeout = Duration(minutes: 2);
          client.close(force: true);
          debugPrint('HTTP-Client zurückgesetzt');
        } catch (resetError) {
          debugPrint(
              'Fehler beim Zurücksetzen des HTTP-Clients: $resetError');
        }
      }
    } catch (e) {
      attempts++;
      debugPrint(
          'Allgemeiner Fehler bei HTTP-Request (Versuch $attempts/$maxRetries): $e');
    }

    // Warte vor dem nächsten Versuch
    await Future.delayed(currentDelay);

    // Erhöhe die Wartezeit bei exponentiellem Backoff
    if (exponentialBackoff) {
      currentDelay *= 2;
    }
  }

  if (lastSocketException != null) {
    // Werfe den letzten Socket-Fehler, wenn wir hier angekommen sind
    throw lastSocketException;
  }

  debugPrint('Alle Wiederholungsversuche ausgeschöpft ohne Erfolg');
  return null; // Konsistent mit dem Rückgabewert von postJSON bei Fehlern
}