Flexible retry library for Dio package

Related tags

Utilities dio-retry
Overview

Pub Version Dart SDK Version style: very good analysis License

Dio Smart Retry

Flexible retry library for Dio package. This is a next generation of an abandoned dio_retry package.
By default, the request will be retried only for appropriate retryable http statuses.
Also, it supports dynamic delay between retries.
Null Safety.

Getting started

  1. Add package to pubspec.yaml: dio_smart_retry: ^1.2.0
  2. Import package: import 'package:dio_smart_retry/dio_smart_retry.dart'

Usage

Just add an interceptor to your dio:

final dio = Dio();
// Add the interceptor
dio.interceptors.add(RetryInterceptor(
  dio: dio,
  logPrint: print, // specify log function (optional)
  retries: 3, // retry count (optional)
  retryDelays: const [ // set delays between retries (optional)
    Duration(seconds: 1), // wait 1 sec before first retry
    Duration(seconds: 2), // wait 2 sec before second retry
    Duration(seconds: 3), // wait 3 sec before third retry
  ],
));

/// Sending a failing request for 3 times with 1s, then 2s, then 3s interval
await dio.get('https://mock.codes/500');

See example/dio_smart_retry_example.dart.

Default retryable status codes list

Responses with these http status codes will be retried by default:

  • 408: RequestTimeout
  • 429: TooManyRequests
  • 500: InternalServerError
  • 502: BadGateway
  • 503: ServiceUnavailable
  • 504: GatewayTimeout
  • 440: LoginTimeout (IIS)
  • 460: ClientClosedRequest (AWS Elastic Load Balancer)
  • 499: ClientClosedRequest (ngnix)
  • 520: WebServerReturnedUnknownError
  • 521: WebServerIsDown
  • 522: ConnectionTimedOut
  • 523: OriginIsUnreachable
  • 524: TimeoutOccurred
  • 525: SSLHandshakeFailed
  • 527: RailgunError
  • 598: NetworkReadTimeoutError
  • 599: NetworkConnectTimeoutError

Disable retry

It's possible to manually disable retry for a specified request. Use disableRetry extension for that:

final request = RequestOptions(path: '/')
  ..disableRetry = true;
