Skip to content
This repository has been archived by the owner on Oct 22, 2024. It is now read-only.

Commit

Permalink
switching to top-level cache util method for code cov
Browse files Browse the repository at this point in the history
  • Loading branch information
verygoodstefan committed Oct 1, 2024
1 parent a189762 commit 532afcc
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 64 deletions.
1 change: 1 addition & 0 deletions api/packages/fluttercon_cache/lib/fluttercon_cache.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export 'src/fluttercon_cache.dart';
export 'src/hive/hive.dart';
export 'src/in_memory/in_memory.dart';
export 'src/keys.dart';
export 'src/utils/utils.dart';
18 changes: 0 additions & 18 deletions api/packages/fluttercon_cache/lib/src/fluttercon_cache.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import 'dart:convert';

/// {@template fluttercon_cache}
/// An abstract cache. Can be implemented with any cache provider.
/// {@endtemplate}
Expand All @@ -12,20 +10,4 @@ abstract class FlutterconCache {

/// Clears the cache.
Future<void> clear();

/// Attempts to fetch a value from the cache.
/// If not present, the cache will call the method
/// in [orElse] to fetch the data.
/// [fromJson] is necessary to deserialize the value.
Future<T> getOrElse<T>({
required String key,
required T Function(Map<String, dynamic>) fromJson,
required Future<T> Function() orElse,
}) async {
final cached = await get(key);
if (cached != null) {
return fromJson(jsonDecode(cached) as Map<String, dynamic>);
}
return orElse();
}
}
2 changes: 0 additions & 2 deletions api/packages/fluttercon_cache/lib/src/keys.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// coverage:ignore-file

/// The cache key for the speakers cache.
const speakersCacheKey = 'speakers';

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import 'dart:convert';

