mirror of
https://github.com/immich-app/immich
synced 2025-11-07 17:27:20 +00:00
use mutex
This commit is contained in:
parent
2f5d75ce21
commit
f8ab533acb
2 changed files with 91 additions and 33 deletions
|
|
@ -9,8 +9,57 @@ class BackgroundSyncManager {
|
|||
Cancelable<void>? _deviceAlbumSyncTask;
|
||||
Cancelable<void>? _hashTask;
|
||||
|
||||
Completer<void>? _localSyncMutex;
|
||||
Completer<void>? _remoteSyncMutex;
|
||||
Completer<void>? _hashMutex;
|
||||
|
||||
BackgroundSyncManager();
|
||||
|
||||
Future<T> _withMutex<T>(
|
||||
Completer<void>? Function() getMutex,
|
||||
void Function(Completer<void>?) setMutex,
|
||||
Future<T> Function() operation,
|
||||
) async {
|
||||
while (getMutex() != null) {
|
||||
await getMutex()!.future;
|
||||
}
|
||||
|
||||
final mutex = Completer<void>();
|
||||
setMutex(mutex);
|
||||
|
||||
try {
|
||||
final result = await operation();
|
||||
return result;
|
||||
} finally {
|
||||
setMutex(null);
|
||||
mutex.complete();
|
||||
}
|
||||
}
|
||||
|
||||
Future<T> _withLocalSyncMutex<T>(Future<T> Function() operation) {
|
||||
return _withMutex(
|
||||
() => _localSyncMutex,
|
||||
(mutex) => _localSyncMutex = mutex,
|
||||
operation,
|
||||
);
|
||||
}
|
||||
|
||||
Future<T> _withRemoteSyncMutex<T>(Future<T> Function() operation) {
|
||||
return _withMutex(
|
||||
() => _remoteSyncMutex,
|
||||
(mutex) => _remoteSyncMutex = mutex,
|
||||
operation,
|
||||
);
|
||||
}
|
||||
|
||||
Future<T> _withHashMutex<T>(Future<T> Function() operation) {
|
||||
return _withMutex(
|
||||
() => _hashMutex,
|
||||
(mutex) => _hashMutex = mutex,
|
||||
operation,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> cancel() {
|
||||
final futures = <Future>[];
|
||||
|
||||
|
|
@ -25,51 +74,57 @@ class BackgroundSyncManager {
|
|||
|
||||
// No need to cancel the task, as it can also be run when the user logs out
|
||||
Future<void> syncLocal({bool full = false}) {
|
||||
if (_deviceAlbumSyncTask != null) {
|
||||
return _deviceAlbumSyncTask!.future;
|
||||
}
|
||||
return _withLocalSyncMutex(() async {
|
||||
if (_deviceAlbumSyncTask != null) {
|
||||
return _deviceAlbumSyncTask!.future;
|
||||
}
|
||||
|
||||
// We use a ternary operator to avoid [_deviceAlbumSyncTask] from being
|
||||
// captured by the closure passed to [runInIsolateGentle].
|
||||
_deviceAlbumSyncTask = full
|
||||
? runInIsolateGentle(
|
||||
computation: (ref) =>
|
||||
ref.read(localSyncServiceProvider).sync(full: true),
|
||||
)
|
||||
: runInIsolateGentle(
|
||||
computation: (ref) =>
|
||||
ref.read(localSyncServiceProvider).sync(full: false),
|
||||
);
|
||||
// We use a ternary operator to avoid [_deviceAlbumSyncTask] from being
|
||||
// captured by the closure passed to [runInIsolateGentle].
|
||||
_deviceAlbumSyncTask = full
|
||||
? runInIsolateGentle(
|
||||
computation: (ref) =>
|
||||
ref.read(localSyncServiceProvider).sync(full: true),
|
||||
)
|
||||
: runInIsolateGentle(
|
||||
computation: (ref) =>
|
||||
ref.read(localSyncServiceProvider).sync(full: false),
|
||||
);
|
||||
|
||||
return _deviceAlbumSyncTask!.whenComplete(() {
|
||||
_deviceAlbumSyncTask = null;
|
||||
return _deviceAlbumSyncTask!.whenComplete(() {
|
||||
_deviceAlbumSyncTask = null;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// No need to cancel the task, as it can also be run when the user logs out
|
||||
Future<void> hashAssets() {
|
||||
if (_hashTask != null) {
|
||||
return _hashTask!.future;
|
||||
}
|
||||
return _withHashMutex(() async {
|
||||
if (_hashTask != null) {
|
||||
return _hashTask!.future;
|
||||
}
|
||||
|
||||
_hashTask = runInIsolateGentle(
|
||||
computation: (ref) => ref.read(hashServiceProvider).hashAssets(),
|
||||
);
|
||||
return _hashTask!.whenComplete(() {
|
||||
_hashTask = null;
|
||||
_hashTask = runInIsolateGentle(
|
||||
computation: (ref) => ref.read(hashServiceProvider).hashAssets(),
|
||||
);
|
||||
return _hashTask!.whenComplete(() {
|
||||
_hashTask = null;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> syncRemote() {
|
||||
if (_syncTask != null) {
|
||||
return _syncTask!.future;
|
||||
}
|
||||
return _withRemoteSyncMutex(() async {
|
||||
if (_syncTask != null) {
|
||||
return _syncTask!.future;
|
||||
}
|
||||
|
||||
_syncTask = runInIsolateGentle(
|
||||
computation: (ref) => ref.read(syncStreamServiceProvider).sync(),
|
||||
);
|
||||
return _syncTask!.whenComplete(() {
|
||||
_syncTask = null;
|
||||
_syncTask = runInIsolateGentle(
|
||||
computation: (ref) => ref.read(syncStreamServiceProvider).sync(),
|
||||
);
|
||||
return _syncTask!.whenComplete(() {
|
||||
_syncTask = null;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue