Add dio_smart_retry for automatic GET request retries

Transient network hiccups and temporary backend errors (5xx, timeouts)
now retry transparently up to twice (1 s then 3 s backoff) before
surfacing an error to the user. Non-idempotent methods (POST, PUT,
DELETE), cancellations, and non-retryable status codes are excluded.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
rzuasti
2026-05-31 17:19:00 -04:00
co-authored by Claude Sonnet 4.6
parent 7437b511ed
commit 838b292456
3 changed files with 30 additions and 0 deletions
+21
View File
@@ -1,6 +1,7 @@
import 'dart:io'; import 'dart:io';
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import 'package:dio_smart_retry/dio_smart_retry.dart';
import 'package:encrypter/encrypter/xor.dart'; import 'package:encrypter/encrypter/xor.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:frontend/utils/pref_utils.dart'; import 'package:frontend/utils/pref_utils.dart';
@@ -16,6 +17,25 @@ const _connectTimeout = Duration(seconds: 5);
const _receiveTimeout = Duration(seconds: 15); const _receiveTimeout = Duration(seconds: 15);
const _sendTimeout = Duration(seconds: 15); const _sendTimeout = Duration(seconds: 15);
const _retryableStatuses = {408, 429, 500, 502, 503, 504};
RetryInterceptor _buildRetryInterceptor(Dio dio) => RetryInterceptor(
dio: dio,
retries: 2,
retryDelays: const [Duration(seconds: 1), Duration(seconds: 3)],
logPrint: kDebugMode ? (msg) => debugPrint(msg.toString()) : null,
retryEvaluator: (error, attempt) {
if (error.requestOptions.method != 'GET') return false;
if (error.type == DioExceptionType.cancel) return false;
if (error.error is FormatException) return false;
if (error.type == DioExceptionType.badResponse) {
final status = error.response?.statusCode;
return status != null && _retryableStatuses.contains(status);
}
return true;
},
);
LogInterceptor _buildLogInterceptor() => LogInterceptor( LogInterceptor _buildLogInterceptor() => LogInterceptor(
request: true, request: true,
requestHeader: false, requestHeader: false,
@@ -87,6 +107,7 @@ class BackendAPI {
}, },
), ),
); );
_dio.interceptors.add(_buildRetryInterceptor(_dio));
if (kDebugMode) { if (kDebugMode) {
_dio.interceptors.add(_buildLogInterceptor()); _dio.interceptors.add(_buildLogInterceptor());
} }
+8
View File
@@ -89,6 +89,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.9.1" version: "5.9.1"
dio_smart_retry:
dependency: "direct main"
description:
name: dio_smart_retry
sha256: c8e20da5f49289fa7dce5c9c6b5b120928e3661aefa0fa2d206ea6d93f580928
url: "https://pub.dev"
source: hosted
version: "7.0.1"
dio_web_adapter: dio_web_adapter:
dependency: transitive dependency: transitive
description: description:
+1
View File
@@ -13,6 +13,7 @@ dependencies:
intl: ^0.20.2 intl: ^0.20.2
provider: ^6.1.5 provider: ^6.1.5
dio: ^5.9.1 dio: ^5.9.1
dio_smart_retry: ^7.0.1
encrypter: ^2.0.0 encrypter: ^2.0.0
shared_preferences: ^2.5.4 shared_preferences: ^2.5.4
fl_chart: ^1.2.0 fl_chart: ^1.2.0