mirror of
https://github.com/immich-app/immich.git
synced 2025-09-29 15:31:13 -04:00
fix: do not listen for store updates in isolates (#21947)
* dispose store on isolate cleanup * do not listen for store updates in isolates --------- Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com> Co-authored-by: Alex <alex.tran1502@gmail.com>
This commit is contained in:
parent
2dcb32f7d0
commit
b26b452530
@ -7,6 +7,8 @@ import 'package:cancellation_token_http/http.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:immich_mobile/constants/constants.dart';
|
import 'package:immich_mobile/constants/constants.dart';
|
||||||
|
import 'package:immich_mobile/domain/services/log.service.dart';
|
||||||
|
import 'package:immich_mobile/entities/store.entity.dart';
|
||||||
import 'package:immich_mobile/extensions/network_capability_extensions.dart';
|
import 'package:immich_mobile/extensions/network_capability_extensions.dart';
|
||||||
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
||||||
import 'package:immich_mobile/generated/intl_keys.g.dart';
|
import 'package:immich_mobile/generated/intl_keys.g.dart';
|
||||||
@ -27,11 +29,11 @@ import 'package:immich_mobile/services/localization.service.dart';
|
|||||||
import 'package:immich_mobile/services/server_info.service.dart';
|
import 'package:immich_mobile/services/server_info.service.dart';
|
||||||
import 'package:immich_mobile/services/upload.service.dart';
|
import 'package:immich_mobile/services/upload.service.dart';
|
||||||
import 'package:immich_mobile/utils/bootstrap.dart';
|
import 'package:immich_mobile/utils/bootstrap.dart';
|
||||||
|
import 'package:immich_mobile/utils/debug_print.dart';
|
||||||
import 'package:immich_mobile/utils/http_ssl_options.dart';
|
import 'package:immich_mobile/utils/http_ssl_options.dart';
|
||||||
import 'package:isar/isar.dart';
|
import 'package:isar/isar.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:worker_manager/worker_manager.dart';
|
import 'package:worker_manager/worker_manager.dart';
|
||||||
import 'package:immich_mobile/utils/debug_print.dart';
|
|
||||||
|
|
||||||
class BackgroundWorkerFgService {
|
class BackgroundWorkerFgService {
|
||||||
final BackgroundWorkerFgHostApi _foregroundHostApi;
|
final BackgroundWorkerFgHostApi _foregroundHostApi;
|
||||||
@ -181,6 +183,8 @@ class BackgroundWorkerBgService extends BackgroundWorkerFlutterApi {
|
|||||||
// Discard any errors on the dispose call
|
// Discard any errors on the dispose call
|
||||||
return;
|
return;
|
||||||
}),
|
}),
|
||||||
|
LogService.I.dispose(),
|
||||||
|
Store.dispose(),
|
||||||
_drift.close(),
|
_drift.close(),
|
||||||
_driftLogger.close(),
|
_driftLogger.close(),
|
||||||
backgroundSyncManager.cancel(),
|
backgroundSyncManager.cancel(),
|
||||||
@ -269,6 +273,6 @@ Future<void> backgroundSyncNativeEntrypoint() async {
|
|||||||
DartPluginRegistrant.ensureInitialized();
|
DartPluginRegistrant.ensureInitialized();
|
||||||
|
|
||||||
final (isar, drift, logDB) = await Bootstrap.initDB();
|
final (isar, drift, logDB) = await Bootstrap.initDB();
|
||||||
await Bootstrap.initDomain(isar, drift, logDB, shouldBufferLogs: false);
|
await Bootstrap.initDomain(isar, drift, logDB, shouldBufferLogs: false, listenStoreUpdates: false);
|
||||||
await BackgroundWorkerBgService(isar: isar, drift: drift, driftLogger: logDB).init();
|
await BackgroundWorkerBgService(isar: isar, drift: drift, driftLogger: logDB).init();
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ class StoreService {
|
|||||||
|
|
||||||
/// In-memory cache. Keys are [StoreKey.id]
|
/// In-memory cache. Keys are [StoreKey.id]
|
||||||
final Map<int, Object?> _cache = {};
|
final Map<int, Object?> _cache = {};
|
||||||
late final StreamSubscription<List<StoreDto>> _storeUpdateSubscription;
|
StreamSubscription<List<StoreDto>>? _storeUpdateSubscription;
|
||||||
|
|
||||||
StoreService._({required IStoreRepository isarStoreRepository}) : _storeRepository = isarStoreRepository;
|
StoreService._({required IStoreRepository isarStoreRepository}) : _storeRepository = isarStoreRepository;
|
||||||
|
|
||||||
@ -24,15 +24,17 @@ class StoreService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Replace the implementation with the one from create after removing the typedef
|
// TODO: Replace the implementation with the one from create after removing the typedef
|
||||||
static Future<StoreService> init({required IStoreRepository storeRepository}) async {
|
static Future<StoreService> init({required IStoreRepository storeRepository, bool listenUpdates = true}) async {
|
||||||
_instance ??= await create(storeRepository: storeRepository);
|
_instance ??= await create(storeRepository: storeRepository, listenUpdates: listenUpdates);
|
||||||
return _instance!;
|
return _instance!;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<StoreService> create({required IStoreRepository storeRepository}) async {
|
static Future<StoreService> create({required IStoreRepository storeRepository, bool listenUpdates = true}) async {
|
||||||
final instance = StoreService._(isarStoreRepository: storeRepository);
|
final instance = StoreService._(isarStoreRepository: storeRepository);
|
||||||
await instance.populateCache();
|
await instance.populateCache();
|
||||||
instance._storeUpdateSubscription = instance._listenForChange();
|
if (listenUpdates) {
|
||||||
|
instance._storeUpdateSubscription = instance._listenForChange();
|
||||||
|
}
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,8 +52,8 @@ class StoreService {
|
|||||||
});
|
});
|
||||||
|
|
||||||
/// Disposes the store and cancels the subscription. To reuse the store call init() again
|
/// Disposes the store and cancels the subscription. To reuse the store call init() again
|
||||||
void dispose() async {
|
Future<void> dispose() async {
|
||||||
await _storeUpdateSubscription.cancel();
|
await _storeUpdateSubscription?.cancel();
|
||||||
_cache.clear();
|
_cache.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,11 +28,11 @@ import 'package:immich_mobile/services/backup.service.dart';
|
|||||||
import 'package:immich_mobile/services/localization.service.dart';
|
import 'package:immich_mobile/services/localization.service.dart';
|
||||||
import 'package:immich_mobile/utils/backup_progress.dart';
|
import 'package:immich_mobile/utils/backup_progress.dart';
|
||||||
import 'package:immich_mobile/utils/bootstrap.dart';
|
import 'package:immich_mobile/utils/bootstrap.dart';
|
||||||
|
import 'package:immich_mobile/utils/debug_print.dart';
|
||||||
import 'package:immich_mobile/utils/diff.dart';
|
import 'package:immich_mobile/utils/diff.dart';
|
||||||
import 'package:immich_mobile/utils/http_ssl_options.dart';
|
import 'package:immich_mobile/utils/http_ssl_options.dart';
|
||||||
import 'package:path_provider_foundation/path_provider_foundation.dart';
|
import 'package:path_provider_foundation/path_provider_foundation.dart';
|
||||||
import 'package:photo_manager/photo_manager.dart' show PMProgressHandler;
|
import 'package:photo_manager/photo_manager.dart' show PMProgressHandler;
|
||||||
import 'package:immich_mobile/utils/debug_print.dart';
|
|
||||||
|
|
||||||
final backgroundServiceProvider = Provider((ref) => BackgroundService());
|
final backgroundServiceProvider = Provider((ref) => BackgroundService());
|
||||||
|
|
||||||
@ -331,7 +331,7 @@ class BackgroundService {
|
|||||||
|
|
||||||
Future<bool> _onAssetsChanged() async {
|
Future<bool> _onAssetsChanged() async {
|
||||||
final (isar, drift, logDb) = await Bootstrap.initDB();
|
final (isar, drift, logDb) = await Bootstrap.initDB();
|
||||||
await Bootstrap.initDomain(isar, drift, logDb);
|
await Bootstrap.initDomain(isar, drift, logDb, shouldBufferLogs: false, listenStoreUpdates: false);
|
||||||
|
|
||||||
final ref = ProviderContainer(
|
final ref = ProviderContainer(
|
||||||
overrides: [
|
overrides: [
|
||||||
|
@ -89,11 +89,17 @@ abstract final class Bootstrap {
|
|||||||
return (isar, drift, logDb);
|
return (isar, drift, logDb);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<void> initDomain(Isar db, Drift drift, DriftLogger logDb, {bool shouldBufferLogs = true}) async {
|
static Future<void> initDomain(
|
||||||
|
Isar db,
|
||||||
|
Drift drift,
|
||||||
|
DriftLogger logDb, {
|
||||||
|
bool listenStoreUpdates = true,
|
||||||
|
bool shouldBufferLogs = true,
|
||||||
|
}) async {
|
||||||
final isBeta = await IsarStoreRepository(db).tryGet(StoreKey.betaTimeline) ?? true;
|
final isBeta = await IsarStoreRepository(db).tryGet(StoreKey.betaTimeline) ?? true;
|
||||||
final IStoreRepository storeRepo = isBeta ? DriftStoreRepository(drift) : IsarStoreRepository(db);
|
final IStoreRepository storeRepo = isBeta ? DriftStoreRepository(drift) : IsarStoreRepository(db);
|
||||||
|
|
||||||
await StoreService.init(storeRepository: storeRepo);
|
await StoreService.init(storeRepository: storeRepo, listenUpdates: listenStoreUpdates);
|
||||||
|
|
||||||
await LogService.init(
|
await LogService.init(
|
||||||
logRepository: LogRepository(logDb),
|
logRepository: LogRepository(logDb),
|
||||||
|
@ -4,14 +4,15 @@ import 'dart:ui';
|
|||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:immich_mobile/domain/services/log.service.dart';
|
import 'package:immich_mobile/domain/services/log.service.dart';
|
||||||
|
import 'package:immich_mobile/entities/store.entity.dart';
|
||||||
import 'package:immich_mobile/providers/db.provider.dart';
|
import 'package:immich_mobile/providers/db.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/cancel.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/cancel.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/db.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/db.provider.dart';
|
||||||
import 'package:immich_mobile/utils/bootstrap.dart';
|
import 'package:immich_mobile/utils/bootstrap.dart';
|
||||||
|
import 'package:immich_mobile/utils/debug_print.dart';
|
||||||
import 'package:immich_mobile/utils/http_ssl_options.dart';
|
import 'package:immich_mobile/utils/http_ssl_options.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:worker_manager/worker_manager.dart';
|
import 'package:worker_manager/worker_manager.dart';
|
||||||
import 'package:immich_mobile/utils/debug_print.dart';
|
|
||||||
|
|
||||||
class InvalidIsolateUsageException implements Exception {
|
class InvalidIsolateUsageException implements Exception {
|
||||||
const InvalidIsolateUsageException();
|
const InvalidIsolateUsageException();
|
||||||
@ -37,7 +38,7 @@ Cancelable<T?> runInIsolateGentle<T>({
|
|||||||
DartPluginRegistrant.ensureInitialized();
|
DartPluginRegistrant.ensureInitialized();
|
||||||
|
|
||||||
final (isar, drift, logDb) = await Bootstrap.initDB();
|
final (isar, drift, logDb) = await Bootstrap.initDB();
|
||||||
await Bootstrap.initDomain(isar, drift, logDb, shouldBufferLogs: false);
|
await Bootstrap.initDomain(isar, drift, logDb, shouldBufferLogs: false, listenStoreUpdates: false);
|
||||||
final ref = ProviderContainer(
|
final ref = ProviderContainer(
|
||||||
overrides: [
|
overrides: [
|
||||||
// TODO: Remove once isar is removed
|
// TODO: Remove once isar is removed
|
||||||
@ -61,6 +62,7 @@ Cancelable<T?> runInIsolateGentle<T>({
|
|||||||
try {
|
try {
|
||||||
ref.dispose();
|
ref.dispose();
|
||||||
|
|
||||||
|
await Store.dispose();
|
||||||
await LogService.I.dispose();
|
await LogService.I.dispose();
|
||||||
await logDb.close();
|
await logDb.close();
|
||||||
await drift.close();
|
await drift.close();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user