await dio.fetch<String>(request);
Comments
  • on retry callback

    on retry callback

    if possible can an on retry callback is called with the status of the request

    (using it to let user know that request failed and the code is retrying)

    documentation 
    opened by zezo357 7
  • RetryInterceptor.onError - exceptions handling

    RetryInterceptor.onError - exceptions handling

    Hi @rodion-m I have tried to use your library in my project. I have several tests of my communication layer including test for incorrect url. Unfortunately test stops working after adding your interceptor. Here is what I have discovered. RetryInterceptor.onError do not handling errors that could arise in this method. For example in my case I have had incorrect url (http ://github.com with spaces) that makes troubles when I am specifying logPrint function. Interceptor prepare output string for logPrint function and call err.requestOptions.uri which throws exception FormatException: Illegal scheme character (at character 5). This exception bubble out without corresponding handling.

    The solution could be simple in my case, just use path instead of uri or something similar in that direction. But I propose you to think about general error handling to avoid issues for example when _retryEvaluator could throw an error.

    opened by solikhver 4
  • Manually add status codes for retry

    Manually add status codes for retry

    Would it be possible to add specific status codes beside the default codes to 'dio_smart_retry'? For example I would like to retry on status code 401, but it is not included. Please add an option to set optional status codes. Thank you!

    opened by awwwer 3
  • [Feature] Override default retryable status codes list

    [Feature] Override default retryable status codes list

    We use an API that returns no default HTTP Status Codes for a lot of cases.

    There is no way to change the API, so would be nice to be able to override the default status codes that should retry.

    Related: https://github.com/rodion-m/dio_smart_retry/issues/11

    opened by adelarsq 2
  • RetryInterceptor changes responseType to json

    RetryInterceptor changes responseType to json

    Hi!

    I dont know if im doing something wrong, but if i set the responseType to ResponseType.plain and the RetryInterceptor is executed after a timeout, the interceptor seems to set the responseType to ResponseType.json.

    Example:

    ``

    final dio = Dio(
      BaseOptions(
        baseUrl: rootUri,
        connectTimeout: 3000,
        receiveTimeout: 5000,
        headers: headers,
        responseType: ResponseType.plain,
      ),
    );
    
    dio.interceptors.add(
      RetryInterceptor(
        dio: dio,
        logPrint: log, // specify log function (optional)
        retryDelays: const [
          Duration(seconds: 3), // wait 1 sec before first retry
          Duration(seconds: 5), // wait 2 sec before second retry
          Duration(seconds: 10), // wait 3 sec before third retry
        ],
      ),
    );
    
    try {
      response = await dio.get(url);
    ...
    

    If there is no timeout, everything works fine.

    Any ideas?

    Thanks!

    opened by danielcmm 2
  • Not an issue but need help implementing it the right way

    Not an issue but need help implementing it the right way

    retry package works great if there is an error on initial request it goes into retry mode and if its successful retry does not happen

    so I wanted to see what happens if server is down and midway turns on

    • I closed the server
    • retry package started retrying I set retry to 3
    • when the attempt number was 1 I turned on the server but then It still kept retrying

    ` Future uploadImage( {required File file, required Function onProgressUpdate}) async { Response? response;

    var dio = Dio();
    
    dio.interceptors.addAll([
      ///For Logging
      PrettyDioLogger(
          requestHeader: true,
          requestBody: true,
          responseBody: true,
          responseHeader: false,
          error: true,
          compact: true,
          maxWidth: 90),
    
      ///For Retrying
      RetryInterceptor(
        retryEvaluator: (DioError error, int attempt) {
          print('---------Rety Intercept Start---------');
          print('inty');
          print(attempt);
          ScaffoldMessenger.of(context).clearSnackBars();
          timerSnackbar(
            backgroundColor: Colors.black,
            context: context,
            buttonLabel: '',
            contentText:
                "Error ${error.error} - Attempt ${attempt.toString()} of 3",
            // buttonPrefixWidget: Image.asset(
            //   'assets/undo.png',
            //   width: 17.0,
            //   height: 15.0,
            //   alignment: Alignment.topCenter,
            //   color: Colors.blue[100],
            // ),
            afterTimeExecute: () => print("Operation Execute."),
            second: 5,
          );
    
          print('dioError');
          print(error.error.toString());
          print('---------Rety Intercept End---------');
          return true;
        },
        dio: dio,
        logPrint: print, // specify log function (optional)
        retries: 3, // retry count (optional)
        retryDelays: const [
          // set delays between retries (optional)
          Duration(seconds: 10), // wait 10 sec before first retry
          Duration(seconds: 10), // wait 10 more sec before second retry
          Duration(seconds: 10), // wait 10 more sec before third retry
          ///You can use timer snackbar package and show time before sending attempt again
        ],
      )
    ]);
    String fileName = file.path.split('/').last;
    FormData formData = FormData.fromMap({
      "image": await MultipartFile.fromFile(file.path, filename: fileName),
    });
    
    response = await dio.post(
      "http://127.0.0.1:8000/uploadImage/",
      data: formData,
      onSendProgress: (v1, v2) {
        ///v2 is the total size of file
        ///v1 is the current progress
        /// example output  v1 value is 590007 v2 value is 630413
        print('v1 value is ${v1.toString()}');
        print('v2 value is ${v2.toString()}');
    
        onProgressUpdate(((v1 / v2) * 100).toStringAsFixed(2));
      },
      onReceiveProgress: (v1, v2) {
        print('v1 from recieveProgress $v1');
        print('v2 from recieveProgress $v2');
      },
      options: Options(
        followRedirects: false,
      ),
    );
    print(response.data);
    print(response.statusMessage);
    return await response.data;
    

    }`

    At first I get web socket error then I get 'Cant finalise a finalised multipart'

    Also I was testing cancel token and if token is cancel it still retry is there a way I cancel retry via a function

    opened by officialFlutterDeveloper 2
  • disableRetry doesn't seem to work

    disableRetry doesn't seem to work

    Hello I have tried to use the disableRetry but it isn't working correctly.

    This is my dio request

    final requestOptions = RequestOptions(
          method: method,
          baseUrl: _dio.options.baseUrl,
          path: path,
          headers: headers,
          data: data,
          queryParameters: queryParameters,
          onSendProgress: onSendProgress,
          onReceiveProgress: onReceiveProgress,
          extra: {
            'Test': 'This is an extra test'
          },
        )..disableRetry = true;
    return _dio.fetch(requestOptions);
    

    I have looked into the problem and it looks as though the extra on the requestOptions is empty on the onError override of the interceptor.

    @override
      Future onError(DioError err, ErrorInterceptorHandler handler) async {
        print(err.requestOptions.extra); //<--- this is always empty even when extra parameters are added.
    }
    

    Not sure if its a dio issue.

    opened by chaser79 2
  • when request is canceled

    when request is canceled

    when request is canceled using cancelToken the retries keep going instead of stopping

    what i think should happed is the to check if the request cancle token was canceled before trying again

    opened by zezo357 1
  • dart analysis:

    dart analysis: "Don't import implementation files from another package."

    Hello, I'm pleasure to using your open source. I want you to know A lint warning is occurs at the line of code below.

    import 'package:dio_smart_retry/dio_smart_retry.dart';
    import 'package:dio_smart_retry/src/http_status_codes.dart';
    

    So I had to change it like this

    import 'package:dio_smart_retry/dio_smart_retry.dart';
    // ignore_for_file: implementation_imports
    import 'package:dio_smart_retry/src/http_status_codes.dart' as dio_smart_retry;
    

    My flutter doctor -v is

    [✓] Flutter (Channel stable, 3.3.2, on macOS 12.6 21G115 darwin-arm, locale en-KR)
        • Flutter version 3.3.2 on channel stable at /Users/9oya/flutter
        • Upstream repository https://github.com/flutter/flutter.git
        • Framework revision e3c29ec00c (12 days ago), 2022-09-14 08:46:55 -0500
        • Engine revision a4ff2c53d8
        • Dart version 2.18.1
        • DevTools version 2.15.0
    

    I think the source code for the status code in http_status_codes.dart could be improved. Thank you.

    opened by 9oya 0
  • Bad state: Can't finalize a finalized MultipartFile

    Bad state: Can't finalize a finalized MultipartFile

    Hi,

    I'm using the latest packages:

    dio: ^4.0.6
    dio_smart_retry: ^1.3.2
    

    When I post a file to the server and, it accepts only after first attemp, the error occours... here a simplified code:

        Dio dio = Dio(BaseOptions(
          baseUrl: ("https://$domain$base"),
        );
    
        dio.interceptors.add(
            RetryInterceptor(
              dio: dio,
              logPrint: print, // specify log function (optional)
              retries: 3, // retry count (optional)
              retryDelays: const [
                // set delays between retries (optional)
                Duration(seconds: 1), // wait 1 sec before first retry
                Duration(seconds: 2), // wait 2 sec before second retry
                Duration(seconds: 3), // wait 3 sec before third retry
              ],
            ),
          );
    
        final bytes = await cameraFile!.readAsBytes();
        final MultipartFile file = MultipartFile.fromBytes(bytes, filename: "teste");
        MapEntry<String, MultipartFile> a = MapEntry('teste', file);
    
        var options = FormData.fromMap({
          "bla": "bla",
        });
    
        options.files.add(a);
    
        var data = await dio.post("/post_test", data: options);
    
    opened by aweiand 10
Owner
Rodion Mostovoy
An independent software developer and musician.
Rodion Mostovoy
Fluro is a Flutter routing library that adds flexible routing options like wildcards, named parameters and clear route definitions.

Fluro is a Flutter routing library that adds flexible routing options like wildcards, named parameters and clear route definitions.

Luke Pighetti 3.5k Jan 4, 2023
Dio Package in Flutter - HTTP Requests and Interceptors.

Dio Package in Flutter - HTTP Requests and Interceptors. Learn how to use Flutter Dio package to make http requests, deal with interceptors and take care of unexpected server responses and failures in Flutter apps.

Sandip Pramanik 14 Nov 18, 2022
A simple flexible API wrapper for coinbase commerce API. Totally unofficial.

coinbase_commerce A dart library that connects to interact with the Coinbase Commerce API. Enables projects to connect seamlessly to coinbase and rece

Onuoha Obinna 3 Oct 17, 2021
Dependency Injection is a great design pattern that allows us to eliminate rigid dependencies between elements and it makes the application more flexible

GetX lib DI pattern Dependency Injection is a great design pattern that allows us to eliminate rigid dependencies between elements and it makes the ap

Trương Việt Hoàng 4 Feb 1, 2022
A Flutter curl-command generator for Dio

curl_logger_dio_interceptor A Flutter curl-command generator for Dio. Easily test your Flutter-made requests in your favorite terminal or even in Post

null 7 Nov 17, 2022
Fetch Data From fakestoreapi.com Api Using Dio

A powerful Http client for Dart, which supports Interceptors, Global configuration, FormData, Request Cancellation, File downloading, Timeout etc

Bouziani Mohammed 6 Oct 26, 2022
A package that lets you include a cool, nice looking and validated Password TextFormField in your app to enhance user experience. The package is fully & easily modifiable.

A package that lets you include a cool, nice looking and validated Password TextFormField in your app to enhance user experience. The package is fully

Muhammad Hamza 20 Jun 7, 2022
A Dart package which supports checking if a current package is up-to-date.

pub_updater A Dart package which enables checking whether packages are up to date and supports updating them. Intended for use in CLIs for prompting u

Very Good Open Source 47 Oct 27, 2022
null 2 Apr 17, 2022
A Dart library to parse Portable Executable (PE) format

pefile A Dart library to parse Portable Executable (PE) format Usage A simple usage example: var pe = pefile.parse('C:\\Windows\\System32\\notepad.exe

null 4 Sep 12, 2022
This library contains methods that make it easy to consume Mpesa Api.

This library contains methods that make it easy to consume Mpesa Api. It's multi-platform, and supports CLI, server, mobile, desktop, and the browser.

Eddie Genius 3 Dec 15, 2021
Scribble is a lightweight library for freehand drawing in Flutter supporting pressure, variable line width and more!

Scribble Scribble is a lightweight library for freehand drawing in Flutter supporting pressure, variable line width and more! A

Tim Created It. 73 Dec 16, 2022
An alternative random library for Dart.

Randt Randt library for Dart... Description Use Randt to get a random integer from a list, generate random integer in a specific range and generate ra

Bangladesh Coding Soldierz 3 Nov 21, 2021
A library for YAML manipulation with comment and whitespace preservation.

Yaml Editor A library for YAML manipulation while preserving comments. Usage A simple usage example: import 'package:yaml_edit/yaml_edit.dart'; void

Dart 17 Dec 26, 2022
The Dart Time Machine is a date and time library for Flutter, Web, and Server with support for timezones, calendars, cultures, formatting and parsing.

The Dart Time Machine is a date and time library for Flutter, Web, and Server with support for timezones, calendars, cultures, formatting and parsing.

null 2 Oct 8, 2021
A comprehensive, cross-platform path manipulation library for Dart.

A comprehensive, cross-platform path manipulation library for Dart. The path package provides common operations for manipulating paths: joining, split

Dart 159 Dec 29, 2022
Boilerplate-free form validation library

Valform Boilerplate-free form validation library. Preface Why? Why not Formz? Why Valform? Getting started Simple Usage Inspiration Why? There is no c

Alexander Farkas 3 Nov 14, 2021
Boilerplate-free form validation library

Trigger Boilerplate-free form validation library. Preface Why? Why not Formz? Why Trigger? Getting started Simple Usage Inspiration Why? There is no c

Alexander Farkas 3 Nov 14, 2021