llfbandit / dio_cache_interceptor

Dio HTTP cache interceptor with multiple stores respecting HTTP directives (ETag, Last-Modified, Cache-Control) with options.
https://pub.dev/packages/dio_cache_interceptor
120 stars 70 forks source link

Feature request: Isar cache store #122

Closed vtisnado closed 11 months ago

vtisnado commented 1 year ago

Hi guys, it will be interesting to add Isar as cache store. Have you seen it?

willsalasare commented 1 year ago

I hope so too, for now I use this basic code, it has worked well for me

cache_interceptor.dart

class CacheInterceptor extends Interceptor {
  CacheInterceptor({this.expires, required this.enableCache});
  final Duration? expires;
  final bool enableCache;
  @override
  void onRequest(
      RequestOptions options, RequestInterceptorHandler handler) async {
    if (options.method != 'GET' || !enableCache) {
      handler.next(options);
      return;
    }
    final cache = await CacheService.get(options.uri.toString());
    if (cache == null) {
      handler.next(options);
      return;
    }
    handler.resolve(Response(
      requestOptions: options,
      headers: _getHeaders(cache.headers),
      statusCode: cache.statusCode,
      data: jsonDecode(cache.data!),
    ));
  }

  Headers _getHeaders(data) {
    final Map<String, dynamic> headersE = jsonDecode(data);
    final headers =
        headersE.map((key, value) => MapEntry(key, List<String>.from(value)));
    return Headers.fromMap(headers);
  }

  @override
  void onResponse(Response response, ResponseInterceptorHandler handler) {
    if (response.requestOptions.method != 'GET' || !enableCache) {
      handler.next(response);
      return;
    }
    CacheService.store(response, expires: expires);
    handler.next(response);
  }
}

cache_service.dart

class CacheService {
  static void store(
    Response response, {
    Duration? expires,
  }) async {
    final isar = await IsarService.db();
    await isar.writeTxn(() async => isar.caches.putByKey(
          Cache()
            ..key = response.requestOptions.uri.toString()
            ..data = jsonEncode(response.data)
            ..expires = DateTime.now().add(expires ?? const Duration(hours: 2))
            ..statusCode = response.statusCode
            ..headers = jsonEncode(response.headers.map),
        ));
  }

  static Future<Cache?> get(String key) async {
    final isar = await IsarService.db();
    final cache = await isar.caches.getByKey(key);
    if (cache == null) return null;
    if (DateTime.now().isAfter(cache.expires)) {
      await isar.writeTxn(() async => await isar.caches.deleteByKey(key));
      return null;
    }

    return cache;
  }
}

cache.dart

@collection
class Cache {
  Id id = Isar.autoIncrement;
  @Index(unique: true)
  late String key;
  String? data;
  late String headers;
  int? statusCode;
  DateTime expires = DateTime.now().add(const Duration(hours: 2));
}
llfbandit commented 1 year ago

Creating a store is really easy. Please, fill free to submit a PR to add it to the list. You can get reference from the other implementations. This is basically get and set operations in stores.

jackwill99 commented 1 year ago

Did anyone submitted to use cache with Isar ??

tusharbhambere commented 1 year ago

any update on this?

vtisnado commented 1 year ago

I desisted to use Isar and got back to Hive, but the code @willsalasare shared looks promising.

tusharbhambere commented 1 year ago

@llfbandit as we need proper implementation Isar with extends CacheStore @willsalasare code is basic

dio_cache_interceptor have more features

tusharbhambere commented 1 year ago

+1

llfbandit commented 11 months ago

Isar store is now availble here