LCOV - code coverage report
Current view: top level - src/network - NetworkRetryPolicy.cpp (source / functions) Coverage Total Hit
Test: coverage.info.cleaned Lines: 77.0 % 74 57
Test Date: 2026-01-27 22:31:25 Functions: 87.5 % 8 7

            Line data    Source code
       1              : #include "NetworkRetryPolicy.h"
       2              : #include <algorithm>
       3              : #include <cmath>
       4              : 
       5            0 : NetworkRetryPolicy::NetworkRetryPolicy()
       6            0 :     : maxNumRetries(0)
       7            0 :     , defaultDelayMs(1000)
       8            0 :     , maxDelayMs(60000)
       9            0 :     , strategy(Exponential)
      10            0 :     , shouldRetryOnTimeout(true)
      11            0 :     , shouldRetryOnDnsFailure(true)
      12            0 :     , shouldRetryOnConnectionRefused(true)
      13            0 :     , shouldRetryOnServerError(true)
      14              : {
      15            0 : }
      16              : 
      17           43 : NetworkRetryPolicy::NetworkRetryPolicy(int maxRetries, int baseDelay, BackoffStrategy strategy, int maxDelay)
      18           43 :     : maxNumRetries(maxRetries)
      19           43 :     , defaultDelayMs(baseDelay)
      20           43 :     , maxDelayMs(maxDelay)
      21           43 :     , strategy(strategy)
      22           43 :     , shouldRetryOnTimeout(true)
      23           43 :     , shouldRetryOnDnsFailure(true)
      24           43 :     , shouldRetryOnConnectionRefused(true)
      25           43 :     , shouldRetryOnServerError(true)
      26              : {
      27           43 : }
      28              : 
      29            4 : NetworkRetryPolicy NetworkRetryPolicy::forFeedUpdate()
      30              : {
      31              :     // Medium importance: 3 retries with exponential backoff: 2s, 4s, 8s
      32            4 :     return NetworkRetryPolicy(3, 2000, Exponential, 30000);
      33              : }
      34              : 
      35            1 : NetworkRetryPolicy NetworkRetryPolicy::forFavicon()
      36              : {
      37              :     // Non-critical: 2 retries with linear backoff: 1s, 2s
      38            1 :     return NetworkRetryPolicy(2, 1000, Linear, 5000);
      39              : }
      40              : 
      41            1 : NetworkRetryPolicy NetworkRetryPolicy::forCritical()
      42              : {
      43              :     // Give it our best shot: 5 retries with fibonacci backoff: 1s, 2s, 3s, 5s, 8s
      44            1 :     return NetworkRetryPolicy(5, 1000, Fibonacci, 60000);
      45              : }
      46              : 
      47           25 : NetworkRetryPolicy NetworkRetryPolicy::noRetry()
      48              : {
      49           25 :     return NetworkRetryPolicy(0, 0, Fixed, 0);
      50              : }
      51              : 
      52           30 : bool NetworkRetryPolicy::isRetryable(QNetworkReply::NetworkError error) const
      53              : {
      54           30 :     switch (error) {
      55              :     // Network errors
      56            1 :     case QNetworkReply::ConnectionRefusedError:
      57            1 :         return shouldRetryOnConnectionRefused;
      58              : 
      59            2 :     case QNetworkReply::RemoteHostClosedError:
      60              :     case QNetworkReply::HostNotFoundError:
      61            2 :         return shouldRetryOnDnsFailure;
      62              : 
      63           14 :     case QNetworkReply::TimeoutError:
      64              :     case QNetworkReply::OperationCanceledError:
      65           14 :         return shouldRetryOnTimeout;
      66              : 
      67            3 :     case QNetworkReply::TemporaryNetworkFailureError:
      68              :     case QNetworkReply::NetworkSessionFailedError:
      69              :     case QNetworkReply::BackgroundRequestNotAllowedError:
      70            3 :         return true;
      71              : 
      72              :     // Don't retry at all for SSL errors
      73            2 :     case QNetworkReply::SslHandshakeFailedError:
      74              :     case QNetworkReply::UnknownServerError:
      75            2 :         return false;
      76              : 
      77              :     // Protocol errors are also not retryable (is that a word?)
      78            2 :     case QNetworkReply::ProtocolUnknownError:
      79              :     case QNetworkReply::ProtocolInvalidOperationError:
      80              :     case QNetworkReply::ProtocolFailure:
      81            2 :         return false;
      82              : 
      83              :     // HTTP-specific errors
      84            2 :     case QNetworkReply::InternalServerError:
      85              :     case QNetworkReply::ServiceUnavailableError:
      86            2 :         return shouldRetryOnServerError;
      87              : 
      88              :     // Oddball errors that we should try again ASAP
      89            0 :     case QNetworkReply::UnknownNetworkError:
      90              :     case QNetworkReply::UnknownProxyError:
      91              :     case QNetworkReply::UnknownContentError:
      92            0 :         return true;
      93              : 
      94              :     // No point in retrying these
      95            4 :     case QNetworkReply::ContentAccessDenied:
      96              :     case QNetworkReply::ContentNotFoundError:
      97              :     case QNetworkReply::AuthenticationRequiredError:
      98              :     case QNetworkReply::ContentOperationNotPermittedError:
      99            4 :         return false;
     100              : 
     101            0 :     case QNetworkReply::NoError:
     102            0 :         return false;
     103              : 
     104            0 :     default:
     105              :         // Retry by default
     106            0 :         return true;
     107              :     }
     108              : }
     109              : 
     110           33 : int NetworkRetryPolicy::calculateDelay(int attemptNumber) const
     111              : {
     112           33 :     if (attemptNumber >= maxNumRetries) {
     113            0 :         return 0;
     114              :     }
     115              : 
     116              :     int delay;
     117              : 
     118           33 :     switch (strategy) {
     119            4 :     case Linear:
     120            4 :         delay = defaultDelayMs * (attemptNumber + 1);
     121            4 :         break;
     122              : 
     123            7 :     case Exponential:
     124            7 :         delay = static_cast<int>(defaultDelayMs * std::pow(2, attemptNumber));
     125            7 :         break;
     126              : 
     127            6 :     case Fibonacci: {
     128              :         // Math alert! Find the next Fibonacci number for this attempt.
     129            6 :         int fib1 = 1, fib2 = 1;
     130           16 :         for (int i = 0; i < attemptNumber; ++i) {
     131           10 :             int temp = fib1 + fib2;
     132           10 :             fib1 = fib2;
     133           10 :             fib2 = temp;
     134              :         }
     135            6 :         delay = defaultDelayMs * fib2;
     136            6 :         break;
     137              :     }
     138              : 
     139           16 :     case Fixed:
     140              :     default:
     141           16 :         delay = defaultDelayMs;
     142           16 :         break;
     143              :     }
     144              : 
     145              :     // Max delay.
     146           33 :     return std::min(delay, maxDelayMs);
     147              : }
        

Generated by: LCOV version 2.0-1