diff --git a/CHANGELOG.md b/CHANGELOG.md index dbeeca50..988f7ddb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 7.12.2 + +Minor improvements to `TaskQueue` and `MemoryTaskQueue` + ## 7.12.1 Bug fix for web compilation diff --git a/README.md b/README.md index 8da33999..7023ffa7 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,8 @@ This version requires Dart 3. If you need support for Dart 2 please use version `^6.1.1`, which will be maintained until the end of 2023. +If you want a 'lite' version, without references to the `sqflite` package, use branch [V7-lite](https://github.com/781flyingdutchman/background_downloader/tree/V7-lite) of the repo. + --- **If you are migrating from Flutter Downloader, please read the [migration document](https://github.com/781flyingdutchman/background_downloader/blob/main/MIGRATION.md)** diff --git a/lib/src/base_downloader.dart b/lib/src/base_downloader.dart index 9049a733..1e0aec71 100644 --- a/lib/src/base_downloader.dart +++ b/lib/src/base_downloader.dart @@ -540,21 +540,39 @@ abstract base class BaseDownloader { setPausedTask(task); } if (update.status.isFinalState) { - for (var taskQueue in taskQueues) { - taskQueue.taskFinished(task); - } //TODO should this also run in states like .paused? removeModifiedTask(task); _clearPauseResumeInfo(task); } + if (update.status.isFinalState || update.status == TaskStatus.paused) { + notifyTaskQueues(task); + } _emitStatusUpdate(update); } } /// Process progress update coming from Downloader to client listener void processProgressUpdate(TaskProgressUpdate update) { + switch (update.progress) { + case progressComplete: + case progressFailed: + case progressNotFound: + case progressCanceled: + case progressPaused: + notifyTaskQueues(update.task); + + default: + // no-op + } _emitProgressUpdate(update); } + /// Notify all [taskQueues] that this task has finished + void notifyTaskQueues(Task task) { + for (var taskQueue in taskQueues) { + taskQueue.taskFinished(task); + } + } + /// Process user tapping on a notification /// /// Because a notification tap may cause the app to start from scratch, we diff --git a/lib/src/queue/task_queue.dart b/lib/src/queue/task_queue.dart index c1118d86..ae190a33 100644 --- a/lib/src/queue/task_queue.dart +++ b/lib/src/queue/task_queue.dart @@ -36,7 +36,8 @@ class MemoryTaskQueue implements TaskQueue { /// message loop when adding many tasks Duration minInterval = const Duration(milliseconds: 20); - final _enqueuedTasks = {}; // by TaskId + /// Set of tasks that have been enqueued with the FileDownloader + final enqueued = {}; // by TaskId var _readyForEnqueue = Completer(); @@ -62,6 +63,29 @@ class MemoryTaskQueue implements TaskQueue { /// with the [FileDownloader] void removeAll() => waiting.removeAll(); + /// remove all waiting tasks matching [taskIds]. Does not affect tasks already enqueued + /// with the [FileDownloader] + void removeTasksWithIds(List taskIds) { + for (final taskId in taskIds) { + final match = waiting.unorderedElements + .firstWhereOrNull((task) => task.taskId == taskId); + if (match != null) { + waiting.remove(match); + } + } + } + + /// remove all waiting tasks in [group]. Does not affect tasks already enqueued + /// with the [FileDownloader] + void removeTasksWithGroup(String group) { + final tasksToRemove = waiting.unorderedElements + .where((task) => task.group == group) + .toList(growable: false); + for (final task in tasksToRemove) { + waiting.remove(task); + } + } + /// Remove [task] from the queue. Does not affect tasks already enqueued /// with the [FileDownloader] void remove(Task task) => waiting.remove(task); @@ -69,9 +93,18 @@ class MemoryTaskQueue implements TaskQueue { /// Reset the state of the [TaskQueue]. /// /// Clears the [waiting] queue and resets active tasks to 0 - void reset() { - removeAll(); - _enqueuedTasks.clear(); + void reset({String? group}) { + if (group == null) { + removeAll(); + enqueued.clear(); + } else { + removeTasksWithGroup(group); + final tasksToRemove = + enqueued.where((task) => task.group != group).toList(growable: false); + for (final task in tasksToRemove) { + enqueued.remove(task); + } + } } /// Advance the queue if possible and ready, no-op if not @@ -86,7 +119,7 @@ class MemoryTaskQueue implements TaskQueue { return; } _readyForEnqueue = Completer(); - _enqueuedTasks.add(task); + enqueued.add(task); enqueue(task).then((success) async { if (!success) { _log.warning( @@ -129,25 +162,26 @@ class MemoryTaskQueue implements TaskQueue { Future enqueue(Task task) => FileDownloader().enqueue(task); /// Task has finished, so remove from active and advance the queue to the - /// next task + /// next task if the task was indeed managed by this queue @override void taskFinished(Task task) { - _enqueuedTasks.remove(task); - advanceQueue(); + if (enqueued.remove(task)) { + advanceQueue(); + } } /// Number of active tasks, i.e. enqueued with the FileDownloader and /// not yet finished - int get numActive => _enqueuedTasks.length; + int get numActive => enqueued.length; /// Returns number of tasks active with this host name - int numActiveWithHostname(String hostname) => _enqueuedTasks.fold( + int numActiveWithHostname(String hostname) => enqueued.fold( 0, (previousValue, task) => task.hostName == hostname ? previousValue + 1 : previousValue); /// Returns number of tasks active with this group - int numActiveWithGroup(String group) => _enqueuedTasks.fold( + int numActiveWithGroup(String group) => enqueued.fold( 0, (previousValue, task) => task.group == group ? previousValue + 1 : previousValue); @@ -158,6 +192,11 @@ class MemoryTaskQueue implements TaskQueue { /// Number of tasks waiting to be enqueued int get numWaiting => waiting.length; + /// Number of tasks waiting to be enqueued in [group] + int numWaitingWithGroup(String group) => waiting.unorderedElements + .where((element) => element.group == group) + .length; + /// Stream with [Task]s that failed to enqueue correctly Stream get enqueueErrors => _enqueueErrorsStreamController.stream; } diff --git a/pubspec.yaml b/pubspec.yaml index 98a8c462..62864178 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: background_downloader description: A multi-platform background file downloader and uploader. Define the task, enqueue and monitor progress -version: 7.12.1 +version: 7.12.2 repository: https://github.com/781flyingdutchman/background_downloader environment: