From 556177358e136efa9a1766f43bb24f9e676ad86d Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Tue, 1 Jul 2025 11:11:24 +0530 Subject: [PATCH] Cache persons data --- .../face_ml/person/person_service.dart | 56 ++++++++++++++----- 1 file changed, 42 insertions(+), 14 deletions(-) diff --git a/mobile/lib/services/machine_learning/face_ml/person/person_service.dart b/mobile/lib/services/machine_learning/face_ml/person/person_service.dart index 7f46dacd79..3fe95041c0 100644 --- a/mobile/lib/services/machine_learning/face_ml/person/person_service.dart +++ b/mobile/lib/services/machine_learning/face_ml/person/person_service.dart @@ -1,6 +1,7 @@ import "dart:convert"; import "dart:developer"; +import "package:computer/computer.dart"; import "package:flutter/foundation.dart"; import "package:logging/logging.dart"; import "package:photos/core/event_bus.dart"; @@ -30,6 +31,9 @@ class PersonService { static const kPersonIDKey = "person_id"; static const kNameKey = "name"; + Future>? _cachedPersonsFuture; + int _lastPersonCacheRefresh = 0; + static PersonService get instance { if (_instance == null) { throw Exception("PersonService not initialized"); @@ -55,21 +59,14 @@ class PersonService { void clearCache() { _emailToPartialPersonDataMapCache.clear(); + _cachedPersonsFuture = null; + _lastPersonCacheRefresh = 0; } Future refreshPersonCache() async { - _emailToPartialPersonDataMapCache.clear(); - await getPersons().then((value) { - for (var person in value) { - if (person.data.email != null && person.data.email!.isNotEmpty) { - _instance!._emailToPartialPersonDataMapCache[person.data.email!] = { - kPersonIDKey: person.remoteID, - kNameKey: person.data.name, - }; - } - } - logger.info("Email to partial person data cache reset"); - }); + _lastPersonCacheRefresh = 0; + // wait to ensure cache is refreshed + final _ = await getPersons(); } Future> getCertainPersons(List ids) async { @@ -90,9 +87,40 @@ class PersonService { } Future> getPersons() async { - // perf todo: move this json decode in computer, and use cached future - // to read values from DB and also poulate the emailPartialPersonDataMapCache + if (_lastPersonCacheRefresh != lastRemoteSyncTime()) { + _lastPersonCacheRefresh = lastRemoteSyncTime(); + _cachedPersonsFuture = null; // Invalidate cache + } + _cachedPersonsFuture ??= _fetchAndCachePersons(); + return _cachedPersonsFuture!; + } + + Future> _fetchAndCachePersons() async { + logger.finest("reading all persons from local db"); final entities = await entityService.getEntities(EntityType.cgroup); + // Only use compute for large datasets to avoid overhead + final persons = await Computer.shared().compute( + _decodePersonEntities, + param: {"entity": entities}, + ); + // Populate email cache if needed + _emailToPartialPersonDataMapCache.clear(); + for (var person in persons) { + if (person.data.email != null && person.data.email!.isNotEmpty) { + _emailToPartialPersonDataMapCache[person.data.email!] = { + kPersonIDKey: person.remoteID, + kNameKey: person.data.name, + }; + } + } + + return persons; + } + + static List _decodePersonEntities( + Map param, + ) { + final entities = param["entity"] as List; return entities .map( (e) => PersonEntity(