Fix the sidebar entry, a test race, and comments left pointing at deleted members

The docs page was linked from docs/index.md but missing from the VitePress sidebar, where every sibling feature page is listed.

In the dispatch test fake, Started.Enqueue ran before the counter incremented, so WaitForStarted could return in the gap and the HighWaterMark assertion could observe one book fewer than had started.

Comments still named TrackedQueue.Current and .Active after both were deleted, the Configuration doc comment still called itself the bound on a spinner when nothing binds it any more, and the ClaimAbort comment said the winner was the book that answered the dialog when it is really whichever book gets there first.
This commit is contained in:
Allamagoosa committed 2026-08-21 06:33:31 -07:00
1 parent 1f38ba8abf
commit 29a9cb3873
5 files changed
+26 -15

No files matched your search

@@ -152,8 +152,8 @@ public class ProcessQueueViewModel : ReactiveObject
: 0;
config.DownloadSpeedLimit = (long)(_speedLimit * 1024 * 1024);
// Apply to all currently active books. Over a copy: the speed limit is changed from the UI
// thread while book tasks start and finish, and Active is the live list.
// Apply to all currently active books. Over a copy, because the speed limit is changed from
// the UI thread while book tasks start and finish, which mutates the queue's active list.
foreach (var activeBook in Queue.GetActive().OfType<ProcessBookViewModel>())
activeBook.Configuration.DownloadSpeedLimit = config.DownloadSpeedLimit;
@@ -717,10 +717,12 @@ public class ProcessQueueViewModel : ReactiveObject
var result = await ProcessBookHandler(book);
// Claimed before the queue is touched, and before the logging. Only the book that
// actually answered Abort tears the queue down: Abort is a session-wide override now, so
// every book in flight arrives here - directly or by inheriting that answer - and each one
// re-entering CancelAllAsync would have every book asking every other book to cancel.
// Claimed before the queue is touched, and before the logging. Exactly one book tears the
// queue down: Abort is a session-wide override now, so every book in flight arrives here -
// directly or by inheriting that answer - and each one re-entering CancelAllAsync would
// have every book asking every other book to cancel. The winner is whichever book reaches
// this line first, not necessarily the one whose dialog was answered; they are
// interchangeable here, and racing to identify the answering book would buy nothing.
// Claiming this early also keeps the window small in which the loop can start another
// book, which would then outlive the abort by starting after CancelAllAsync snapshots
// what to cancel.
@@ -744,8 +746,8 @@ public class ProcessQueueViewModel : ReactiveObject
await CancelAllAsync(book);
else
{
// Inherited the abort rather than answering it. It was cancelled by the book
// that did, and that is what it should report.
// Inherited the abort rather than triggering the teardown. It was cancelled by
// the book that did, and that is what it should report.
book.Result = ProcessBookResult.Cancelled;
book.Status = ProcessBookStatus.Cancelled;
}