mistral
Для реализации методов retrieveItems и getItemFromCache в классе ObjectDdCacheManager, нам нужно учитывать все условия, описанные в задаче. Давайте начнем с реализации этих методов.
Реализация метода retrieveItems
FetchDataPolicy:
never: Возвращаем данные из кеша (или ничего).
onEmptyCache: Делаем запрос к API только если в кеше нет данных.
always: Всегда делаем запрос к API и обновляем данные кеша.
CacheUpdateMode:
entities: Заменяем сущности.
box: Удаляем старую коробку целиком со всеми объектами.
Filter:
Если установлен, то запрос к базе делаем через getBeyKey (вид фильтра entityKey) или select (вид range).
Фильтр применяем и для удаления сущностей в режиме entities.
useMemoryCache:
Если установлен, то используем дополнительно кеш в памяти _memoryCache.
Реализация метода getItemFromCache
useMemoryCache:
Если установлен, то сначала проверяем кеш в памяти _memoryCache.
Если данных нет в _memoryCache, то проверяем базу данных.
| | code |
| | class ObjectDdCacheManager<TApiObject, TDataEntity extends DataEntity, TModel>
extends CacheManager<TApiObject, TDataEntity, TModel> {
ObjectDdCacheManager(
{required super.fetchFromApi,
required super.transformToDataEntities,
required super.transformToModel,
required super.boxName});
@override
Future<ResultOrError<List<TModel>>> retrieveItems(
{FetchDataPolicy fetchDataPolicy = FetchDataPolicy.onEmptyCache,
CacheUpdateMode cacheUpdateMode = CacheUpdateMode.entities,
Filter? filter}) async {
final box = ObjectDdMock<TDataEntity>();
List<TDataEntity> cachedEntities = [];
// Check memory cache first if useMemoryCache is true
if (useMemoryCache && _memoryCache.containsKey(boxName)) {
cachedEntities = _memoryCache[boxName]!.values.cast<TDataEntity>().toList();
} else {
// Check database cache
if (filter != null) {
if (filter.kind == FilterKind.entityKey && filter is FilterByKey) {
final entity = box.getBeyKey(filter.key);
if (entity != null) {
cachedEntities = [entity];
}
} else if (filter.kind == FilterKind.range && filter is FilterByRange) {
cachedEntities = box.select(filter.startKey, filter.endKey);
}
} else {
cachedEntities = box.getAll();
}
}
// Determine if we need to fetch from API
bool needToFetch = false;
if (fetchDataPolicy == FetchDataPolicy.always) {
needToFetch = true;
} else if (fetchDataPolicy == FetchDataPolicy.onEmptyCache && cachedEntities.isEmpty) {
needToFetch = true;
}
if (needToFetch) {
final apiResult = await fetchFromApi();
if (apiResult.isSuccess) {
final newEntities = transformToDataEntities(apiResult.result!);
if (cacheUpdateMode == CacheUpdateMode.box) {
box.deleteBox();
if (useMemoryCache) {
_memoryCache.remove(boxName);
}
} else if (cacheUpdateMode == CacheUpdateMode.entities) {
if (filter != null) {
List<TDataEntity> entitiesToDelete = [];
if (filter.kind == FilterKind.entityKey && filter is FilterByKey) {
final entity = box.getBeyKey(filter.key);
if (entity != null) {
entitiesToDelete.add(entity);
}
} else if (filter.kind == FilterKind.range && filter is FilterByRange) {
entitiesToDelete = box.select(filter.startKey, filter.endKey);
}
box.deleteEntities(entitiesToDelete);
if (useMemoryCache) {
for (final entity in entitiesToDelete) {
_memoryCache[boxName]?.remove(entity.key);
}
}
}
}
box.putAll(newEntities);
if (useMemoryCache) {
if (!_memoryCache.containsKey(boxName)) {
_memoryCache[boxName] = {};
}
for (final entity in newEntities) {
_memoryCache[boxName]![entity.key] = entity;
}
}
cachedEntities = newEntities;
} else {
return ResultOrError.fromError(apiResult.error!);
}
}
final models = cachedEntities.map(transformToModel).toList();
return ResultOrError.fromResult(models);
}
@override
Future<TModel?> getItemFromCache(String key) async {
if (useMemoryCache && _memoryCache.containsKey(boxName)) {
final entity = _memoryCache[boxName]![key] as TDataEntity?;
if (entity != null) {
return transformToModel(entity);
}
}
final box = ObjectDdMock<TDataEntity>();
final entity = box.getBeyKey(key);
if (entity != null) {
return transformToModel(entity);
}
return null;
}
}
void main() async {
final cacheManager = ObjectDdCacheManager(
fetchFromApi: () async {
return ResultOrError.fromResult(ApiObject1());
},
transformToDataEntities: (apiObject) {
return apiObject.items.keys
.map((k) => DataEntity1(k, apiObject.items[k]!))
.toList();
},
transformToModel: (dataEntity) {
return Model1(dataEntity.value);
},
boxName: 'box1');
final items = await cacheManager.retrieveItems();
print(items.result!.length);
}
|
| | |