added caching for span details api responses, also pre-calling of span details endpoint for each match after fetching IGC data
This commit is contained in:
parent
0309feb03d
commit
14f4192b6f
2 changed files with 80 additions and 11 deletions
|
|
@ -19,14 +19,37 @@ import '../../repo/tokens_repo.dart';
|
|||
import '../../utils/error_handler.dart';
|
||||
import '../../utils/overlay.dart';
|
||||
|
||||
class _SpanDetailsCacheItem {
|
||||
SpanDetailsRepoReqAndRes data;
|
||||
|
||||
_SpanDetailsCacheItem({required this.data});
|
||||
}
|
||||
|
||||
class IgcController {
|
||||
Choreographer choreographer;
|
||||
IGCTextData? igcTextData;
|
||||
Object? igcError;
|
||||
|
||||
Completer<IGCTextData> igcCompleter = Completer();
|
||||
final Map<int, _SpanDetailsCacheItem> _cache = {};
|
||||
Timer? _cacheClearTimer;
|
||||
|
||||
IgcController(this.choreographer);
|
||||
IgcController(this.choreographer) {
|
||||
_initializeCacheClearing();
|
||||
}
|
||||
|
||||
void _initializeCacheClearing() {
|
||||
const duration = Duration(minutes: 2);
|
||||
_cacheClearTimer = Timer.periodic(duration, (Timer t) => _clearCache());
|
||||
}
|
||||
|
||||
void _clearCache() {
|
||||
_cache.clear();
|
||||
}
|
||||
|
||||
void dispose() {
|
||||
_cacheClearTimer?.cancel();
|
||||
}
|
||||
|
||||
Future<void> getIGCTextData({required bool tokensOnly}) async {
|
||||
try {
|
||||
|
|
@ -80,6 +103,14 @@ class IgcController {
|
|||
|
||||
igcTextData = igcTextDataResponse;
|
||||
|
||||
// After fetching igc data, pre-call span details for each match optimistically.
|
||||
// This will make the loading of span details faster for the user
|
||||
if (igcTextData?.matches.isNotEmpty ?? false) {
|
||||
for (int i = 0; i < igcTextData!.matches.length; i++) {
|
||||
getSpanDetails(i);
|
||||
}
|
||||
}
|
||||
|
||||
debugPrint("igc text ${igcTextData.toString()}");
|
||||
} catch (err, stack) {
|
||||
debugger(when: kDebugMode);
|
||||
|
|
@ -99,18 +130,38 @@ class IgcController {
|
|||
debugger(when: kDebugMode);
|
||||
return;
|
||||
}
|
||||
final SpanData span = igcTextData!.matches[matchIndex].match;
|
||||
|
||||
final SpanDetailsRepoReqAndRes response = await SpanDataRepo.getSpanDetails(
|
||||
await choreographer.accessToken,
|
||||
request: SpanDetailsRepoReqAndRes(
|
||||
userL1: choreographer.l1LangCode!,
|
||||
userL2: choreographer.l2LangCode!,
|
||||
enableIGC: choreographer.igcEnabled,
|
||||
enableIT: choreographer.itEnabled,
|
||||
span: span,
|
||||
),
|
||||
/// Retrieves the span data from the `igcTextData` matches at the specified `matchIndex`.
|
||||
/// Creates a `SpanDetailsRepoReqAndRes` object with the retrieved span data and other parameters.
|
||||
/// Generates a cache key based on the created `SpanDetailsRepoReqAndRes` object.
|
||||
final SpanData span = igcTextData!.matches[matchIndex].match;
|
||||
final req = SpanDetailsRepoReqAndRes(
|
||||
userL1: choreographer.l1LangCode!,
|
||||
userL2: choreographer.l2LangCode!,
|
||||
enableIGC: choreographer.igcEnabled,
|
||||
enableIT: choreographer.itEnabled,
|
||||
span: span,
|
||||
);
|
||||
final int cacheKey = req.hashCode;
|
||||
|
||||
/// Retrieves the [SpanDetailsRepoReqAndRes] response from the cache if it exists,
|
||||
/// otherwise makes an API call to get the response and stores it in the cache.
|
||||
SpanDetailsRepoReqAndRes response;
|
||||
if (_cache.containsKey(cacheKey)) {
|
||||
response = _cache[cacheKey]!.data;
|
||||
} else {
|
||||
response = await SpanDataRepo.getSpanDetails(
|
||||
await choreographer.accessToken,
|
||||
request: SpanDetailsRepoReqAndRes(
|
||||
userL1: choreographer.l1LangCode!,
|
||||
userL2: choreographer.l2LangCode!,
|
||||
enableIGC: choreographer.igcEnabled,
|
||||
enableIT: choreographer.itEnabled,
|
||||
span: span,
|
||||
),
|
||||
);
|
||||
_cache[cacheKey] = _SpanDetailsCacheItem(data: response);
|
||||
}
|
||||
|
||||
try {
|
||||
igcTextData!.matches[matchIndex].match = response.span;
|
||||
|
|
|
|||
|
|
@ -72,6 +72,24 @@ class SpanDetailsRepoReqAndRes {
|
|||
enableIGC: json['enable_igc'] as bool,
|
||||
span: SpanData.fromJson(json['span']),
|
||||
);
|
||||
|
||||
/// Overrides the equality operator to compare two [SpanDetailsRepoReqAndRes] objects.
|
||||
/// Returns true if the objects are identical or have the same property
|
||||
/// values (based on the results of the toJson function), false otherwise.
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) return true;
|
||||
if (other is! SpanDetailsRepoReqAndRes) return false;
|
||||
|
||||
return toJson().toString() == other.toJson().toString();
|
||||
}
|
||||
|
||||
/// Overrides the hashCode getter to generate a hash code for the [SpanDetailsRepoReqAndRes] object.
|
||||
/// Used as keys in response cache in igc_controller.
|
||||
@override
|
||||
int get hashCode {
|
||||
return toJson().toString().hashCode;
|
||||
}
|
||||
}
|
||||
|
||||
final spanDataRepomockSpan = SpanData(
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue