mirror of
https://github.com/samsonjs/immich.git
synced 2026-04-27 15:07:45 +00: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:
parent
724948d36d
commit
a57c4d9a9e
2 changed files with 50 additions and 5 deletions
|
|
@ -5,16 +5,21 @@ import 'package:immich_mobile/providers/sync_status.provider.dart';
|
||||||
|
|
||||||
final backgroundSyncProvider = Provider<BackgroundSyncManager>((ref) {
|
final backgroundSyncProvider = Provider<BackgroundSyncManager>((ref) {
|
||||||
final syncStatusNotifier = ref.read(syncStatusProvider.notifier);
|
final syncStatusNotifier = ref.read(syncStatusProvider.notifier);
|
||||||
final backupProvider = ref.read(driftBackupProvider.notifier);
|
|
||||||
|
|
||||||
final manager = BackgroundSyncManager(
|
final manager = BackgroundSyncManager(
|
||||||
onRemoteSyncStart: () {
|
onRemoteSyncStart: () {
|
||||||
syncStatusNotifier.startRemoteSync();
|
syncStatusNotifier.startRemoteSync();
|
||||||
backupProvider.updateError(BackupError.none);
|
final backupProvider = ref.read(driftBackupProvider.notifier);
|
||||||
|
if (backupProvider.mounted) {
|
||||||
|
backupProvider.updateError(BackupError.none);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onRemoteSyncComplete: (isSuccess) {
|
onRemoteSyncComplete: (isSuccess) {
|
||||||
syncStatusNotifier.completeRemoteSync();
|
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,
|
onRemoteSyncError: syncStatusNotifier.errorRemoteSync,
|
||||||
onLocalSyncStart: syncStatusNotifier.startLocalSync,
|
onLocalSyncStart: syncStatusNotifier.startLocalSync,
|
||||||
|
|
|
||||||
|
|
@ -212,8 +212,8 @@ class DriftBackupNotifier extends StateNotifier<DriftBackupState> {
|
||||||
),
|
),
|
||||||
) {
|
) {
|
||||||
{
|
{
|
||||||
_uploadService.taskStatusStream.listen(_handleTaskStatusUpdate);
|
_statusSubscription = _uploadService.taskStatusStream.listen(_handleTaskStatusUpdate);
|
||||||
_uploadService.taskProgressStream.listen(_handleTaskProgressUpdate);
|
_progressSubscription = _uploadService.taskProgressStream.listen(_handleTaskProgressUpdate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -224,6 +224,10 @@ class DriftBackupNotifier extends StateNotifier<DriftBackupState> {
|
||||||
|
|
||||||
/// Remove upload item from state
|
/// Remove upload item from state
|
||||||
void _removeUploadItem(String taskId) {
|
void _removeUploadItem(String taskId) {
|
||||||
|
if (!mounted) {
|
||||||
|
_logger.warning("Skip _removeUploadItem: notifier disposed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (state.uploadItems.containsKey(taskId)) {
|
if (state.uploadItems.containsKey(taskId)) {
|
||||||
final updatedItems = Map<String, DriftUploadStatus>.from(state.uploadItems);
|
final updatedItems = Map<String, DriftUploadStatus>.from(state.uploadItems);
|
||||||
updatedItems.remove(taskId);
|
updatedItems.remove(taskId);
|
||||||
|
|
@ -232,6 +236,10 @@ class DriftBackupNotifier extends StateNotifier<DriftBackupState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void _handleTaskStatusUpdate(TaskStatusUpdate update) {
|
void _handleTaskStatusUpdate(TaskStatusUpdate update) {
|
||||||
|
if (!mounted) {
|
||||||
|
_logger.warning("Skip _handleTaskStatusUpdate: notifier disposed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
final taskId = update.task.taskId;
|
final taskId = update.task.taskId;
|
||||||
|
|
||||||
switch (update.status) {
|
switch (update.status) {
|
||||||
|
|
@ -291,6 +299,10 @@ class DriftBackupNotifier extends StateNotifier<DriftBackupState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void _handleTaskProgressUpdate(TaskProgressUpdate update) {
|
void _handleTaskProgressUpdate(TaskProgressUpdate update) {
|
||||||
|
if (!mounted) {
|
||||||
|
_logger.warning("Skip _handleTaskProgressUpdate: notifier disposed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
final taskId = update.task.taskId;
|
final taskId = update.task.taskId;
|
||||||
final filename = update.task.displayName;
|
final filename = update.task.displayName;
|
||||||
final progress = update.progress;
|
final progress = update.progress;
|
||||||
|
|
@ -332,7 +344,15 @@ class DriftBackupNotifier extends StateNotifier<DriftBackupState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> getBackupStatus(String userId) async {
|
Future<void> getBackupStatus(String userId) async {
|
||||||
|
if (!mounted) {
|
||||||
|
_logger.warning("Skip getBackupStatus (pre-call): notifier disposed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
final counts = await _uploadService.getBackupCounts(userId);
|
final counts = await _uploadService.getBackupCounts(userId);
|
||||||
|
if (!mounted) {
|
||||||
|
_logger.warning("Skip getBackupStatus (post-call): notifier disposed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
state = state.copyWith(
|
state = state.copyWith(
|
||||||
totalCount: counts.total,
|
totalCount: counts.total,
|
||||||
|
|
@ -343,6 +363,10 @@ class DriftBackupNotifier extends StateNotifier<DriftBackupState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateError(BackupError error) async {
|
void updateError(BackupError error) async {
|
||||||
|
if (!mounted) {
|
||||||
|
_logger.warning("Skip updateError: notifier disposed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
state = state.copyWith(error: error);
|
state = state.copyWith(error: error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -360,10 +384,18 @@ class DriftBackupNotifier extends StateNotifier<DriftBackupState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> cancel() async {
|
Future<void> cancel() async {
|
||||||
|
if (!mounted) {
|
||||||
|
_logger.warning("Skip cancel (pre-call): notifier disposed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
dPrint(() => "Canceling backup tasks...");
|
dPrint(() => "Canceling backup tasks...");
|
||||||
state = state.copyWith(enqueueCount: 0, enqueueTotalCount: 0, isCanceling: true, error: BackupError.none);
|
state = state.copyWith(enqueueCount: 0, enqueueTotalCount: 0, isCanceling: true, error: BackupError.none);
|
||||||
|
|
||||||
final activeTaskCount = await _uploadService.cancelBackup();
|
final activeTaskCount = await _uploadService.cancelBackup();
|
||||||
|
if (!mounted) {
|
||||||
|
_logger.warning("Skip cancel (post-call): notifier disposed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (activeTaskCount > 0) {
|
if (activeTaskCount > 0) {
|
||||||
dPrint(() => "$activeTaskCount tasks left, continuing to cancel...");
|
dPrint(() => "$activeTaskCount tasks left, continuing to cancel...");
|
||||||
|
|
@ -376,9 +408,17 @@ class DriftBackupNotifier extends StateNotifier<DriftBackupState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> handleBackupResume(String userId) async {
|
Future<void> handleBackupResume(String userId) async {
|
||||||
|
if (!mounted) {
|
||||||
|
_logger.warning("Skip handleBackupResume (pre-call): notifier disposed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
_logger.info("Resuming backup tasks...");
|
_logger.info("Resuming backup tasks...");
|
||||||
state = state.copyWith(error: BackupError.none);
|
state = state.copyWith(error: BackupError.none);
|
||||||
final tasks = await _uploadService.getActiveTasks(kBackupGroup);
|
final tasks = await _uploadService.getActiveTasks(kBackupGroup);
|
||||||
|
if (!mounted) {
|
||||||
|
_logger.warning("Skip handleBackupResume (post-call): notifier disposed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
_logger.info("Found ${tasks.length} tasks");
|
_logger.info("Found ${tasks.length} tasks");
|
||||||
|
|
||||||
if (tasks.isEmpty) {
|
if (tasks.isEmpty) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue