M3: a password prompt keeps a place in the open queue for its retry (#6731)

This commit is contained in:
BFlat authored and GitHub committed 2026-11-09 22:21:21 +07:00
1 parent 5aae0c3b82
commit ba28458ad8
2 files changed
+37 -3

No files matched your search

+10 -3
View File
@@ -142,12 +142,19 @@ impl PdfCraftApp {
Ok(token)
}
/// How many opens may wait for the worker: its bound, less one place while a password prompt
/// is open, so the prompt's retry fits even before the worker has taken any of the others.
#[cfg(not(target_arch = "wasm32"))]
fn open_slots(&self) -> usize {
open_worker::MAX_QUEUED_OPENS - usize::from(self.password_prompt.is_some())
}
/// Hand waiting files to the worker, oldest first, while its queue has room. Every queued
/// job has a `pending_opens` entry, so fewer entries than the bound means room.
/// job has a `pending_opens` entry, so fewer entries than [`Self::open_slots`] means room.
#[cfg(not(target_arch = "wasm32"))]
fn submit_deferred_opens(&mut self) {
let mut queue = std::mem::take(&mut self.deferred_opens);
while self.deferred_opens.is_empty() && self.pending_opens.len() < open_worker::MAX_QUEUED_OPENS {
while self.deferred_opens.is_empty() && self.pending_opens.len() < self.open_slots() {
let Some(next) = queue.pop_front() else { break };
self.open_path_request(&next.path, next.then, next.display_override);
}
@@ -866,7 +873,7 @@ impl PdfCraftApp {
self.startup_superseded = true;
// The worker queue is bounded. A long file list (a launch behind a password prompt,
// or many files at once) waits here, in order, and is submitted as opens finish.
if self.pending_opens.len() >= open_worker::MAX_QUEUED_OPENS || !self.deferred_opens.is_empty() {
if self.pending_opens.len() >= self.open_slots() || !self.deferred_opens.is_empty() {
self.deferred_opens.push_back(DeferredOpen { path: path.to_string(), then, display_override });
return OpenOutcome::Pending;
}
@@ -921,3 +921,30 @@ fn a_repeated_waiting_open_keeps_the_tool_it_brings() {
assert_eq!(app.open_path(&path), crate::OpenOutcome::Pending);
assert_eq!(app.deferred_opens.front().and_then(|d| d.then), Some("export.text"));
}
/// A password prompt keeps a place in the worker's bounded queue for its retry: files named after
/// the protected one fill the rest and wait in order, and the retry is queued, not refused as
/// "too many documents are waiting to open" while the worker has yet to take the others.
#[test]
#[allow(clippy::expect_used)]
fn a_password_prompt_keeps_a_place_in_the_open_queue_for_its_retry() {
let mut harness = tool_open_harness();
let held = HeldToolOpen::install(&mut harness);
let locked = tool_open_file("queue-locked", "pdf", &encrypted_tool_fixture());
harness.state_mut().open_path(&locked.0.to_string_lossy());
held.wait_started();
let others: Vec<ToolOpenFile> =
(0..open_worker::MAX_QUEUED_OPENS + 4).map(|i| tool_open_file(&format!("queue-{i}"), "pdf", &fixture(1))).collect();
for file in &others {
harness.state_mut().open_path(&file.0.to_string_lossy());
}
held.complete(&mut harness);
let app = harness.state();
assert!(app.password_prompt.is_some(), "the protected file asks for its password");
assert!(app.pending_opens.len() < open_worker::MAX_QUEUED_OPENS, "one place stays free: {} waiting", app.pending_opens.len());
assert!(!app.deferred_opens.is_empty(), "the rest wait their turn");
harness.state_mut().submit_password(Some("tool-password".into()));
let app = harness.state();
assert!(app.password_prompt.is_none(), "the retry is queued: {:?}", app.password_prompt.as_ref().and_then(|p| p.error.clone()));
assert!(app.password_retry.is_some());
}