From fc9370caca93c41560d2f764c3f4571282caf0ac Mon Sep 17 00:00:00 2001 From: mertalev <101130780+mertalev@users.noreply.github.com> Date: Sun, 17 Nov 2024 16:58:11 -0500 Subject: [PATCH 1/6] use sets in album sync, concurrent futures --- mobile/lib/services/album.service.dart | 27 ++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/mobile/lib/services/album.service.dart b/mobile/lib/services/album.service.dart index 53a65e2869aea..b251d72a0219e 100644 --- a/mobile/lib/services/album.service.dart +++ b/mobile/lib/services/album.service.dart @@ -76,10 +76,16 @@ class AlbumService { final Stopwatch sw = Stopwatch()..start(); bool changes = false; try { - final List excludedIds = await _backupAlbumRepository - .getIdsBySelection(BackupSelection.exclude); - final List selectedIds = await _backupAlbumRepository - .getIdsBySelection(BackupSelection.select); + final (selectedIds, excludedIds, onDevice) = await ( + _backupAlbumRepository + .getIdsBySelection(BackupSelection.select) + .then((value) => value.toSet()), + _backupAlbumRepository + .getIdsBySelection(BackupSelection.exclude) + .then((value) => value.toSet()), + _albumMediaRepository.getAll() + ).wait; + _log.info("Found ${onDevice.length} device albums"); if (selectedIds.isEmpty) { final numLocal = await _albumRepository.count(local: true); if (numLocal > 0) { @@ -87,8 +93,6 @@ class AlbumService { } return false; } - final List onDevice = await _albumMediaRepository.getAll(); - _log.info("Found ${onDevice.length} device albums"); Set? excludedAssets; if (excludedIds.isNotEmpty) { if (Platform.isIOS) { @@ -138,7 +142,7 @@ class AlbumService { Future> _loadExcludedAssetIds( List albums, - List excludedAlbumIds, + Set excludedAlbumIds, ) async { final Set result = HashSet(); for (Album album in albums) { @@ -163,11 +167,10 @@ class AlbumService { bool changes = false; try { await _userService.refreshUsers(); - final List sharedAlbum = - await _albumApiRepository.getAll(shared: true); - - final List ownedAlbum = - await _albumApiRepository.getAll(shared: null); + final (sharedAlbum, ownedAlbum) = await ( + _albumApiRepository.getAll(shared: true), + _albumApiRepository.getAll(shared: null) + ).wait; final albums = HashSet( equals: (a, b) => a.remoteId == b.remoteId, From e29ff47eec4b28964b88d3eeab115eb626fcd788 Mon Sep 17 00:00:00 2001 From: mertalev <101130780+mertalev@users.noreply.github.com> Date: Sun, 17 Nov 2024 17:09:46 -0500 Subject: [PATCH 2/6] batch excluded asset IDs --- mobile/lib/services/album.service.dart | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/mobile/lib/services/album.service.dart b/mobile/lib/services/album.service.dart index b251d72a0219e..771dabdb0f3e2 100644 --- a/mobile/lib/services/album.service.dart +++ b/mobile/lib/services/album.service.dart @@ -145,12 +145,16 @@ class AlbumService { Set excludedAlbumIds, ) async { final Set result = HashSet(); - for (Album album in albums) { - if (excludedAlbumIds.contains(album.localId)) { - final assetIds = - await _albumMediaRepository.getAssetIds(album.localId!); - result.addAll(assetIds); - } + for (final batchAlbums in albums + .where((album) => excludedAlbumIds.contains(album.localId)) + .slices(5)) { + await batchAlbums + .map( + (album) => _albumMediaRepository + .getAssetIds(album.localId!) + .then((assetIds) => result.addAll(assetIds)), + ) + .wait; } return result; } From a2eeec13396b18f4b8848bdc44dbc1571a7d3c83 Mon Sep 17 00:00:00 2001 From: mertalev <101130780+mertalev@users.noreply.github.com> Date: Sun, 17 Nov 2024 17:19:15 -0500 Subject: [PATCH 3/6] update test --- mobile/test/services/album.service_test.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/mobile/test/services/album.service_test.dart b/mobile/test/services/album.service_test.dart index 848d7cfad7078..c0775a1c3e070 100644 --- a/mobile/test/services/album.service_test.dart +++ b/mobile/test/services/album.service_test.dart @@ -54,6 +54,7 @@ void main() { .thenAnswer((_) async => []); when(() => backupRepository.getIdsBySelection(BackupSelection.select)) .thenAnswer((_) async => []); + when(() => albumMediaRepository.getAll()).thenAnswer((_) async => []); when(() => albumRepository.count(local: true)).thenAnswer((_) async => 1); when(() => syncService.removeAllLocalAlbumsAndAssets()) .thenAnswer((_) async => true); From 0faef91918f87684fda90cb8c352bf538adc11a0 Mon Sep 17 00:00:00 2001 From: mertalev <101130780+mertalev@users.noreply.github.com> Date: Sun, 17 Nov 2024 18:03:46 -0500 Subject: [PATCH 4/6] take advantage of sets in Recents check --- mobile/lib/services/album.service.dart | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/mobile/lib/services/album.service.dart b/mobile/lib/services/album.service.dart index 771dabdb0f3e2..108732ffae88d 100644 --- a/mobile/lib/services/album.service.dart +++ b/mobile/lib/services/album.service.dart @@ -112,24 +112,21 @@ class AlbumService { "Ignoring ${excludedIds.length} excluded albums resulting in ${onDevice.length} device albums", ); } - final hasAll = selectedIds - .map( - (id) => onDevice.firstWhereOrNull((album) => album.localId == id), - ) - .whereNotNull() - .any((a) => a.isAll); - if (hasAll) { + + final allAlbum = onDevice.firstWhereOrNull((album) => album.isAll); + if (allAlbum != null && selectedIds.contains(allAlbum.localId)) { + // remove the virtual "Recent" album and keep and individual albums + // on Android, the virtual "Recent" `lastModified` value is always null if (Platform.isAndroid) { - // remove the virtual "Recent" album and keep and individual albums - // on Android, the virtual "Recent" `lastModified` value is always null - onDevice.removeWhere((e) => e.isAll); - _log.info("'Recents' is selected, keeping all individual albums"); + onDevice.removeWhere((album) => album.isAll); } + _log.info("'Recents' is selected, keeping all individual albums"); } else { // keep only the explicitly selected albums - onDevice.removeWhere((e) => !selectedIds.contains(e.localId)); + onDevice.removeWhere((album) => !selectedIds.contains(album.localId)); _log.info("'Recents' is not selected, keeping only selected albums"); } + changes = await _syncService.syncLocalAlbumAssetsToDb(onDevice, excludedAssets); _log.info("Syncing completed. Changes: $changes"); From 1003319c5c8311458794e6e34982279890f46003 Mon Sep 17 00:00:00 2001 From: mertalev <101130780+mertalev@users.noreply.github.com> Date: Sun, 17 Nov 2024 18:05:00 -0500 Subject: [PATCH 5/6] move log statement --- mobile/lib/services/album.service.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mobile/lib/services/album.service.dart b/mobile/lib/services/album.service.dart index 108732ffae88d..06cdc331e742f 100644 --- a/mobile/lib/services/album.service.dart +++ b/mobile/lib/services/album.service.dart @@ -119,8 +119,8 @@ class AlbumService { // on Android, the virtual "Recent" `lastModified` value is always null if (Platform.isAndroid) { onDevice.removeWhere((album) => album.isAll); + _log.info("'Recents' is selected, keeping all individual albums"); } - _log.info("'Recents' is selected, keeping all individual albums"); } else { // keep only the explicitly selected albums onDevice.removeWhere((album) => !selectedIds.contains(album.localId)); From f1dde03b69415184466bf41f30b99a3113a78a2c Mon Sep 17 00:00:00 2001 From: mertalev <101130780+mertalev@users.noreply.github.com> Date: Sun, 17 Nov 2024 18:09:05 -0500 Subject: [PATCH 6/6] smaller diff --- mobile/lib/services/album.service.dart | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mobile/lib/services/album.service.dart b/mobile/lib/services/album.service.dart index 06cdc331e742f..1a2370591658f 100644 --- a/mobile/lib/services/album.service.dart +++ b/mobile/lib/services/album.service.dart @@ -114,10 +114,11 @@ class AlbumService { } final allAlbum = onDevice.firstWhereOrNull((album) => album.isAll); - if (allAlbum != null && selectedIds.contains(allAlbum.localId)) { - // remove the virtual "Recent" album and keep and individual albums - // on Android, the virtual "Recent" `lastModified` value is always null + final hasAll = allAlbum != null && selectedIds.contains(allAlbum.localId); + if (hasAll) { if (Platform.isAndroid) { + // remove the virtual "Recent" album and keep and individual albums + // on Android, the virtual "Recent" `lastModified` value is always null onDevice.removeWhere((album) => album.isAll); _log.info("'Recents' is selected, keeping all individual albums"); } @@ -126,7 +127,6 @@ class AlbumService { onDevice.removeWhere((album) => !selectedIds.contains(album.localId)); _log.info("'Recents' is not selected, keeping only selected albums"); } - changes = await _syncService.syncLocalAlbumAssetsToDb(onDevice, excludedAssets); _log.info("Syncing completed. Changes: $changes");