fixed igc match and implemented cache system (#1165)

* fixed igc match and implemented cache system

* code cleanup

* remove unused spanDetailsCache

* updated igc request hash function, use igc request hash as cache key

* give both caches their own timer and clear on interval

* made igc data cache entries into futures and removed previous message cache

* clear IGC cache at the right time, restart timer if it's been stopped

---------

Co-authored-by: choreo development <williamjordan-cooley@Williams-MacBook-Pro-3.local>
Co-authored-by: ggurdin <46800240+ggurdin@users.noreply.github.com>
Co-authored-by: ggurdin <ggurdin@gmail.com>
This commit is contained in:
a_youngdiggs 2024-12-12 09:45:04 -05:00 committed by GitHub
parent dee409e41d
commit 4cc7483c27
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 96 additions and 5 deletions

View file

@ -457,7 +457,7 @@ class Choreographer {
isFetching = false;
choreoRecord = ChoreoRecord.newRecord;
itController.clear();
igc.clear();
igc.dispose();
//@ggurdin - why is this commented out?
// errorService.clear();
_resetDebounceTimer();

View file

@ -17,6 +17,12 @@ import '../../models/span_card_model.dart';
import '../../utils/error_handler.dart';
import '../../utils/overlay.dart';
class _IGCTextDataCacheItem {
Future<IGCTextData> data;
_IGCTextDataCacheItem({required this.data});
}
class IgcController {
Choreographer choreographer;
IGCTextData? igcTextData;
@ -24,8 +30,20 @@ class IgcController {
Completer<IGCTextData> igcCompleter = Completer();
late SpanDataController spanDataController;
// cache for IGC data and prev message
final Map<int, _IGCTextDataCacheItem> _igcTextDataCache = {};
Timer? _igcCacheClearTimer;
IgcController(this.choreographer) {
spanDataController = SpanDataController(choreographer);
_initializeCacheClearing();
}
void _initializeCacheClearing() {
const duration = Duration(minutes: 1);
_igcCacheClearTimer =
Timer.periodic(duration, (Timer t) => _igcTextDataCache.clear());
}
Future<void> getIGCTextData({
@ -49,15 +67,37 @@ class IgcController {
prevMessages: prevMessages(),
);
final IGCTextData igcTextDataResponse = await IgcRepo.getIGC(
if (_igcCacheClearTimer == null || !_igcCacheClearTimer!.isActive) {
_initializeCacheClearing();
}
// Check if cached data exists
if (_igcTextDataCache.containsKey(reqBody.hashCode)) {
igcTextData = await _igcTextDataCache[reqBody.hashCode]!.data;
return;
}
final igcFuture = IgcRepo.getIGC(
choreographer.accessToken,
igcRequest: reqBody,
);
_igcTextDataCache[reqBody.hashCode] =
_IGCTextDataCacheItem(data: igcFuture);
final IGCTextData igcTextDataResponse =
await _igcTextDataCache[reqBody.hashCode]!.data;
// this will happen when the user changes the input while igc is fetching results
if (igcTextDataResponse.originalInput != choreographer.currentText) {
return;
}
// get ignored matches from the original igcTextData
// if the new matches are the same as the original match
// could possibly change the status of the new match
// thing is the same if the text we are trying to change is the smae
// as the new text we are trying to change (suggestion is the same)
// Check for duplicate or minor text changes that shouldn't trigger suggestions
// checks for duplicate input
igcTextData = igcTextDataResponse;
@ -158,7 +198,8 @@ class IgcController {
choreographer.l2LangCode,
)
?.transcript
.text;
.text
.trim(); // trim whitespace
if (content == null) continue;
messages.add(
PreviousMessage(
@ -189,7 +230,12 @@ class IgcController {
clear() {
igcTextData = null;
spanDataController.clearCache();
// Not sure why this is here
// MatrixState.pAnyState.closeOverlay();
spanDataController.dispose();
}
dispose() {
clear();
_igcTextDataCache.clear();
_igcCacheClearTimer?.cancel();
}
}

View file

@ -121,6 +121,26 @@ class PreviousMessage {
ModelKey.prevSender: sender,
ModelKey.prevTimestamp: timestamp.toIso8601String(),
};
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
if (other is! PreviousMessage) return false;
return content == other.content &&
sender == other.sender &&
timestamp == other.timestamp;
}
@override
int get hashCode {
return Object.hash(
content,
sender,
timestamp,
);
}
}
class IGCRequestBody {
@ -152,4 +172,29 @@ class IGCRequestBody {
ModelKey.prevMessages:
jsonEncode(prevMessages.map((x) => x.toJson()).toList()),
};
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
if (other is! IGCRequestBody) return false;
return fullText.trim() == other.fullText.trim() &&
fullText == other.fullText &&
userL1 == other.userL1 &&
userL2 == other.userL2 &&
enableIT == other.enableIT &&
userId == other.userId;
}
@override
int get hashCode => Object.hash(
fullText.trim(),
userL1,
userL2,
enableIT,
enableIGC,
userId,
Object.hashAll(prevMessages),
);
}