mirror of
https://github.com/immich-app/immich.git
synced 2025-12-28 09:14:59 +03:00
fix(drift backup notifier): add lifecycle guards and dispose logging (#24806)
* fix(drift backup notifier): add lifecycle guards and dispose logging * fix(drift backup notifier): re-read notifiers in callbacks to avoid disposed backup notifier * fix(drift backup notifier): increase the log level to warning. --------- Co-authored-by: Peter Ombodi <peter.ombodi@gmail.com>
This commit is contained in:
@@ -5,16 +5,21 @@ import 'package:immich_mobile/providers/sync_status.provider.dart';
|
||||
|
||||
final backgroundSyncProvider = Provider<BackgroundSyncManager>((ref) {
|
||||
final syncStatusNotifier = ref.read(syncStatusProvider.notifier);
|
||||
final backupProvider = ref.read(driftBackupProvider.notifier);
|
||||
|
||||
final manager = BackgroundSyncManager(
|
||||
onRemoteSyncStart: () {
|
||||
syncStatusNotifier.startRemoteSync();
|
||||
backupProvider.updateError(BackupError.none);
|
||||
final backupProvider = ref.read(driftBackupProvider.notifier);
|
||||
if (backupProvider.mounted) {
|
||||
backupProvider.updateError(BackupError.none);
|
||||
}
|
||||
},
|
||||
onRemoteSyncComplete: (isSuccess) {
|
||||
syncStatusNotifier.completeRemoteSync();
|
||||
backupProvider.updateError(isSuccess == true ? BackupError.none : BackupError.syncFailed);
|
||||
final backupProvider = ref.read(driftBackupProvider.notifier);
|
||||
if (backupProvider.mounted) {
|
||||
backupProvider.updateError(isSuccess == true ? BackupError.none : BackupError.syncFailed);
|
||||
}
|
||||
},
|
||||
onRemoteSyncError: syncStatusNotifier.errorRemoteSync,
|
||||
onLocalSyncStart: syncStatusNotifier.startLocalSync,
|
||||
|
||||
@@ -212,8 +212,8 @@ class DriftBackupNotifier extends StateNotifier<DriftBackupState> {
|
||||
),
|
||||
) {
|
||||
{
|
||||
_uploadService.taskStatusStream.listen(_handleTaskStatusUpdate);
|
||||
_uploadService.taskProgressStream.listen(_handleTaskProgressUpdate);
|
||||
_statusSubscription = _uploadService.taskStatusStream.listen(_handleTaskStatusUpdate);
|
||||
_progressSubscription = _uploadService.taskProgressStream.listen(_handleTaskProgressUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,6 +224,10 @@ class DriftBackupNotifier extends StateNotifier<DriftBackupState> {
|
||||
|
||||
/// Remove upload item from state
|
||||
void _removeUploadItem(String taskId) {
|
||||
if (!mounted) {
|
||||
_logger.warning("Skip _removeUploadItem: notifier disposed");
|
||||
return;
|
||||
}
|
||||
if (state.uploadItems.containsKey(taskId)) {
|
||||
final updatedItems = Map<String, DriftUploadStatus>.from(state.uploadItems);
|
||||
updatedItems.remove(taskId);
|
||||
@@ -232,6 +236,10 @@ class DriftBackupNotifier extends StateNotifier<DriftBackupState> {
|
||||
}
|
||||
|
||||
void _handleTaskStatusUpdate(TaskStatusUpdate update) {
|
||||
if (!mounted) {
|
||||
_logger.warning("Skip _handleTaskStatusUpdate: notifier disposed");
|
||||
return;
|
||||
}
|
||||
final taskId = update.task.taskId;
|
||||
|
||||
switch (update.status) {
|
||||
@@ -291,6 +299,10 @@ class DriftBackupNotifier extends StateNotifier<DriftBackupState> {
|
||||
}
|
||||
|
||||
void _handleTaskProgressUpdate(TaskProgressUpdate update) {
|
||||
if (!mounted) {
|
||||
_logger.warning("Skip _handleTaskProgressUpdate: notifier disposed");
|
||||
return;
|
||||
}
|
||||
final taskId = update.task.taskId;
|
||||
final filename = update.task.displayName;
|
||||
final progress = update.progress;
|
||||
@@ -332,7 +344,15 @@ class DriftBackupNotifier extends StateNotifier<DriftBackupState> {
|
||||
}
|
||||
|
||||
Future<void> getBackupStatus(String userId) async {
|
||||
if (!mounted) {
|
||||
_logger.warning("Skip getBackupStatus (pre-call): notifier disposed");
|
||||
return;
|
||||
}
|
||||
final counts = await _uploadService.getBackupCounts(userId);
|
||||
if (!mounted) {
|
||||
_logger.warning("Skip getBackupStatus (post-call): notifier disposed");
|
||||
return;
|
||||
}
|
||||
|
||||
state = state.copyWith(
|
||||
totalCount: counts.total,
|
||||
@@ -343,6 +363,10 @@ class DriftBackupNotifier extends StateNotifier<DriftBackupState> {
|
||||
}
|
||||
|
||||
void updateError(BackupError error) async {
|
||||
if (!mounted) {
|
||||
_logger.warning("Skip updateError: notifier disposed");
|
||||
return;
|
||||
}
|
||||
state = state.copyWith(error: error);
|
||||
}
|
||||
|
||||
@@ -360,10 +384,18 @@ class DriftBackupNotifier extends StateNotifier<DriftBackupState> {
|
||||
}
|
||||
|
||||
Future<void> cancel() async {
|
||||
if (!mounted) {
|
||||
_logger.warning("Skip cancel (pre-call): notifier disposed");
|
||||
return;
|
||||
}
|
||||
dPrint(() => "Canceling backup tasks...");
|
||||
state = state.copyWith(enqueueCount: 0, enqueueTotalCount: 0, isCanceling: true, error: BackupError.none);
|
||||
|
||||
final activeTaskCount = await _uploadService.cancelBackup();
|
||||
if (!mounted) {
|
||||
_logger.warning("Skip cancel (post-call): notifier disposed");
|
||||
return;
|
||||
}
|
||||
|
||||
if (activeTaskCount > 0) {
|
||||
dPrint(() => "$activeTaskCount tasks left, continuing to cancel...");
|
||||
@@ -376,9 +408,17 @@ class DriftBackupNotifier extends StateNotifier<DriftBackupState> {
|
||||
}
|
||||
|
||||
Future<void> handleBackupResume(String userId) async {
|
||||
if (!mounted) {
|
||||
_logger.warning("Skip handleBackupResume (pre-call): notifier disposed");
|
||||
return;
|
||||
}
|
||||
_logger.info("Resuming backup tasks...");
|
||||
state = state.copyWith(error: BackupError.none);
|
||||
final tasks = await _uploadService.getActiveTasks(kBackupGroup);
|
||||
if (!mounted) {
|
||||
_logger.warning("Skip handleBackupResume (post-call): notifier disposed");
|
||||
return;
|
||||
}
|
||||
_logger.info("Found ${tasks.length} tasks");
|
||||
|
||||
if (tasks.isEmpty) {
|
||||
|
||||
Reference in New Issue
Block a user