Skip to content

Commit

Permalink
Minor improvements to TaskQueue and MemoryTaskQueue
Browse files Browse the repository at this point in the history
* `enqueued` set of tasks is now no longer private
* add `removeTasksWithIds`
* add `removeTasksWithGroup`
* add `numWaitingWithGroup`
* add optional `group` parameter to `reset`
* fixed `tasksFinished` bug (if task was not enqueued by TaskQueue)
* add reference to V7-lite to README.md

In BaseDownloader, improved logic for when to send `taskFinished` to task queues
  • Loading branch information
781flyingdutchman committed Oct 23, 2023
1 parent ce024d8 commit 27a694b
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 15 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 7.12.2

Minor improvements to `TaskQueue` and `MemoryTaskQueue`

## 7.12.1

Bug fix for web compilation
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)**
Expand Down
24 changes: 21 additions & 3 deletions lib/src/base_downloader.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
61 changes: 50 additions & 11 deletions lib/src/queue/task_queue.dart
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ class MemoryTaskQueue implements TaskQueue {
/// message loop when adding many tasks
Duration minInterval = const Duration(milliseconds: 20);

final _enqueuedTasks = <Task>{}; // by TaskId
/// Set of tasks that have been enqueued with the FileDownloader
final enqueued = <Task>{}; // by TaskId

var _readyForEnqueue = Completer();

Expand All @@ -62,16 +63,48 @@ 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<String> 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);

/// 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
Expand All @@ -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(
Expand Down Expand Up @@ -129,25 +162,26 @@ class MemoryTaskQueue implements TaskQueue {
Future<bool> 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);
Expand All @@ -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<Task> get enqueueErrors => _enqueueErrorsStreamController.stream;
}
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -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:
Expand Down

0 comments on commit 27a694b

Please sign in to comment.