fix: resume interrupted downloads after force-kill

This commit is contained in:
edde746
2026-02-09 09:04:44 +01:00
parent 1fb32f1618
commit 839c274e0d
3 changed files with 32 additions and 1 deletions
+7 -1
View File
@@ -214,7 +214,7 @@ class _MainAppState extends State<MainApp> with WidgetsBindingObserver {
PlexApiCache.initialize(_appDatabase);
_downloadManager = DownloadManagerService(database: _appDatabase, storageService: DownloadStorageService.instance);
_downloadManager.recoverInterruptedDownloads();
_downloadManager.recoveryFuture = _downloadManager.recoverInterruptedDownloads();
_offlineWatchSyncService = OfflineWatchSyncService(database: _appDatabase, serverManager: _serverManager);
@@ -398,6 +398,12 @@ class _SetupScreenState extends State<SetupScreen> {
if (!mounted) return;
if (result.hasConnections) {
// Resume any downloads that were interrupted by app kill
final downloadProvider = context.read<DownloadProvider>();
downloadProvider.ensureInitialized().then((_) {
downloadProvider.resumeQueuedDownloads(result.firstClient!);
});
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => MainScreen(client: result.firstClient!)),
+10
View File
@@ -71,6 +71,10 @@ class DownloadProvider extends ChangeNotifier {
/// Load all persisted downloads and metadata from the database/cache
Future<void> _loadPersistedDownloads() async {
try {
// Wait for recovery to finish before loading state so that
// interrupted "downloading" rows have been transitioned to "queued"
await _downloadManager.recoveryFuture;
// Clear existing data to prevent stale entries after deletions
_downloads.clear();
_artworkPaths.clear();
@@ -987,6 +991,12 @@ class DownloadProvider extends ChangeNotifier {
await _loadPersistedDownloads();
}
/// Resume queued downloads that were interrupted by app kill.
/// Call after a PlexClient becomes available (e.g. after server connect on launch).
void resumeQueuedDownloads(PlexClient client) {
_downloadManager.resumeQueuedDownloads(client);
}
/// Refresh only metadata from API cache (after watch state sync).
///
/// This is more lightweight than full refresh() - only updates metadata
@@ -244,6 +244,10 @@ class DownloadManagerService {
!connectivity.contains(ConnectivityResult.ethernet);
}
/// Future that completes when interrupted download recovery finishes.
/// Await this before reading download state from the DB to avoid races.
late final Future<void> recoveryFuture;
DownloadManagerService({required AppDatabase database, required DownloadStorageService storageService, Dio? dio})
: _database = database,
_storageService = storageService,
@@ -271,6 +275,17 @@ class DownloadManagerService {
}
}
/// Resume queued downloads that have no active processing.
/// Call after a PlexClient becomes available (e.g. after server connect on launch).
void resumeQueuedDownloads(PlexClient client) {
_database.getNextQueueItem().then((item) {
if (item != null && !_isProcessingQueue) {
appLogger.i('Resuming queued downloads after app restart');
_processQueue(client);
}
});
}
/// Delete a file if it exists and log the deletion
/// Returns true if file was deleted, false otherwise
Future<bool> _deleteFileIfExists(File file, String description) async {