Skip to content

Commit 46b94e9

Browse files
committed
chore: clean up background tasks
1 parent e239b8d commit 46b94e9

File tree

7 files changed

+69
-88
lines changed

7 files changed

+69
-88
lines changed

mobile/lib/domain/services/background_worker.service.dart

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ class BackgroundWorkerBgService extends BackgroundWorkerFlutterApi {
176176
}
177177

178178
Future<void> _handleBackup({bool processBulk = true}) async {
179-
if (!_isBackupEnabled) {
179+
if (!_isBackupEnabled || _isCleanedUp) {
180180
_logger.info("[_handleBackup 1] Backup is disabled. Skipping backup routine");
181181
return;
182182
}
@@ -205,30 +205,27 @@ class BackgroundWorkerBgService extends BackgroundWorkerFlutterApi {
205205
}
206206

207207
Future<void> _syncAssets({Duration? hashTimeout}) async {
208-
final futures = <Future<void>>[];
209-
210-
final localSyncFuture = _ref.read(backgroundSyncProvider).syncLocal().then((_) async {
211-
if (_isCleanedUp) {
212-
return;
213-
}
214-
215-
var hashFuture = _ref.read(backgroundSyncProvider).hashAssets();
216-
if (hashTimeout != null) {
217-
hashFuture = hashFuture.timeout(
218-
hashTimeout,
219-
onTimeout: () {
220-
// Consume cancellation errors as we want to continue processing
221-
},
222-
);
223-
}
208+
await _ref.read(backgroundSyncProvider).syncLocal();
209+
if (_isCleanedUp) {
210+
return;
211+
}
224212

225-
return hashFuture;
226-
});
213+
await _ref.read(backgroundSyncProvider).syncRemote();
214+
if (_isCleanedUp) {
215+
return;
216+
}
227217

228-
futures.add(localSyncFuture);
229-
futures.add(_ref.read(backgroundSyncProvider).syncRemote());
218+
var hashFuture = _ref.read(backgroundSyncProvider).hashAssets();
219+
if (hashTimeout != null) {
220+
hashFuture = hashFuture.timeout(
221+
hashTimeout,
222+
onTimeout: () {
223+
// Consume cancellation errors as we want to continue processing
224+
},
225+
);
226+
}
230227

231-
await Future.wait(futures);
228+
await hashFuture;
232229
}
233230
}
234231

mobile/lib/domain/services/sync_linked_album.service.dart

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import 'package:immich_mobile/infrastructure/repositories/local_album.repository
55
import 'package:immich_mobile/infrastructure/repositories/remote_album.repository.dart';
66
import 'package:immich_mobile/providers/infrastructure/album.provider.dart';
77
import 'package:immich_mobile/repositories/drift_album_api_repository.dart';
8+
import 'package:logging/logging.dart';
89

910
final syncLinkedAlbumServiceProvider = Provider(
1011
(ref) => SyncLinkedAlbumService(
@@ -19,7 +20,9 @@ class SyncLinkedAlbumService {
1920
final DriftRemoteAlbumRepository _remoteAlbumRepository;
2021
final DriftAlbumApiRepository _albumApiRepository;
2122

22-
const SyncLinkedAlbumService(this._localAlbumRepository, this._remoteAlbumRepository, this._albumApiRepository);
23+
SyncLinkedAlbumService(this._localAlbumRepository, this._remoteAlbumRepository, this._albumApiRepository);
24+
25+
final _log = Logger("SyncLinkedAlbumService");
2326

2427
Future<void> syncLinkedAlbums(String userId) async {
2528
final selectedAlbums = await _localAlbumRepository.getBackupAlbums();
@@ -48,8 +51,12 @@ class SyncLinkedAlbumService {
4851
}
4952

5053
Future<void> manageLinkedAlbums(List<LocalAlbum> localAlbums, String ownerId) async {
51-
for (final album in localAlbums) {
52-
await _processLocalAlbum(album, ownerId);
54+
try {
55+
for (final album in localAlbums) {
56+
await _processLocalAlbum(album, ownerId);
57+
}
58+
} catch (error, stackTrace) {
59+
_log.severe("Error managing linked albums", error, stackTrace);
5360
}
5461
}
5562

mobile/lib/pages/common/splash_screen.page.dart

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
44
import 'package:immich_mobile/domain/models/store.model.dart';
55
import 'package:immich_mobile/entities/store.entity.dart';
66
import 'package:immich_mobile/providers/auth.provider.dart';
7+
import 'package:immich_mobile/providers/background_sync.provider.dart';
78
import 'package:immich_mobile/providers/backup/backup.provider.dart';
89
import 'package:immich_mobile/providers/gallery_permission.provider.dart';
910
import 'package:immich_mobile/providers/server_info.provider.dart';
@@ -47,11 +48,23 @@ class SplashScreenPageState extends ConsumerState<SplashScreenPage> {
4748
if (accessToken != null && serverUrl != null && endpoint != null) {
4849
final infoProvider = ref.read(serverInfoProvider.notifier);
4950
final wsProvider = ref.read(websocketProvider.notifier);
51+
final backgroundManager = ref.read(backgroundSyncProvider);
52+
5053
ref.read(authProvider.notifier).saveAuthInfo(accessToken: accessToken).then(
51-
(a) {
54+
(isAuth) async {
5255
try {
5356
wsProvider.connect();
5457
infoProvider.getServerInfo();
58+
59+
if (Store.isBetaTimelineEnabled) {
60+
await backgroundManager.syncLocal();
61+
await backgroundManager.syncRemote();
62+
await backgroundManager.hashAssets();
63+
}
64+
65+
if (Store.get(StoreKey.syncAlbums, false)) {
66+
await backgroundManager.syncLinkedAlbum();
67+
}
5568
} catch (e) {
5669
log.severe('Failed establishing connection to the server: $e');
5770
}

mobile/lib/pages/common/tab_shell.page.dart

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
77
import 'package:immich_mobile/domain/models/timeline.model.dart';
88
import 'package:immich_mobile/domain/utils/event_stream.dart';
99
import 'package:immich_mobile/extensions/build_context_extensions.dart';
10-
import 'package:immich_mobile/providers/app_settings.provider.dart';
11-
import 'package:immich_mobile/providers/backup/drift_backup.provider.dart';
1210
import 'package:immich_mobile/providers/haptic_feedback.provider.dart';
1311
import 'package:immich_mobile/providers/infrastructure/album.provider.dart';
1412
import 'package:immich_mobile/providers/infrastructure/memory.provider.dart';
@@ -17,11 +15,7 @@ import 'package:immich_mobile/providers/infrastructure/readonly_mode.provider.da
1715
import 'package:immich_mobile/providers/search/search_input_focus.provider.dart';
1816
import 'package:immich_mobile/providers/tab.provider.dart';
1917
import 'package:immich_mobile/providers/timeline/multiselect.provider.dart';
20-
import 'package:immich_mobile/providers/user.provider.dart';
21-
import 'package:immich_mobile/providers/websocket.provider.dart';
2218
import 'package:immich_mobile/routing/router.dart';
23-
import 'package:immich_mobile/services/app_settings.service.dart';
24-
import 'package:immich_mobile/utils/migration.dart';
2519

2620
@RoutePage()
2721
class TabShellPage extends ConsumerStatefulWidget {
@@ -32,28 +26,6 @@ class TabShellPage extends ConsumerStatefulWidget {
3226
}
3327

3428
class _TabShellPageState extends ConsumerState<TabShellPage> {
35-
@override
36-
void initState() {
37-
super.initState();
38-
39-
WidgetsBinding.instance.addPostFrameCallback((_) async {
40-
ref.read(websocketProvider.notifier).connect();
41-
42-
final isEnableBackup = ref.read(appSettingsServiceProvider).getSetting(AppSettingsEnum.enableBackup);
43-
44-
await runNewSync(ref, full: true).then((_) async {
45-
if (isEnableBackup) {
46-
final currentUser = ref.read(currentUserProvider);
47-
if (currentUser == null) {
48-
return;
49-
}
50-
51-
await ref.read(driftBackupProvider.notifier).handleBackupResume(currentUser.id);
52-
}
53-
});
54-
});
55-
}
56-
5729
@override
5830
Widget build(BuildContext context) {
5931
final isScreenLandscape = context.orientation == Orientation.landscape;

mobile/lib/providers/app_life_cycle.provider.dart

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -148,19 +148,21 @@ class AppLifeCycleNotifier extends StateNotifier<AppLifeCycleEnum> {
148148

149149
try {
150150
// Run operations sequentially with state checks and error handling for each
151-
_safeRun(backgroundManager.syncLocal(), "syncLocal");
152-
_safeRun(backgroundManager.hashAssets(), "hashAssets");
153-
_safeRun(backgroundManager.syncRemote(), "syncRemote").then((_) {
154-
if (isAlbumLinkedSyncEnable) {
155-
_safeRun(backgroundManager.syncLinkedAlbum(), "syncLinkedAlbum");
156-
}
157-
});
151+
await _safeRun(backgroundManager.syncLocal(), "syncLocal");
152+
await _safeRun(backgroundManager.syncRemote(), "syncRemote");
153+
await _safeRun(backgroundManager.hashAssets(), "hashAssets");
154+
if (isAlbumLinkedSyncEnable) {
155+
await _safeRun(backgroundManager.syncLinkedAlbum(), "syncLinkedAlbum");
156+
}
158157

159158
// Handle backup resume only if still active
160159
if (isEnableBackup) {
161160
final currentUser = _ref.read(currentUserProvider);
162161
if (currentUser != null) {
163-
_safeRun(_ref.read(driftBackupProvider.notifier).handleBackupResume(currentUser.id), "handleBackupResume");
162+
await _safeRun(
163+
_ref.read(driftBackupProvider.notifier).handleBackupResume(currentUser.id),
164+
"handleBackupResume",
165+
);
164166
}
165167
}
166168
} catch (e, stackTrace) {

mobile/lib/utils/migration.dart

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import 'dart:io';
55
import 'package:collection/collection.dart';
66
import 'package:drift/drift.dart';
77
import 'package:flutter/foundation.dart';
8-
import 'package:hooks_riverpod/hooks_riverpod.dart';
98
import 'package:immich_mobile/domain/models/album/local_album.model.dart';
109
import 'package:immich_mobile/domain/models/store.model.dart';
1110
import 'package:immich_mobile/entities/album.entity.dart';
@@ -23,13 +22,8 @@ import 'package:immich_mobile/infrastructure/entities/store.entity.dart';
2322
import 'package:immich_mobile/infrastructure/entities/store.entity.drift.dart';
2423
import 'package:immich_mobile/infrastructure/entities/user.entity.dart';
2524
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
26-
import 'package:immich_mobile/providers/app_settings.provider.dart';
27-
import 'package:immich_mobile/providers/background_sync.provider.dart';
28-
import 'package:immich_mobile/providers/backup/backup.provider.dart';
29-
import 'package:immich_mobile/services/app_settings.service.dart';
3025
import 'package:immich_mobile/utils/diff.dart';
3126
import 'package:isar/isar.dart';
32-
import 'package:logging/logging.dart';
3327
// ignore: import_rule_photo_manager
3428
import 'package:photo_manager/photo_manager.dart';
3529

@@ -310,25 +304,6 @@ class _DeviceAsset {
310304
const _DeviceAsset({required this.assetId, this.hash, this.dateTime});
311305
}
312306

313-
Future<List<void>> runNewSync(WidgetRef ref, {bool full = false}) {
314-
ref.read(backupProvider.notifier).cancelBackup();
315-
316-
final backgroundManager = ref.read(backgroundSyncProvider);
317-
final isAlbumLinkedSyncEnable = ref.read(appSettingsServiceProvider).getSetting(AppSettingsEnum.syncAlbums);
318-
319-
return Future.wait([
320-
backgroundManager.syncLocal(full: full).then((_) {
321-
Logger("runNewSync").fine("Hashing assets after syncLocal");
322-
return backgroundManager.hashAssets();
323-
}),
324-
backgroundManager.syncRemote().then((_) {
325-
if (isAlbumLinkedSyncEnable) {
326-
return backgroundManager.syncLinkedAlbum();
327-
}
328-
}),
329-
]);
330-
}
331-
332307
Future<void> resetDriftDatabase(Drift drift) async {
333308
// https://github.com/simolus3/drift/commit/bd80a46264b6dd833ef4fd87fffc03f5a832ab41#diff-3f879e03b4a35779344ef16170b9353608dd9c42385f5402ec6035aac4dd8a04R76-R94
334309
final database = drift.attachedDatabase;

mobile/lib/widgets/forms/login/login_form.dart

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@ import 'package:flutter/services.dart';
1010
import 'package:flutter_hooks/flutter_hooks.dart' hide Store;
1111
import 'package:fluttertoast/fluttertoast.dart';
1212
import 'package:hooks_riverpod/hooks_riverpod.dart';
13+
import 'package:immich_mobile/domain/models/store.model.dart';
1314
import 'package:immich_mobile/entities/store.entity.dart';
1415
import 'package:immich_mobile/extensions/build_context_extensions.dart';
1516
import 'package:immich_mobile/providers/auth.provider.dart';
17+
import 'package:immich_mobile/providers/background_sync.provider.dart';
1618
import 'package:immich_mobile/providers/backup/backup.provider.dart';
1719
import 'package:immich_mobile/providers/gallery_permission.provider.dart';
1820
import 'package:immich_mobile/providers/oauth.provider.dart';
@@ -161,6 +163,18 @@ class LoginForm extends HookConsumerWidget {
161163
serverEndpointController.text = 'http://10.1.15.216:2283/api';
162164
}
163165

166+
Future<void> handleSyncFlow() async {
167+
final backgroundManager = ref.read(backgroundSyncProvider);
168+
169+
await backgroundManager.syncLocal(full: true);
170+
await backgroundManager.syncRemote();
171+
await backgroundManager.hashAssets();
172+
173+
if (Store.get(StoreKey.syncAlbums, false)) {
174+
await backgroundManager.syncLinkedAlbum();
175+
}
176+
}
177+
164178
login() async {
165179
TextInput.finishAutofillContext();
166180

@@ -178,7 +192,7 @@ class LoginForm extends HookConsumerWidget {
178192
final isBeta = Store.isBetaTimelineEnabled;
179193
if (isBeta) {
180194
await ref.read(galleryPermissionNotifier.notifier).requestGalleryPermission();
181-
195+
handleSyncFlow();
182196
context.replaceRoute(const TabShellRoute());
183197
return;
184198
}
@@ -276,6 +290,7 @@ class LoginForm extends HookConsumerWidget {
276290
}
277291
if (isBeta) {
278292
await ref.read(galleryPermissionNotifier.notifier).requestGalleryPermission();
293+
handleSyncFlow();
279294
context.replaceRoute(const TabShellRoute());
280295
return;
281296
}

0 commit comments

Comments
 (0)