smart_request 0.2.0 copy "smart_request: ^0.2.0" to clipboard
smart_request: ^0.2.0 copied to clipboard

A lightweight Dart package for resilient API calls with retry, backoff, timeout, and fallback.

Pub Version Pub Likes Pub Points Popularity Dart SDK License: MIT

Smart Request #

Lightweight, dependency-free retries with exponential backoff, timeout, and optional fallback for any async operation.

Works with any HTTP client (Dio, http), GraphQL, gRPC, database calls, or your own async functions.

Features #

  • Retry with backoff: exponential factor, max delay, and optional jitter
  • Timeout per attempt: wrap each try in a timeout
  • Fallback support: switch to an alternate function when retries are exhausted
  • Callbacks: onError, onRetry
  • Custom retry predicate: decide which errors are transient
  • Built-in offline cache manager: noCache, cacheFirst, cacheAndRefresh

Install #

Add to your pubspec.yaml:

dependencies:
  smart_request: ^0.1.0

Quick start (Dio) with cache #

import 'dart:async';
import 'package:dio/dio.dart';
import 'package:smart_request/smart_request.dart';

Future<void> main() async {
  final dio = Dio();
  final cache = MemoryCacheStore<Response<dynamic>>();
  const url = 'https://jsonplaceholder.typicode.com/posts/1';

  try {
    final response = await smartRequest<Response<dynamic>>(
      () => dio.get(url),
      fallback: () => dio.get('https://jsonplaceholder.typicode.com/posts/2'),
      config: SmartRequestConfig(
        maxRetries: 3,
        initialDelay: const Duration(milliseconds: 500),
        maxDelay: const Duration(seconds: 8),
        backoffFactor: 2.0,
        jitter: true,
        timeout: const Duration(seconds: 5),
        onError: (e, s) => print('Error: $e'),
        onRetry: (attempt, nextDelay, e, s) =>
            print('Retry #$attempt after $nextDelay due to $e'),
        shouldRetry: (_) => true,
      ),
      // Scenario 3: return cache and refresh in background
      cacheConfig: const CacheConfig(
        policy: CachePolicy.cacheAndRefresh,
        ttl: Duration(minutes: 10),
      ),
      cacheKey: defaultCacheKeyBuilder(CacheKeyParts(
        method: 'GET',
        url: url,
        query: const {},
        headers: const {},
        varyHeaders: const ['authorization'],
      )),
      cacheStore: cache,
      onRefresh: (value) {
        print('πŸ”„ Background refreshed cache with latest data');
      },
    );

    print('βœ… First return (cache or network): ${response.data}');
  } catch (e) {
    print('❌ Final error: $e');
  }
}

API #

typedef RequestFunc<T> = Future<T> Function();

Future<T> smartRequest<T>(
  RequestFunc<T> request, {
  RequestFunc<T>? fallback,
  SmartRequestConfig config = const SmartRequestConfig(),
  CacheConfig cacheConfig = const CacheConfig(),
  String? cacheKey,
  CacheStore<T>? cacheStore,
  FutureOr<void> Function(T value)? onRefresh,
});

SmartRequestConfig #

Field Type Default Description
maxRetries int 3 Number of retries. Total attempts = 1 + maxRetries.
initialDelay Duration 1s Delay before the first retry.
maxDelay Duration 30s Maximum backoff delay cap.
backoffFactor double 2.0 Exponential growth factor for delay.
jitter bool true Adds Β±50% randomness to each delay.
timeout Duration 30s Per-attempt timeout (applies to fallback too).
onError FutureOr null Called on every error before retry decision.
onRetry FutureOr null Called before waiting for the next retry.
shouldRetry bool Function(Object error)? true (all errors) Decides if an error is retryable.
fallbackOn bool Function(Object error)? true Whether to use fallback when retries are exhausted.

Example app #

See example/lib/main.dart for a runnable example using Dio.

CacheConfig #

Field Type Default Description
policy CachePolicy noCache Caching strategy: noCache, cacheFirst, cacheAndRefresh.
ttl Duration? null Time-to-live for entries. null means never expire.

Cache keys #

For robust caching you often need more than just the URL. Build a key using:

  • method: GET/POST/etc
  • url: canonical base URL
  • query: sorted query params
  • body: canonicalized request payload (for POST/PUT)
  • headers: only selected headers (e.g., Authorization) via varyHeaders

Helper:

final key = defaultCacheKeyBuilder(CacheKeyParts(
  method: 'POST',
  url: 'https://api.example.com/items',
  query: {'page': 1, 'sort': 'asc'},
  body: {'name': 'abc', 'tags': ['x', 'y']},
  headers: {'authorization': 'Bearer ...', 'accept': 'application/json'},
  varyHeaders: ['authorization'],
));

License #

MIT

0
likes
160
points
39
downloads

Publisher

verified publishermwaqas.mobvers.com

Weekly Downloads

A lightweight Dart package for resilient API calls with retry, backoff, timeout, and fallback.

Repository (GitHub)
View/report issues

Topics

#http #retry #backoff #networking

Documentation

API reference

License

MIT (license)

More

Packages that depend on smart_request