/// Attempts to fetch a value from the cache.
/// If not present, the cache will call the method
/// in [orElse] to fetch the data.
/// [fromJson] is necessary to deserialize the value.
Future<T> tryGetFromCache<T>({
required Future<String?> Function() getFromCache,
required T Function(Map<String, dynamic>) fromJson,
required Future<T> Function() orElse,
}) async {
final cached = await getFromCache();
if (cached != null) {
return fromJson(jsonDecode(cached) as Map<String, dynamic>);
}
return orElse();
}
1 change: 1 addition & 0 deletions api/packages/fluttercon_cache/lib/src/utils/utils.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export 'try_get_from_cache.dart';
18 changes: 6 additions & 12 deletions api/packages/speakers_repository/lib/src/speakers_repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,13 @@ class SpeakersRepository {
/// if the cache is empty.
///
/// If fetching from api, the speakers are then cached.
Future<PaginatedData<SpeakerPreview>> getSpeakers() async => _cache.getOrElse(
key: speakersCacheKey,
// coverage:ignore-start
Future<PaginatedData<SpeakerPreview>> getSpeakers() async => tryGetFromCache(
getFromCache: () => _cache.get(speakersCacheKey),
fromJson: (json) => PaginatedData.fromJson(
json,
(val) => SpeakerPreview.fromJson((val ?? {}) as Map<String, dynamic>),
),
orElse: getSpeakersFromApi,
// coverage:ignore-end
);

/// Fetches a [SpeakerDetail] with a given [id].
Expand All @@ -41,12 +39,10 @@ class SpeakersRepository {
required String id,
required String userId,
}) async {
return _cache.getOrElse(
key: speakerCacheKey(id),
return tryGetFromCache(
getFromCache: () => _cache.get(speakerCacheKey(id)),
fromJson: SpeakerDetail.fromJson,
// coverage:ignore-start
orElse: () => getSpeakerDetailFromApi(id: id, userId: userId),
// coverage:ignore-end
);
}

Expand Down Expand Up @@ -105,14 +101,12 @@ class SpeakersRepository {
.toList(),
);

final favorites = await _cache.getOrElse(
key: favoritesCacheKey(userId),
// coverage:ignore-start
final favorites = await tryGetFromCache(
getFromCache: () => _cache.get(favoritesCacheKey(userId)),
fromJson: favoritesFromJson,
orElse: () async {
final response = await _dataSource.getFavorites(userId: userId);
return response.items.first;
// coverage:ignore-end
},
);

Expand Down
56 changes: 24 additions & 32 deletions api/packages/talks_repository/lib/src/talks_repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,10 @@ class TalksRepository {
Future<CreateFavoriteResponse> createFavorite({
required CreateFavoriteRequest request,
}) async {
final favorites = await _cache.getOrElse(
key: favoritesCacheKey(request.userId),
final favorites = await tryGetFromCache(
getFromCache: () => _cache.get(favoritesCacheKey(request.userId)),
fromJson: favoritesFromJson,
// coverage:ignore-start
orElse: () async => getFavoritesFromApi(request.userId),
// coverage:ignore-end
);

final createResponse = await _dataSource.createFavoritesTalk(
Expand Down Expand Up @@ -56,12 +54,10 @@ class TalksRepository {
Future<DeleteFavoriteResponse> deleteFavorite({
required DeleteFavoriteRequest request,
}) async {
final favorites = await _cache.getOrElse(
key: favoritesCacheKey(request.userId),
final favorites = await tryGetFromCache(
getFromCache: () => _cache.get(favoritesCacheKey(request.userId)),
fromJson: favoritesFromJson,
// coverage:ignore-start
orElse: () async => getFavoritesFromApi(request.userId),
// coverage:ignore-end
);

final favoritesTalkResponse = await _dataSource.getFavoritesTalks(
Expand Down Expand Up @@ -107,34 +103,32 @@ class TalksRepository {
Future<PaginatedData<TalkTimeSlot>> getTalks({
required String userId,
}) async {
final talkData = await _cache.getOrElse(
key: talksCacheKey,
// coverage:ignore-start
final talkData = await tryGetFromCache(
getFromCache: () => _cache.get(talksCacheKey),
fromJson: (json) => PaginatedData.fromJson(
json,
(val) => Talk.fromJson((val ?? {}) as Map<String, dynamic>),
),
orElse: getTalksFromApi,
// coverage:ignore-end
);

final speakerData = await _cache.getOrElse(
key: speakerTalksCacheKey(talkData.items.map((t) => t?.id).join(',')),
// coverage:ignore-start
final speakerData = await tryGetFromCache(
getFromCache: () => _cache.get(
speakerTalksCacheKey(
talkData.items.map((t) => t?.id).join(','),
),
),
fromJson: (json) => PaginatedData.fromJson(
json,
(val) => SpeakerTalk.fromJson((val ?? {}) as Map<String, dynamic>),
),
orElse: () => getSpeakersFromApi(talkData.items),
// coverage:ignore-end
);

final favorites = await _cache.getOrElse(
key: favoritesCacheKey(userId),
final favorites = await tryGetFromCache(
getFromCache: () => _cache.get(favoritesCacheKey(userId)),
fromJson: favoritesFromJson,
// coverage:ignore-start
orElse: () async => getFavoritesFromApi(userId),
// coverage:ignore-end
);

final timeSlots = await _buildTalkTimeSlots(
Expand All @@ -151,12 +145,10 @@ class TalksRepository {
}

/// Fetches a [TalkDetail] entity by [id].
Future<TalkDetail> getTalk({required String id}) async => _cache.getOrElse(
key: talkCacheKey(id),
Future<TalkDetail> getTalk({required String id}) async => tryGetFromCache(
getFromCache: () => _cache.get(talkCacheKey(id)),
fromJson: TalkDetail.fromJson,
// coverage:ignore-start
orElse: () => getTalkDetailFromApi(id),
// coverage:ignore-end
);

/// Fetches a paginated list of talks for a given [userId].
Expand All @@ -166,12 +158,10 @@ class TalksRepository {
Future<PaginatedData<TalkTimeSlot>> getFavorites({
required String userId,
}) async {
final favorites = await _cache.getOrElse(
key: favoritesCacheKey(userId),
final favorites = await tryGetFromCache(
getFromCache: () => _cache.get(favoritesCacheKey(userId)),
fromJson: favoritesFromJson,
// coverage:ignore-start
orElse: () async => getFavoritesFromApi(userId),
// coverage:ignore-end
);

final favoritesTalks = favorites.talks ?? [];
Expand All @@ -181,15 +171,17 @@ class TalksRepository {
.map((ft) => ft.talk!)
.toList();

final speakerData = await _cache.getOrElse(
key: speakerTalksCacheKey(talks.map((t) => t.id).join(',')),
// coverage:ignore-start
final speakerData = await tryGetFromCache(
getFromCache: () => _cache.get(
speakerTalksCacheKey(
talks.map((t) => t.id).join(','),
),
),
fromJson: (json) => PaginatedData.fromJson(
json,
(val) => SpeakerTalk.fromJson((val ?? {}) as Map<String, dynamic>),
),
orElse: () => getSpeakersFromApi(talks),
// coverage:ignore-end
);

final timeSlots = await _buildTalkTimeSlots(
Expand Down

0 comments on commit 532afcc

Please sign in to comment.