fix: concurrency issue (#21830)

This commit is contained in:
Alex 2025-09-11 14:02:03 -05:00 committed by GitHub
parent 722a464e23
commit 42a03f2556
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 90 additions and 73 deletions

View file

@ -169,7 +169,10 @@ class BackgroundWorkerBgService extends BackgroundWorkerFlutterApi {
} }
try { try {
final backgroundSyncManager = _ref.read(backgroundSyncProvider);
_isCleanedUp = true; _isCleanedUp = true;
_ref.dispose();
_cancellationToken.cancel(); _cancellationToken.cancel();
_logger.info("Cleaning up background worker"); _logger.info("Cleaning up background worker");
final cleanupFutures = [ final cleanupFutures = [
@ -179,14 +182,13 @@ class BackgroundWorkerBgService extends BackgroundWorkerFlutterApi {
}), }),
_drift.close(), _drift.close(),
_driftLogger.close(), _driftLogger.close(),
_ref.read(backgroundSyncProvider).cancel(), backgroundSyncManager.cancel(),
_ref.read(backgroundSyncProvider).cancelLocal(), backgroundSyncManager.cancelLocal(),
]; ];
if (_isar.isOpen) { if (_isar.isOpen) {
cleanupFutures.add(_isar.close()); cleanupFutures.add(_isar.close());
} }
_ref.dispose();
await Future.wait(cleanupFutures); await Future.wait(cleanupFutures);
_logger.info("Background worker resources cleaned up"); _logger.info("Background worker resources cleaned up");
} catch (error, stack) { } catch (error, stack) {
@ -195,6 +197,8 @@ class BackgroundWorkerBgService extends BackgroundWorkerFlutterApi {
} }
Future<void> _handleBackup() async { Future<void> _handleBackup() async {
await runZonedGuarded(
() async {
if (!_isBackupEnabled || _isCleanedUp) { if (!_isBackupEnabled || _isCleanedUp) {
_logger.info("[_handleBackup 1] Backup is disabled. Skipping backup routine"); _logger.info("[_handleBackup 1] Backup is disabled. Skipping backup routine");
return; return;
@ -224,6 +228,11 @@ class BackgroundWorkerBgService extends BackgroundWorkerFlutterApi {
return _ref return _ref
.read(uploadServiceProvider) .read(uploadServiceProvider)
.startBackupWithHttpClient(currentUser.id, networkCapabilities.hasWifi, _cancellationToken); .startBackupWithHttpClient(currentUser.id, networkCapabilities.hasWifi, _cancellationToken);
},
(error, stack) {
debugPrint("Error in backup zone $error, $stack");
},
);
} }
Future<void> _syncAssets({Duration? hashTimeout}) async { Future<void> _syncAssets({Duration? hashTimeout}) async {

View file

@ -1,9 +1,10 @@
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/domain/models/store.model.dart';
import 'package:immich_mobile/domain/services/sync_linked_album.service.dart'; import 'package:immich_mobile/domain/services/sync_linked_album.service.dart';
import 'package:immich_mobile/providers/user.provider.dart'; import 'package:immich_mobile/entities/store.entity.dart';
Future<void> syncLinkedAlbumsIsolated(ProviderContainer ref) { Future<void> syncLinkedAlbumsIsolated(ProviderContainer ref) {
final user = ref.read(currentUserProvider); final user = Store.tryGet(StoreKey.currentUser);
if (user == null) { if (user == null) {
return Future.value(); return Future.value();
} }

View file

@ -46,7 +46,7 @@ void main() async {
await Bootstrap.initDomain(isar, drift, logDb); await Bootstrap.initDomain(isar, drift, logDb);
await initApp(); await initApp();
// Warm-up isolate pool for worker manager // Warm-up isolate pool for worker manager
await workerManager.init(dynamicSpawning: false); await workerManager.init(dynamicSpawning: true);
await migrateDatabaseIfNeeded(isar, drift); await migrateDatabaseIfNeeded(isar, drift);
HttpSSLOptions.apply(); HttpSSLOptions.apply();

View file

@ -31,6 +31,8 @@ Cancelable<T?> runInIsolateGentle<T>({
} }
return workerManager.executeGentle((cancelledChecker) async { return workerManager.executeGentle((cancelledChecker) async {
await runZonedGuarded(
() async {
BackgroundIsolateBinaryMessenger.ensureInitialized(token); BackgroundIsolateBinaryMessenger.ensureInitialized(token);
DartPluginRegistrant.ensureInitialized(); DartPluginRegistrant.ensureInitialized();
@ -57,21 +59,20 @@ Cancelable<T?> runInIsolateGentle<T>({
log.severe("Error in runInIsolateGentle ${debugLabel == null ? '' : ' for $debugLabel'}", error, stack); log.severe("Error in runInIsolateGentle ${debugLabel == null ? '' : ' for $debugLabel'}", error, stack);
} finally { } finally {
try { try {
ref.dispose();
await LogService.I.dispose(); await LogService.I.dispose();
await logDb.close(); await logDb.close();
await ref.read(driftProvider).close(); await drift.close();
// Close Isar safely // Close Isar safely
try { try {
final isar = ref.read(isarProvider);
if (isar.isOpen) { if (isar.isOpen) {
await isar.close(); await isar.close();
} }
} catch (e) { } catch (e) {
debugPrint("Error closing Isar: $e"); debugPrint("Error closing Isar: $e");
} }
ref.dispose();
} catch (error, stack) { } catch (error, stack) {
debugPrint("Error closing resources in isolate: $error, $stack"); debugPrint("Error closing resources in isolate: $error, $stack");
} finally { } finally {
@ -81,5 +82,11 @@ Cancelable<T?> runInIsolateGentle<T>({
} }
} }
return null; return null;
},
(error, stack) {
debugPrint("Error in isolate zone: $error, $stack");
},
);
return null;
}); });
} }