From e3fd1a842831e6d38102e768471420eb9c936325 Mon Sep 17 00:00:00 2001 From: Sebastine Odeh Date: Sun, 4 May 2025 11:53:35 +0100 Subject: [PATCH 1/3] refactor: rename files and update method signatures; add tests for cache functionality --- CHANGELOG.md | 5 + lib/cache_manager_plus.dart | 3 +- lib/src/{cache => }/cache_item.dart | 4 +- lib/src/{cache => }/cache_store.dart | 8 ++ lib/src/in_memory_store.dart | 46 ++++++-- lib/src/{cache => }/manager.dart | 44 +++++--- lib/src/{cache/cache.dart => src.dart} | 1 + pubspec.yaml | 4 +- test/cache_item_test.dart | 35 ++++++ test/cache_manager_test.dart | 63 ++++++++++- test/multi_store_manager_test.dart | 144 ++++++++++++++++--------- 11 files changed, 275 insertions(+), 82 deletions(-) rename lib/src/{cache => }/cache_item.dart (97%) rename lib/src/{cache => }/cache_store.dart (91%) rename lib/src/{cache => }/manager.dart (86%) rename lib/src/{cache/cache.dart => src.dart} (76%) create mode 100644 test/cache_item_test.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index 7fec8c9..b5260e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.1.0 + +- changed method signature from `hasCacheItemExpired` to `isCacheItemExpired` +- expose a where API which takes a key and a predicate for more conditional CacheStore filtering + ## 1.0.2 - moved cache utils to its own package diff --git a/lib/cache_manager_plus.dart b/lib/cache_manager_plus.dart index 6b532e8..9c5f79c 100644 --- a/lib/cache_manager_plus.dart +++ b/lib/cache_manager_plus.dart @@ -1,4 +1,3 @@ library; -export 'src/cache/cache.dart'; -export 'src/in_memory_store.dart'; +export 'src/src.dart'; diff --git a/lib/src/cache/cache_item.dart b/lib/src/cache_item.dart similarity index 97% rename from lib/src/cache/cache_item.dart rename to lib/src/cache_item.dart index 71c29d1..9cc20a2 100644 --- a/lib/src/cache/cache_item.dart +++ b/lib/src/cache_item.dart @@ -31,8 +31,6 @@ final class CacheItem { bool get isValid => !isExpired; - bool get isInvalid => !isValid; - String toCacheEntryString() { return jsonEncode({ 'expiry': expiry.toIso8601String(), @@ -79,6 +77,8 @@ final class CacheItem { other.expiry == expiry; } + //coverage:ignore-start @override int get hashCode => key.hashCode ^ data.hashCode ^ expiry.hashCode; + //coverage:ignore-end } diff --git a/lib/src/cache/cache_store.dart b/lib/src/cache_store.dart similarity index 91% rename from lib/src/cache/cache_store.dart rename to lib/src/cache_store.dart index e345525..5ecd7de 100644 --- a/lib/src/cache/cache_store.dart +++ b/lib/src/cache_store.dart @@ -1,3 +1,5 @@ +//coverage:ignore-file + import 'dart:async'; import '../../cache_manager_plus.dart'; @@ -79,4 +81,10 @@ abstract interface class CacheStore { /// /// ``` bool containsKey(String key); + + /// contract requirement for closing the cache store + /// helpful to allow stores be closed safely to prevent memory leaks. + /// When implemented, the client should have to reinitialise the store to read + /// its content + FutureOr close(); } diff --git a/lib/src/in_memory_store.dart b/lib/src/in_memory_store.dart index aa6839d..ded54e0 100644 --- a/lib/src/in_memory_store.dart +++ b/lib/src/in_memory_store.dart @@ -1,28 +1,47 @@ -import 'cache/cache.dart'; +import 'dart:async'; + +import 'cache_item.dart'; +import 'cache_store.dart'; final class InMemoryCacheStore implements CacheStore { InMemoryCacheStore(); - late final Map _store; + Map? _store; @override Future get cacheVersion async { - return int.parse(_store['version'] ?? '-1'); + if (_store == null) + throw StateError( + 'Store not initialised, did you fail to initialise the store?'); + + return int.parse(_store!['version'] ?? '-1'); } @override Future updateCacheVersion(int version) async { - _store['version'] = version.toString(); + if (_store == null) + throw StateError( + 'Store not initialised, did you fail to initialise the store?'); + + _store!['version'] = version.toString(); } @override bool containsKey(String key) { - return _store.containsKey(key); + if (_store == null) + throw StateError( + 'Store not initialised, did you fail to initialise the store?'); + + return _store!.containsKey(key); } @override Future getCacheItem(String key) async { - final item = _store[key]; + if (_store == null) + throw StateError( + 'Store not initialised, did you fail to initialise the store?'); + + final item = _store![key]; if (item == null) return null; return CacheItem.fromCacheEntryString(item, key: key); @@ -30,12 +49,16 @@ final class InMemoryCacheStore implements CacheStore { @override Future initialiseStore() async { - _store = {}; + _store ??= {}; } @override Future invalidateCache() async { - return _store.clear(); + if (_store == null) + throw StateError( + 'Store not initialised, did you fail to initialise the store?'); + + return _store!.clear(); } @override @@ -49,6 +72,11 @@ final class InMemoryCacheStore implements CacheStore { @override Future saveCacheItem(CacheItem item) async { - _store[item.key] = item.toCacheEntryString(); + _store![item.key] = item.toCacheEntryString(); + } + + @override + FutureOr close() { + _store = null; } } diff --git a/lib/src/cache/manager.dart b/lib/src/manager.dart similarity index 86% rename from lib/src/cache/manager.dart rename to lib/src/manager.dart index 3c23ef0..a25d6e1 100644 --- a/lib/src/cache/manager.dart +++ b/lib/src/manager.dart @@ -40,14 +40,11 @@ final class CacheManager { List stores = const [], bool forceInit = false, }) async { - assert(store != null || stores.isNotEmpty, - 'At least one store must be provided'); - - if (store == null && stores.isEmpty) { + if (store == null && stores.isEmpty) throw ArgumentError('At least one store must be provided'); - } if (forceInit) { + await close(); // safe closes all stores _instance = CacheManager._(); } else { if (_instance != null) { @@ -57,18 +54,39 @@ final class CacheManager { _instance ??= CacheManager._(); } - _instance!._stores = { - if (store != null) store.runtimeType.toString(): store, - for (final store in stores) store.runtimeType.toString(): store, - }; + _instance!._stores = {}; + if (store case final CacheStore s) + _instance!._stores.putIfAbsent(s.runtimeType.toString(), () => s); + for (final store in stores) { + _instance!._stores.putIfAbsent(store.runtimeType.toString(), () => store); + } await Future.wait( instance._stores.values.map((store) => store.initialiseStore()), ); } - static void close() { - _instance = null; + /// closes all stores + static Future close() async { + if (_instance != null) { + await _instance!._stores.values + .map((store) async => await store.close()) + .wait; + _instance = null; + } + } + + /// retrieves all [CacheStore] that matches the [predicate] + Future> where( + String key, bool Function(CacheItem i) predicate) async { + List s = []; + for (final store in _stores.values) { + if (await store.getCacheItem(key) case final CacheItem it) { + if (predicate(it)) s.add(store); + } + } + + return s; } /// retrieves the [CacheStore] version for the [CacheStore] specified by @@ -163,11 +181,11 @@ final class CacheManager { return await invalidateItemInCache(_effectiveStore(S.toString())); } - /// helper method to check if a [CacheItem] has expired/valid. It returns a + /// helper method to check if a [CacheItem] is expired/valid. It returns a /// nullable boolean with null being returned when the item doesn't exist /// in the [CacheStore] specified by the method's generic type [S] /// or the first [CacheStore] in the manager - FutureOr hasCacheItemExpired(String key) async { + FutureOr isCacheItemExpired(String key) async { final item = await _effectiveStore(S.toString()).getCacheItem(key); return item?.isExpired; } diff --git a/lib/src/cache/cache.dart b/lib/src/src.dart similarity index 76% rename from lib/src/cache/cache.dart rename to lib/src/src.dart index 5d133bc..2d08df9 100644 --- a/lib/src/cache/cache.dart +++ b/lib/src/src.dart @@ -1,4 +1,5 @@ //GENERATED BARREL FILE export 'cache_item.dart'; export 'cache_store.dart'; +export 'in_memory_store.dart'; export 'manager.dart'; diff --git a/pubspec.yaml b/pubspec.yaml index 0d40182..fb14fba 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: cache_manager_plus description: "A Dart package for managing cache with support for multiple storage backends." -version: 1.0.2 +version: 1.1.0 homepage: https://github.com/CoderNamedHendrick/cache_manager repository: https://github.com/CoderNamedHendrick/cache_manager issue_tracker: https://github.com/CoderNamedHendrick/cache_manager/issues @@ -15,8 +15,6 @@ topics: environment: sdk: ^3.0.0 -dependencies: - dev_dependencies: lints: any test: ^1.25.15 diff --git a/test/cache_item_test.dart b/test/cache_item_test.dart new file mode 100644 index 0000000..b9fc4d6 --- /dev/null +++ b/test/cache_item_test.dart @@ -0,0 +1,35 @@ +import 'package:cache_manager_plus/cache_manager_plus.dart'; +import 'package:test/expect.dart'; +import 'package:test/scaffolding.dart'; + +void main() { + group('Cache item test', () { + test('equality comparison', () { + final a = CacheItem.ephemeral(key: 'a', data: 'Data a') + .copyWith(expiry: DateTime(1900)); + final b = CacheItem.ephemeral(key: 'a', data: 'Data a') + .copyWith(expiry: DateTime(1900)); + + expect(a == b, true); + }); + + test('persistence duration update', () { + var a = CacheItem.ephemeral(key: 'a', data: 'data a'); + + expect(a.isExpired, true); + + a = a.copyWith(persistenceDuration: Duration(minutes: 20)); + expect(a.isExpired, false); + + a = a.copyWith( + expiry: DateTime.now().add(Duration(minutes: 10)), + persistenceDuration: Duration(minutes: -20)); + expect(a.isExpired, true); + final expiry = a.expiry; + + a = a.copyWith(); + + expect(a.expiry, expiry); + }); + }); +} diff --git a/test/cache_manager_test.dart b/test/cache_manager_test.dart index f11ad7f..8b00df8 100644 --- a/test/cache_manager_test.dart +++ b/test/cache_manager_test.dart @@ -4,11 +4,27 @@ import 'package:test/test.dart'; void main() { group('Cache test suite', () { late CacheManager manager; - setUp(() { - CacheManager.init(store: InMemoryCacheStore(), forceInit: true); + setUp(() async { + await CacheManager.init(store: InMemoryCacheStore(), forceInit: true); manager = CacheManager.instance; }); + tearDown(() async { + await CacheManager.close(); + }); + + test('not passing any store throws error', () async { + await CacheManager.close(); + + expect( + CacheManager.init(), + throwsA( + isArgumentError.having((p0) => p0.message, 'invalid arguments error', + 'At least one store must be provided'), + ), + ); + }); + test('re-initialisation without forcing throw error', () async { expect( CacheManager.init(store: InMemoryCacheStore()), @@ -22,6 +38,14 @@ void main() { ); }); + test('update cache version', () async { + expect(await manager.cacheVersion(), -1); + + manager.updateCacheVersion(1); + + expect(await manager.cacheVersion(), 1); + }); + test('ephemeral cache items expire immediately', () async { final item = CacheItem.ephemeral( key: 'test-key-1', @@ -74,5 +98,40 @@ void main() { expect(updatedCachedItem?.isExpired, true); expect(updatedCachedItem?.data, {'data': 'look at me'}); }); + + test('close store and reinitialise', () async { + final item = CacheItem.persistent( + key: 'test-key-3', + data: {'data': 'look at me'}, + duration: Duration(seconds: 40), + ); + + CacheManager.instance.set(item); + + var cachedItem = await CacheManager.instance.get('test-key-3'); + expect(cachedItem?.isExpired, false); + + await CacheManager.close(); + + expect( + () async { + await CacheManager.instance.set(item); + }(), + throwsA( + isArgumentError.having( + (p0) => p0.message, + 'state error message', + 'CacheManager not initialized', + ), + ), + ); + + CacheManager.init(store: InMemoryCacheStore()); + + CacheManager.instance.set(item); + + cachedItem = await CacheManager.instance.get('test-key-3'); + expect(cachedItem?.isExpired, false); + }); }); } diff --git a/test/multi_store_manager_test.dart b/test/multi_store_manager_test.dart index 099c326..dd431e3 100644 --- a/test/multi_store_manager_test.dart +++ b/test/multi_store_manager_test.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:cache_manager_plus/cache_manager_plus.dart'; import 'package:test/test.dart'; @@ -5,14 +7,18 @@ void main() { group('Multi store cache test suite', () { late CacheManager manager; - setUp(() { - CacheManager.init( + setUp(() async { + await CacheManager.init( stores: [InMemoryCacheStore(), TestInMemoryCacheStore()], forceInit: true, ); manager = CacheManager.instance; }); + tearDown(() async { + await CacheManager.close(); + }); + test('verify ephemeral cache item is saved to a single store', () async { final item = CacheItem.ephemeral( key: 'test-key-1', @@ -58,6 +64,29 @@ void main() { (await manager.get('test-key-1')) != null, true); }); + test('verify where returns the correct cache stores', () async { + final item1 = CacheItem.ephemeral( + key: 'test-key-1', + data: 'John', + ); + final item2 = CacheItem.ephemeral( + key: 'test-key-1', + data: 'Doe', + ); + + await manager.set(item1); + await manager.set(item2); + + var stores = + await manager.where('test-key-1', (item) => item.data == 'Doe'); + expect(stores.length, 1); + expect(stores.first, isA()); + + stores = await manager.where('test-key-1', (item) => item.data == 'John'); + expect(stores.length, 1); + expect(stores.first, isA()); + }); + test('verify contains method works correctly across stores', () async { var item = CacheItem.ephemeral( key: 'test-key-1', @@ -178,21 +207,21 @@ void main() { await manager.set(item, all: true); expect( - (await manager.hasCacheItemExpired('test-key-1')), + (await manager.isCacheItemExpired('test-key-1')), false); expect( (await manager - .hasCacheItemExpired('test-key-1')), + .isCacheItemExpired('test-key-1')), false); await manager.invalidateCacheItem('test-key-1'); expect( - (await manager.hasCacheItemExpired('test-key-1')), + (await manager.isCacheItemExpired('test-key-1')), true); expect( (await manager - .hasCacheItemExpired('test-key-1')), + .isCacheItemExpired('test-key-1')), false); }); @@ -207,11 +236,11 @@ void main() { await manager.set(item, all: true); expect( - (await manager.hasCacheItemExpired('test-key-1')), + (await manager.isCacheItemExpired('test-key-1')), false); expect( (await manager - .hasCacheItemExpired('test-key-1')), + .isCacheItemExpired('test-key-1')), false); await manager.invalidateCacheItem('test-key-1'); @@ -249,52 +278,46 @@ void main() { await storeActions.wait; - expect( - await manager.hasCacheItemExpired('test-key-1'), + expect(await manager.isCacheItemExpired('test-key-1'), false); - expect( - await manager.hasCacheItemExpired('test-key-2'), + expect(await manager.isCacheItemExpired('test-key-2'), false); - expect( - await manager.hasCacheItemExpired('test-key-3'), + expect(await manager.isCacheItemExpired('test-key-3'), false); expect( await manager - .hasCacheItemExpired('test-key-1'), + .isCacheItemExpired('test-key-1'), false); expect( await manager - .hasCacheItemExpired('test-key-2'), + .isCacheItemExpired('test-key-2'), false); expect( await manager - .hasCacheItemExpired('test-key-3'), + .isCacheItemExpired('test-key-3'), false); await manager.invalidateCache(); - expect( - await manager.hasCacheItemExpired('test-key-1'), + expect(await manager.isCacheItemExpired('test-key-1'), null); - expect( - await manager.hasCacheItemExpired('test-key-2'), + expect(await manager.isCacheItemExpired('test-key-2'), null); - expect( - await manager.hasCacheItemExpired('test-key-3'), + expect(await manager.isCacheItemExpired('test-key-3'), null); expect( await manager - .hasCacheItemExpired('test-key-1'), + .isCacheItemExpired('test-key-1'), false); expect( await manager - .hasCacheItemExpired('test-key-2'), + .isCacheItemExpired('test-key-2'), false); expect( await manager - .hasCacheItemExpired('test-key-3'), + .isCacheItemExpired('test-key-3'), false); }); @@ -327,52 +350,46 @@ void main() { await storeActions.wait; - expect( - await manager.hasCacheItemExpired('test-key-1'), + expect(await manager.isCacheItemExpired('test-key-1'), false); - expect( - await manager.hasCacheItemExpired('test-key-2'), + expect(await manager.isCacheItemExpired('test-key-2'), false); - expect( - await manager.hasCacheItemExpired('test-key-3'), + expect(await manager.isCacheItemExpired('test-key-3'), false); expect( await manager - .hasCacheItemExpired('test-key-1'), + .isCacheItemExpired('test-key-1'), false); expect( await manager - .hasCacheItemExpired('test-key-2'), + .isCacheItemExpired('test-key-2'), false); expect( await manager - .hasCacheItemExpired('test-key-3'), + .isCacheItemExpired('test-key-3'), false); await manager.invalidateCache(all: true); - expect( - await manager.hasCacheItemExpired('test-key-1'), + expect(await manager.isCacheItemExpired('test-key-1'), null); - expect( - await manager.hasCacheItemExpired('test-key-2'), + expect(await manager.isCacheItemExpired('test-key-2'), null); - expect( - await manager.hasCacheItemExpired('test-key-3'), + expect(await manager.isCacheItemExpired('test-key-3'), null); expect( await manager - .hasCacheItemExpired('test-key-1'), + .isCacheItemExpired('test-key-1'), null); expect( await manager - .hasCacheItemExpired('test-key-2'), + .isCacheItemExpired('test-key-2'), null); expect( await manager - .hasCacheItemExpired('test-key-3'), + .isCacheItemExpired('test-key-3'), null); }); }); @@ -381,26 +398,42 @@ void main() { final class TestInMemoryCacheStore implements CacheStore { TestInMemoryCacheStore(); - late final Map _store; + Map? _store; @override Future get cacheVersion async { - return int.parse(_store['version'] ?? '-1'); + if (_store == null) + throw StateError( + 'Store not initialised, did you fail to initialise the store?'); + + return int.parse(_store!['version'] ?? '-1'); } @override Future updateCacheVersion(int version) async { - _store['version'] = version.toString(); + if (_store == null) + throw StateError( + 'Store not initialised, did you fail to initialise the store?'); + + _store!['version'] = version.toString(); } @override bool containsKey(String key) { - return _store.containsKey(key); + if (_store == null) + throw StateError( + 'Store not initialised, did you fail to initialise the store?'); + + return _store!.containsKey(key); } @override Future getCacheItem(String key) async { - final item = _store[key]; + if (_store == null) + throw StateError( + 'Store not initialised, did you fail to initialise the store?'); + + final item = _store![key]; if (item == null) return null; return CacheItem.fromCacheEntryString(item, key: key); @@ -413,7 +446,11 @@ final class TestInMemoryCacheStore implements CacheStore { @override Future invalidateCache() async { - return _store.clear(); + if (_store == null) + throw StateError( + 'Store not initialised, did you fail to initialise the store?'); + + return _store!.clear(); } @override @@ -427,6 +464,11 @@ final class TestInMemoryCacheStore implements CacheStore { @override Future saveCacheItem(CacheItem item) async { - _store[item.key] = item.toCacheEntryString(); + _store![item.key] = item.toCacheEntryString(); + } + + @override + FutureOr close() { + _store = null; } } From 08aff6f5044c5529b09fc112e6e11b40069cf7bd Mon Sep 17 00:00:00 2001 From: Sebastine Odeh Date: Sun, 4 May 2025 11:58:02 +0100 Subject: [PATCH 2/3] fix lint issues --- lib/src/in_memory_store.dart | 15 ++++++++++----- lib/src/manager.dart | 29 ++++++++++++----------------- test/multi_store_manager_test.dart | 15 ++++++++++----- 3 files changed, 32 insertions(+), 27 deletions(-) diff --git a/lib/src/in_memory_store.dart b/lib/src/in_memory_store.dart index ded54e0..f4d6005 100644 --- a/lib/src/in_memory_store.dart +++ b/lib/src/in_memory_store.dart @@ -10,36 +10,40 @@ final class InMemoryCacheStore implements CacheStore { @override Future get cacheVersion async { - if (_store == null) + if (_store == null) { throw StateError( 'Store not initialised, did you fail to initialise the store?'); + } return int.parse(_store!['version'] ?? '-1'); } @override Future updateCacheVersion(int version) async { - if (_store == null) + if (_store == null) { throw StateError( 'Store not initialised, did you fail to initialise the store?'); + } _store!['version'] = version.toString(); } @override bool containsKey(String key) { - if (_store == null) + if (_store == null) { throw StateError( 'Store not initialised, did you fail to initialise the store?'); + } return _store!.containsKey(key); } @override Future getCacheItem(String key) async { - if (_store == null) + if (_store == null) { throw StateError( 'Store not initialised, did you fail to initialise the store?'); + } final item = _store![key]; if (item == null) return null; @@ -54,9 +58,10 @@ final class InMemoryCacheStore implements CacheStore { @override Future invalidateCache() async { - if (_store == null) + if (_store == null) { throw StateError( 'Store not initialised, did you fail to initialise the store?'); + } return _store!.clear(); } diff --git a/lib/src/manager.dart b/lib/src/manager.dart index a25d6e1..c090462 100644 --- a/lib/src/manager.dart +++ b/lib/src/manager.dart @@ -40,23 +40,24 @@ final class CacheManager { List stores = const [], bool forceInit = false, }) async { - if (store == null && stores.isEmpty) + if (store == null && stores.isEmpty) { throw ArgumentError('At least one store must be provided'); + } if (forceInit) { await close(); // safe closes all stores _instance = CacheManager._(); } else { if (_instance != null) { - throw StateError( - 'Cache manager has already been initialised, force initialisation instead?'); + throw StateError('Cache manager has already been initialised, force initialisation instead?'); } _instance ??= CacheManager._(); } _instance!._stores = {}; - if (store case final CacheStore s) + if (store case final CacheStore s) { _instance!._stores.putIfAbsent(s.runtimeType.toString(), () => s); + } for (final store in stores) { _instance!._stores.putIfAbsent(store.runtimeType.toString(), () => store); } @@ -69,16 +70,13 @@ final class CacheManager { /// closes all stores static Future close() async { if (_instance != null) { - await _instance!._stores.values - .map((store) async => await store.close()) - .wait; + await _instance!._stores.values.map((store) async => await store.close()).wait; _instance = null; } } /// retrieves all [CacheStore] that matches the [predicate] - Future> where( - String key, bool Function(CacheItem i) predicate) async { + Future> where(String key, bool Function(CacheItem i) predicate) async { List s = []; for (final store in _stores.values) { if (await store.getCacheItem(key) case final CacheItem it) { @@ -98,8 +96,7 @@ final class CacheManager { /// updates the [CacheStore] version for the [CacheStore] specified by /// the method's generic type [S] or the first [CacheStore] in the manager. /// All [CacheStore] in the manager can be updated by setting [all] to true - Future updateCacheVersion(int version, - {bool all = false}) async { + Future updateCacheVersion(int version, {bool all = false}) async { return await _effectiveStore(S.toString()).updateCacheVersion(version); } @@ -107,8 +104,7 @@ final class CacheManager { /// generic type [S] or the first [CacheStore] in the manager. /// The [CacheItem] can be set in all [CacheStore] in the manager by setting /// [all] to true - Future set(CacheItem item, - {bool all = false}) async { + Future set(CacheItem item, {bool all = false}) async { if (all) { log('setting cache data for ${item.key} in all stores'); await _stores.values.map((store) => store.saveCacheItem(item)).wait; @@ -163,8 +159,7 @@ final class CacheManager { /// invalidates [CacheItem] with the [key] in the [CacheStore] specified /// by the method's generic type [S] or the first [CacheStore] in the manager. /// Invalidate [CacheItem] in all [CacheStore] by setting [all] to true - Future invalidateCacheItem(String key, - {bool all = false}) async { + Future invalidateCacheItem(String key, {bool all = false}) async { Future invalidateItemInCache(CacheStore store) async { if (!store.containsKey(key)) { return; @@ -194,8 +189,8 @@ final class CacheManager { /// in the [CacheManager] Future anyCacheItemExpired(String key) async { for (final store in _stores.values) { - if (await _effectiveStore(store.runtimeType.toString()).getCacheItem(key) - case final CacheItem item when item.isExpired) { + if (await _effectiveStore(store.runtimeType.toString()).getCacheItem(key) case final CacheItem item + when item.isExpired) { return store; } } diff --git a/test/multi_store_manager_test.dart b/test/multi_store_manager_test.dart index dd431e3..1ac3478 100644 --- a/test/multi_store_manager_test.dart +++ b/test/multi_store_manager_test.dart @@ -402,36 +402,40 @@ final class TestInMemoryCacheStore implements CacheStore { @override Future get cacheVersion async { - if (_store == null) + if (_store == null) { throw StateError( 'Store not initialised, did you fail to initialise the store?'); + } return int.parse(_store!['version'] ?? '-1'); } @override Future updateCacheVersion(int version) async { - if (_store == null) + if (_store == null) { throw StateError( 'Store not initialised, did you fail to initialise the store?'); + } _store!['version'] = version.toString(); } @override bool containsKey(String key) { - if (_store == null) + if (_store == null) { throw StateError( 'Store not initialised, did you fail to initialise the store?'); + } return _store!.containsKey(key); } @override Future getCacheItem(String key) async { - if (_store == null) + if (_store == null) { throw StateError( 'Store not initialised, did you fail to initialise the store?'); + } final item = _store![key]; if (item == null) return null; @@ -446,9 +450,10 @@ final class TestInMemoryCacheStore implements CacheStore { @override Future invalidateCache() async { - if (_store == null) + if (_store == null) { throw StateError( 'Store not initialised, did you fail to initialise the store?'); + } return _store!.clear(); } From cad3cdfd61c953a244d255b9bdcd91821159777e Mon Sep 17 00:00:00 2001 From: Sebastine Odeh Date: Sun, 4 May 2025 12:00:00 +0100 Subject: [PATCH 3/3] fix lint issues --- lib/src/manager.dart | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/lib/src/manager.dart b/lib/src/manager.dart index c090462..e913fce 100644 --- a/lib/src/manager.dart +++ b/lib/src/manager.dart @@ -49,7 +49,8 @@ final class CacheManager { _instance = CacheManager._(); } else { if (_instance != null) { - throw StateError('Cache manager has already been initialised, force initialisation instead?'); + throw StateError( + 'Cache manager has already been initialised, force initialisation instead?'); } _instance ??= CacheManager._(); } @@ -70,13 +71,16 @@ final class CacheManager { /// closes all stores static Future close() async { if (_instance != null) { - await _instance!._stores.values.map((store) async => await store.close()).wait; + await _instance!._stores.values + .map((store) async => await store.close()) + .wait; _instance = null; } } /// retrieves all [CacheStore] that matches the [predicate] - Future> where(String key, bool Function(CacheItem i) predicate) async { + Future> where( + String key, bool Function(CacheItem i) predicate) async { List s = []; for (final store in _stores.values) { if (await store.getCacheItem(key) case final CacheItem it) { @@ -96,7 +100,8 @@ final class CacheManager { /// updates the [CacheStore] version for the [CacheStore] specified by /// the method's generic type [S] or the first [CacheStore] in the manager. /// All [CacheStore] in the manager can be updated by setting [all] to true - Future updateCacheVersion(int version, {bool all = false}) async { + Future updateCacheVersion(int version, + {bool all = false}) async { return await _effectiveStore(S.toString()).updateCacheVersion(version); } @@ -104,7 +109,8 @@ final class CacheManager { /// generic type [S] or the first [CacheStore] in the manager. /// The [CacheItem] can be set in all [CacheStore] in the manager by setting /// [all] to true - Future set(CacheItem item, {bool all = false}) async { + Future set(CacheItem item, + {bool all = false}) async { if (all) { log('setting cache data for ${item.key} in all stores'); await _stores.values.map((store) => store.saveCacheItem(item)).wait; @@ -159,7 +165,8 @@ final class CacheManager { /// invalidates [CacheItem] with the [key] in the [CacheStore] specified /// by the method's generic type [S] or the first [CacheStore] in the manager. /// Invalidate [CacheItem] in all [CacheStore] by setting [all] to true - Future invalidateCacheItem(String key, {bool all = false}) async { + Future invalidateCacheItem(String key, + {bool all = false}) async { Future invalidateItemInCache(CacheStore store) async { if (!store.containsKey(key)) { return; @@ -189,8 +196,8 @@ final class CacheManager { /// in the [CacheManager] Future anyCacheItemExpired(String key) async { for (final store in _stores.values) { - if (await _effectiveStore(store.runtimeType.toString()).getCacheItem(key) case final CacheItem item - when item.isExpired) { + if (await _effectiveStore(store.runtimeType.toString()).getCacheItem(key) + case final CacheItem item when item.isExpired) { return store; } }