diff --git a/mobile/lib/domain/services/background_worker.service.dart b/mobile/lib/domain/services/background_worker.service.dart index a2e96f2313..6316fbe650 100644 --- a/mobile/lib/domain/services/background_worker.service.dart +++ b/mobile/lib/domain/services/background_worker.service.dart @@ -128,17 +128,31 @@ class BackgroundWorkerBgService extends BackgroundWorkerFlutterApi { _logger.info('iOS background upload started with maxSeconds: ${maxSeconds}s'); final sw = Stopwatch()..start(); try { - final timeout = isRefresh ? const Duration(seconds: 5) : Duration(minutes: _isBackupEnabled ? 3 : 6); - if (!await _syncAssets(hashTimeout: timeout)) { - _logger.warning("Remote sync did not complete successfully, skipping backup"); + final hashTimeout = isRefresh + ? Duration(seconds: (maxSeconds ?? 20) - 1) + : Duration(minutes: _isBackupEnabled ? 3 : 6); + final budget = maxSeconds != null ? Duration(seconds: maxSeconds - 1) : null; + + final sync = _ref?.read(backgroundSyncProvider); + if (sync == null) { return; } + // Run sync local, sync remote, hash and backup concurrently so the bg + // refresh task (20s budget) can make progress on all four instead of + // racing them sequentially. Phases are independent at the data layer: + // hash and handle_backup read drift state and tolerate stale reads + // (server-side dedup catches the rare race). + final localFuture = sync.syncLocal(); + final remoteFuture = sync.syncRemote(); + final hashFuture = sync.hashAssets().timeout(hashTimeout, onTimeout: () {}); final backupFuture = _handleBackup(); - if (maxSeconds != null) { - await backupFuture.timeout(Duration(seconds: maxSeconds - 1), onTimeout: () {}); + + final all = Future.wait([localFuture, remoteFuture, hashFuture, backupFuture]); + if (budget != null) { + await all.timeout(budget, onTimeout: () => []); } else { - await backupFuture; + await all; } } catch (error, stack) { _logger.severe("Failed to complete iOS background upload", error, stack); diff --git a/mobile/lib/infrastructure/repositories/local_album.repository.dart b/mobile/lib/infrastructure/repositories/local_album.repository.dart index 9b355334d4..2c80385c34 100644 --- a/mobile/lib/infrastructure/repositories/local_album.repository.dart +++ b/mobile/lib/infrastructure/repositories/local_album.repository.dart @@ -241,7 +241,7 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository { innerJoin(_db.localAssetEntity, _db.localAlbumAssetEntity.assetId.equalsExp(_db.localAssetEntity.id)), ]) ..where(_db.localAlbumAssetEntity.albumId.equals(albumId) & _db.localAssetEntity.checksum.isNull()) - ..orderBy([OrderingTerm.asc(_db.localAssetEntity.id)]); + ..orderBy([OrderingTerm.desc(_db.localAssetEntity.createdAt)]); return query.map((row) => row.readTable(_db.localAssetEntity).toDto()).get(); }