Compare commits

...

2 Commits

Author SHA1 Message Date
shenlong-tanwen
172180d03f use custom drift with isolate fixes 2025-11-13 22:35:04 +05:30
Alex
82b7b8a0b1 fix: iOS soft freeze 2025-11-12 15:15:52 -06:00
5 changed files with 52 additions and 27 deletions

View File

@@ -133,9 +133,9 @@ class BackgroundWorker: BackgroundWorkerBgHostApi {
self.complete(success: false) self.complete(success: false)
} }
// Fallback safety mechanism: ensure completion is called within 2 seconds // Fallback safety mechanism: ensure completion is called within 5 seconds
// This prevents the background task from hanging indefinitely if Flutter doesn't respond // This prevents the background task from hanging indefinitely if Flutter doesn't respond
Timer.scheduledTimer(withTimeInterval: 2, repeats: false) { _ in Timer.scheduledTimer(withTimeInterval: 5, repeats: false) { _ in
self.complete(success: false) self.complete(success: false)
} }
} }

View File

@@ -110,8 +110,8 @@ class BackgroundWorkerApiImpl: BackgroundWorkerFgHostApi {
} }
isSuccess = false isSuccess = false
// Schedule a timer to signal the semaphore after 2 seconds // Schedule a timer to signal the semaphore after 5 seconds
Timer.scheduledTimer(withTimeInterval: 2, repeats: false) { _ in Timer.scheduledTimer(withTimeInterval: 5, repeats: false) { _ in
semaphore.signal() semaphore.signal()
} }
} }

View File

@@ -61,8 +61,11 @@ class BackgroundWorkerFgService {
class BackgroundWorkerBgService extends BackgroundWorkerFlutterApi { class BackgroundWorkerBgService extends BackgroundWorkerFlutterApi {
ProviderContainer? _ref; ProviderContainer? _ref;
// ignore: unused_field
final Isar _isar; final Isar _isar;
// ignore: unused_field
final Drift _drift; final Drift _drift;
// ignore: unused_field
final DriftLogger _driftLogger; final DriftLogger _driftLogger;
final BackgroundWorkerBgHostApi _backgroundHostApi; final BackgroundWorkerBgHostApi _backgroundHostApi;
final CancellationToken _cancellationToken = CancellationToken(); final CancellationToken _cancellationToken = CancellationToken();
@@ -79,7 +82,14 @@ class BackgroundWorkerBgService extends BackgroundWorkerFlutterApi {
overrides: [ overrides: [
dbProvider.overrideWithValue(isar), dbProvider.overrideWithValue(isar),
isarProvider.overrideWithValue(isar), isarProvider.overrideWithValue(isar),
driftProvider.overrideWith(driftOverride(drift)), // IMPORTANT: Do NOT use driftOverride here because it registers an onDispose
// callback that closes the database. Since the databases use shareAcrossIsolates: true,
// closing them from the background isolate will hang indefinitely.
// Instead, provide the drift instance directly without the dispose callback.
driftProvider.overrideWith((ref) {
ref.keepAlive();
return drift;
}),
], ],
); );
BackgroundWorkerFlutterApi.setUp(this); BackgroundWorkerFlutterApi.setUp(this);
@@ -184,31 +194,38 @@ class BackgroundWorkerBgService extends BackgroundWorkerFlutterApi {
try { try {
_isCleanedUp = true; _isCleanedUp = true;
_logger.info("Cleaning up background worker");
final backgroundSyncManager = _ref?.read(backgroundSyncProvider); final backgroundSyncManager = _ref?.read(backgroundSyncProvider);
final nativeSyncApi = _ref?.read(nativeSyncApiProvider); final nativeSyncApi = _ref?.read(nativeSyncApiProvider);
_cancellationToken.cancel();
await backgroundSyncManager?.cancel();
await nativeSyncApi?.cancelHashing();
// Dispose ref to release all providers
// Note: We use a custom drift provider override (see constructor) that does NOT
// close the database on dispose, so this is safe and won't hang
_ref?.dispose(); _ref?.dispose();
_ref = null; _ref = null;
_cancellationToken.cancel(); try {
_logger.info("Cleaning up background worker"); await workerManagerPatch.dispose();
final cleanupFutures = [ } catch (_) {}
nativeSyncApi?.cancelHashing(),
workerManagerPatch.dispose().catchError((_) async {
// Discard any errors on the dispose call
return;
}),
LogService.I.dispose(),
Store.dispose(),
_drift.close(),
_driftLogger.close(),
backgroundSyncManager?.cancel(),
];
if (_isar.isOpen) { try {
cleanupFutures.add(_isar.close()); await LogService.I.dispose();
} catch (error) {
_logger.warning("Failed to dispose LogService: $error");
} }
await Future.wait(cleanupFutures.nonNulls);
_logger.info("Background worker resources cleaned up"); try {
await Store.dispose();
} catch (error) {
_logger.warning("Failed to dispose Store: $error");
}
_logger.info("Background worker resources cleaned up successfully");
} catch (error, stack) { } catch (error, stack) {
dPrint(() => 'Failed to cleanup background worker: $error with stack: $stack'); dPrint(() => 'Failed to cleanup background worker: $error with stack: $stack');
} }

View File

@@ -452,10 +452,11 @@ packages:
drift: drift:
dependency: "direct main" dependency: "direct main"
description: description:
name: drift path: drift
sha256: "14a61af39d4584faf1d73b5b35e4b758a43008cf4c0fdb0576ec8e7032c0d9a5" ref: e7c909f0483b84510a9a60da8b020adc82ff16a3
url: "https://pub.dev" resolved-ref: e7c909f0483b84510a9a60da8b020adc82ff16a3
source: hosted url: "https://github.com/shenlong-tanwen/drift"
source: git
version: "2.26.0" version: "2.26.0"
drift_dev: drift_dev:
dependency: "direct dev" dependency: "direct dev"

View File

@@ -113,6 +113,13 @@ dev_dependencies:
riverpod_generator: ^2.6.1 riverpod_generator: ^2.6.1
riverpod_lint: ^2.6.1 riverpod_lint: ^2.6.1
dependency_overrides:
drift:
git:
url: https://github.com/shenlong-tanwen/drift
ref: 'e7c909f0483b84510a9a60da8b020adc82ff16a3'
path: drift/
flutter: flutter:
uses-material-design: true uses-material-design: true
assets: assets: