From 0d839777a1a28bdd85314a824de98918c8a2fa11 Mon Sep 17 00:00:00 2001 From: Marcos Augusto Date: Thu, 22 Jan 2026 09:59:21 -0300 Subject: [PATCH] feat: adding a way to use different values for max capacity query --- .../lib/src/cache_store.dart | 4 +- .../lib/src/config/_config_unsupported.dart | 5 ++ .../lib/src/config/config.dart | 3 + .../cache_info_repository.dart | 5 +- .../cache_object_provider.dart | 4 +- .../json_cache_info_repository.dart | 11 +-- .../non_storing_object_provider.dart | 2 +- flutter_cache_manager/test/mock.mocks.dart | 67 ++++++++++--------- .../json_file_repository_test.dart | 2 +- 9 files changed, 61 insertions(+), 42 deletions(-) diff --git a/flutter_cache_manager/lib/src/cache_store.dart b/flutter_cache_manager/lib/src/cache_store.dart index ca6e9188..591f3652 100644 --- a/flutter_cache_manager/lib/src/cache_store.dart +++ b/flutter_cache_manager/lib/src/cache_store.dart @@ -24,6 +24,8 @@ class CacheStore { Duration get _maxAge => _config.stalePeriod; + Duration get _maxCapacityAgeFilterDuration => _config.maxCapacityAgeFilterDuration ?? const Duration(days: 1); + DateTime lastCleanupRun = DateTime.now(); Timer? _scheduledCleanup; @@ -136,7 +138,7 @@ class CacheStore { final toRemove = []; final provider = await _cacheInfoRepository; - final overCapacity = await provider.getObjectsOverCapacity(_capacity); + final overCapacity = await provider.getObjectsOverCapacity(_capacity, maxAge: _maxCapacityAgeFilterDuration); for (final cacheObject in overCapacity) { _removeCachedFile(cacheObject, toRemove); } diff --git a/flutter_cache_manager/lib/src/config/_config_unsupported.dart b/flutter_cache_manager/lib/src/config/_config_unsupported.dart index b14ebeb3..68b61fcf 100644 --- a/flutter_cache_manager/lib/src/config/_config_unsupported.dart +++ b/flutter_cache_manager/lib/src/config/_config_unsupported.dart @@ -18,6 +18,8 @@ class Config implements def.Config { FileSystem? fileSystem, //ignore: avoid_unused_constructor_parameters FileService? fileService, + //ignore: avoid_unused_constructor_parameters + Duration? maxCapacityAgeFilterDuration, }) { throw UnsupportedError('Platform is not supported'); } @@ -39,4 +41,7 @@ class Config implements def.Config { @override FileService get fileService => throw UnimplementedError(); + + @override + Duration? get maxCapacityAgeFilterDuration => throw UnimplementedError(); } diff --git a/flutter_cache_manager/lib/src/config/config.dart b/flutter_cache_manager/lib/src/config/config.dart index 1af4730f..bb84b68a 100644 --- a/flutter_cache_manager/lib/src/config/config.dart +++ b/flutter_cache_manager/lib/src/config/config.dart @@ -27,6 +27,7 @@ abstract class Config { CacheInfoRepository repo, FileSystem fileSystem, FileService fileService, + Duration? maxCapacityAgeFilterDuration, }) = impl.Config; String get cacheKey; @@ -40,4 +41,6 @@ abstract class Config { FileSystem get fileSystem; FileService get fileService; + + Duration? get maxCapacityAgeFilterDuration; } diff --git a/flutter_cache_manager/lib/src/storage/cache_info_repositories/cache_info_repository.dart b/flutter_cache_manager/lib/src/storage/cache_info_repositories/cache_info_repository.dart index 5a282b24..9c4c2bc5 100644 --- a/flutter_cache_manager/lib/src/storage/cache_info_repositories/cache_info_repository.dart +++ b/flutter_cache_manager/lib/src/storage/cache_info_repositories/cache_info_repository.dart @@ -36,8 +36,9 @@ abstract class CacheInfoRepository { /// Gets the list of [CacheObject] that can be removed if the repository is over capacity. /// /// The exact implementation is up to the repository, but implementations should - /// return a preferred list of items. For example, the least recently accessed - Future> getObjectsOverCapacity(int capacity); + /// return a preferred list of items. For example, the least recently accessed. + /// [maxAge] filters objects older than the given duration (defaults to 1 day). + Future> getObjectsOverCapacity(int capacity, {Duration? maxAge}); /// Returns a list of [CacheObject] that are older than [maxAge] Future> getOldObjects(Duration maxAge); diff --git a/flutter_cache_manager/lib/src/storage/cache_info_repositories/cache_object_provider.dart b/flutter_cache_manager/lib/src/storage/cache_info_repositories/cache_object_provider.dart index 16bf5656..5196bdfd 100644 --- a/flutter_cache_manager/lib/src/storage/cache_info_repositories/cache_object_provider.dart +++ b/flutter_cache_manager/lib/src/storage/cache_info_repositories/cache_object_provider.dart @@ -145,14 +145,14 @@ class CacheObjectProvider extends CacheInfoRepository } @override - Future> getObjectsOverCapacity(int capacity) async { + Future> getObjectsOverCapacity(int capacity, {Duration? maxAge}) async { return CacheObject.fromMapList(await db!.query( _tableCacheObject, columns: null, orderBy: '${CacheObject.columnTouched} DESC', where: '${CacheObject.columnTouched} < ?', whereArgs: [ - DateTime.now().subtract(const Duration(days: 1)).millisecondsSinceEpoch + DateTime.now().subtract(maxAge ?? const Duration(days: 1)).millisecondsSinceEpoch ], limit: 100, offset: capacity, diff --git a/flutter_cache_manager/lib/src/storage/cache_info_repositories/json_cache_info_repository.dart b/flutter_cache_manager/lib/src/storage/cache_info_repositories/json_cache_info_repository.dart index 800f4ba1..072db084 100644 --- a/flutter_cache_manager/lib/src/storage/cache_info_repositories/json_cache_info_repository.dart +++ b/flutter_cache_manager/lib/src/storage/cache_info_repositories/json_cache_info_repository.dart @@ -87,11 +87,14 @@ class JsonCacheInfoRepository extends CacheInfoRepository } @override - Future> getObjectsOverCapacity(int capacity) async { - final allSorted = _cacheObjects.values.toList() + Future> getObjectsOverCapacity(int capacity, {Duration? maxAge}) async { + final threshold = DateTime.now().subtract(maxAge ?? const Duration(days: 1)); + final filtered = _cacheObjects.values + .where((c) => c.touched!.isBefore(threshold)) + .toList() ..sort((c1, c2) => c1.touched!.compareTo(c2.touched!)); - if (allSorted.length <= capacity) return []; - return allSorted.getRange(0, allSorted.length - capacity).toList(); + if (filtered.length <= capacity) return []; + return filtered.getRange(0, filtered.length - capacity).toList(); } @override diff --git a/flutter_cache_manager/lib/src/storage/cache_info_repositories/non_storing_object_provider.dart b/flutter_cache_manager/lib/src/storage/cache_info_repositories/non_storing_object_provider.dart index 92ea41c2..1400c994 100644 --- a/flutter_cache_manager/lib/src/storage/cache_info_repositories/non_storing_object_provider.dart +++ b/flutter_cache_manager/lib/src/storage/cache_info_repositories/non_storing_object_provider.dart @@ -28,7 +28,7 @@ class NonStoringObjectProvider implements CacheInfoRepository { } @override - Future> getObjectsOverCapacity(int capacity) { + Future> getObjectsOverCapacity(int capacity, {Duration? maxAge}) { return Future.value([]); } diff --git a/flutter_cache_manager/test/mock.mocks.dart b/flutter_cache_manager/test/mock.mocks.dart index 708ee9dd..4ab8e468 100644 --- a/flutter_cache_manager/test/mock.mocks.dart +++ b/flutter_cache_manager/test/mock.mocks.dart @@ -1,4 +1,4 @@ -// Mocks generated by Mockito 5.4.4 from annotations +// Mocks generated by Mockito 5.4.6 from annotations // in flutter_cache_manager/test/mock.dart. // Do not manually edit this file. @@ -20,10 +20,12 @@ import 'package:mockito/src/dummies.dart' as _i6; // ignore_for_file: deprecated_member_use_from_same_package // ignore_for_file: implementation_imports // ignore_for_file: invalid_use_of_visible_for_testing_member +// ignore_for_file: must_be_immutable // ignore_for_file: prefer_const_constructors // ignore_for_file: unnecessary_parenthesis // ignore_for_file: camel_case_types // ignore_for_file: subtype_of_sealed_class +// ignore_for_file: invalid_use_of_internal_member class _FakeCacheObject_0 extends _i1.SmartFake implements _i2.CacheObject { _FakeCacheObject_0( @@ -196,11 +198,15 @@ class MockCacheInfoRepositoryBase extends _i1.Mock ) as _i4.Future>); @override - _i4.Future> getObjectsOverCapacity(int? capacity) => + _i4.Future> getObjectsOverCapacity( + int? capacity, { + Duration? maxAge, + }) => (super.noSuchMethod( Invocation.method( #getObjectsOverCapacity, [capacity], + {#maxAge: maxAge}, ), returnValue: _i4.Future>.value(<_i2.CacheObject>[]), @@ -254,16 +260,6 @@ class MockCacheStoreBase extends _i1.Mock implements _i5.CacheStore { ), ) as Duration); - @override - set cleanupRunMinInterval(Duration? _cleanupRunMinInterval) => - super.noSuchMethod( - Invocation.setter( - #cleanupRunMinInterval, - _cleanupRunMinInterval, - ), - returnValueForMissingStub: null, - ); - @override _i3.FileSystem get fileSystem => (super.noSuchMethod( Invocation.getter(#fileSystem), @@ -274,13 +270,13 @@ class MockCacheStoreBase extends _i1.Mock implements _i5.CacheStore { ) as _i3.FileSystem); @override - set fileSystem(_i3.FileSystem? _fileSystem) => super.noSuchMethod( - Invocation.setter( - #fileSystem, - _fileSystem, + String get storeKey => (super.noSuchMethod( + Invocation.getter(#storeKey), + returnValue: _i6.dummyValue( + this, + Invocation.getter(#storeKey), ), - returnValueForMissingStub: null, - ); + ) as String); @override DateTime get lastCleanupRun => (super.noSuchMethod( @@ -292,22 +288,31 @@ class MockCacheStoreBase extends _i1.Mock implements _i5.CacheStore { ) as DateTime); @override - set lastCleanupRun(DateTime? _lastCleanupRun) => super.noSuchMethod( + set cleanupRunMinInterval(Duration? value) => super.noSuchMethod( Invocation.setter( - #lastCleanupRun, - _lastCleanupRun, + #cleanupRunMinInterval, + value, ), returnValueForMissingStub: null, ); @override - String get storeKey => (super.noSuchMethod( - Invocation.getter(#storeKey), - returnValue: _i6.dummyValue( - this, - Invocation.getter(#storeKey), + set fileSystem(_i3.FileSystem? value) => super.noSuchMethod( + Invocation.setter( + #fileSystem, + value, ), - ) as String); + returnValueForMissingStub: null, + ); + + @override + set lastCleanupRun(DateTime? value) => super.noSuchMethod( + Invocation.setter( + #lastCleanupRun, + value, + ), + returnValueForMissingStub: null, + ); @override _i4.Future<_i3.FileInfo?> getFile( @@ -431,10 +436,10 @@ class MockFileServiceBase extends _i1.Mock implements _i3.FileService { ) as int); @override - set concurrentFetches(int? _concurrentFetches) => super.noSuchMethod( + set concurrentFetches(int? value) => super.noSuchMethod( Invocation.setter( #concurrentFetches, - _concurrentFetches, + value, ), returnValueForMissingStub: null, ); @@ -486,10 +491,10 @@ class MockWebHelper extends _i1.Mock implements _i7.WebHelper { ) as int); @override - set concurrentCalls(int? _concurrentCalls) => super.noSuchMethod( + set concurrentCalls(int? value) => super.noSuchMethod( Invocation.setter( #concurrentCalls, - _concurrentCalls, + value, ), returnValueForMissingStub: null, ); diff --git a/flutter_cache_manager/test/repositories/json_file_repository_test.dart b/flutter_cache_manager/test/repositories/json_file_repository_test.dart index 0e6e1dba..c69d8ba4 100644 --- a/flutter_cache_manager/test/repositories/json_file_repository_test.dart +++ b/flutter_cache_manager/test/repositories/json_file_repository_test.dart @@ -99,7 +99,7 @@ void main() { test('getObjectsOverCapacity should return oldest objects', () async { var repo = await JsonRepoHelpers.createRepository(); - var result = await repo.getObjectsOverCapacity(1); + var result = await repo.getObjectsOverCapacity(1, maxAge: Duration.zero); expect(result.length, 2); expectIdInList(result, 1); expectIdInList(result, 3);