Harden concurrency and resource lifecycle (#101)
Some checks failed
Native code generation / deterministic (push) Failing after 2m4s
Concurrency and resource soak audit / soak (push) Failing after 6m31s
Imaging and meshing gate / native (push) Failing after 2m52s
JPEG 2000 feature / linux (push) Successful in 2m45s
Release platform and feature matrix / audit (push) Successful in 35s
Native Rust workspace compile / compile (push) Failing after 54s
Release platform and feature matrix / matrix (false, linux-stable-minimal, x86_64-unknown-linux-gnu, stable) (push) Has been cancelled
Release platform and feature matrix / matrix (false, macos-stable-portable, x86_64-apple-darwin, stable) (push) Has been cancelled
Release platform and feature matrix / matrix (false, windows-stable-portable, x86_64-pc-windows-gnu, stable) (push) Has been cancelled
Release platform and feature matrix / matrix (true, linux-msrv-portable, x86_64-unknown-linux-gnu, 1.96.0) (push) Has been cancelled
Release platform and feature matrix / matrix (true, linux-stable-default, x86_64-unknown-linux-gnu, stable) (push) Has been cancelled
Release platform and feature matrix / matrix (true, linux-stable-features, x86_64-unknown-linux-gnu, stable) (push) Has been cancelled
Release platform and feature matrix / matrix (true, linux-stable-release-surface, x86_64-unknown-linux-gnu, stable) (push) Has been cancelled
Dependency and supply-chain audit / audit (push) Has been cancelled
Skia feature / linux (push) Has been cancelled
Some checks failed
Native code generation / deterministic (push) Failing after 2m4s
Concurrency and resource soak audit / soak (push) Failing after 6m31s
Imaging and meshing gate / native (push) Failing after 2m52s
JPEG 2000 feature / linux (push) Successful in 2m45s
Release platform and feature matrix / audit (push) Successful in 35s
Native Rust workspace compile / compile (push) Failing after 54s
Release platform and feature matrix / matrix (false, linux-stable-minimal, x86_64-unknown-linux-gnu, stable) (push) Has been cancelled
Release platform and feature matrix / matrix (false, macos-stable-portable, x86_64-apple-darwin, stable) (push) Has been cancelled
Release platform and feature matrix / matrix (false, windows-stable-portable, x86_64-pc-windows-gnu, stable) (push) Has been cancelled
Release platform and feature matrix / matrix (true, linux-msrv-portable, x86_64-unknown-linux-gnu, 1.96.0) (push) Has been cancelled
Release platform and feature matrix / matrix (true, linux-stable-default, x86_64-unknown-linux-gnu, stable) (push) Has been cancelled
Release platform and feature matrix / matrix (true, linux-stable-features, x86_64-unknown-linux-gnu, stable) (push) Has been cancelled
Release platform and feature matrix / matrix (true, linux-stable-release-surface, x86_64-unknown-linux-gnu, stable) (push) Has been cancelled
Dependency and supply-chain audit / audit (push) Has been cancelled
Skia feature / linux (push) Has been cancelled
This commit is contained in:
@@ -723,6 +723,67 @@ async fn downloads_honor_parallel_limit_progress_and_external_completion_source(
|
||||
downloads.dispose().expect("dispose");
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn download_queue_applies_backpressure_and_cancellation_drains_every_job() {
|
||||
let active = Arc::new(AtomicUsize::new(0));
|
||||
let handler_active = Arc::clone(&active);
|
||||
let handler = HttpMessageHandler::new(move |_request, cancellation| {
|
||||
let active = Arc::clone(&handler_active);
|
||||
async move {
|
||||
active.fetch_add(1, Ordering::AcqRel);
|
||||
cancellation.cancelled().await;
|
||||
active.fetch_sub(1, Ordering::AcqRel);
|
||||
response(200, Vec::new())
|
||||
}
|
||||
});
|
||||
let mut client = GridClient::new().expect("client");
|
||||
client.set_http_caps_client(HttpCapsClient::new(handler).expect("HTTP client"));
|
||||
let mut downloads = DownloadManager::new(client).expect("downloads");
|
||||
downloads.set_parallel_downloads(1);
|
||||
downloads
|
||||
.queue_download_with_download_request(
|
||||
DownloadRequest::new(
|
||||
Uri("http://example.test/backpressure/initial".into()),
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.expect("request"),
|
||||
)
|
||||
.expect("initial request");
|
||||
tokio::time::timeout(Duration::from_secs(2), async {
|
||||
while active.load(Ordering::Acquire) == 0 {
|
||||
tokio::task::yield_now().await;
|
||||
}
|
||||
})
|
||||
.await
|
||||
.expect("initial request started");
|
||||
|
||||
let mut rejected = 0;
|
||||
for index in 0..300 {
|
||||
let result = downloads.queue_download_with_download_request(
|
||||
DownloadRequest::new(
|
||||
Uri(format!("http://example.test/backpressure/{index}")),
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.expect("request"),
|
||||
);
|
||||
match result {
|
||||
Ok(()) => {}
|
||||
Err(Error::InvalidOperation) => rejected += 1,
|
||||
Err(error) => panic!("unexpected queue error: {error:?}"),
|
||||
}
|
||||
}
|
||||
assert!(rejected > 0, "the bounded queue must reject excess work");
|
||||
assert!(downloads.active_download_count() <= 258);
|
||||
|
||||
downloads.dispose().expect("dispose");
|
||||
assert_eq!(active.load(Ordering::Acquire), 0);
|
||||
assert_eq!(downloads.active_download_count(), 0);
|
||||
assert!(!downloads.dispatcher_running());
|
||||
assert!(downloads.is_disposed());
|
||||
}
|
||||
|
||||
async fn read_http_request(stream: &mut tokio::net::TcpStream) -> Vec<u8> {
|
||||
let mut request = Vec::new();
|
||||
let mut scratch = [0_u8; 1024];
|
||||
|
||||
Reference in New Issue
Block a user