Verify preview admission bounds under contention and worker unwind
This commit is contained in:
1 parent
ec75a52cf7
commit
c8e611081f
2 files changed
+55
-2
No files matched your search
@@ -413,6 +413,51 @@ pub fn error_response(status: StatusCode) -> Response<Vec<u8>> {
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn concurrent_admission_stays_bounded_and_unwind_releases_capacity() {
|
||||
let registry = Arc::new(PreviewRegistry::default());
|
||||
let active = Arc::new(AtomicUsize::new(0));
|
||||
let barrier = Arc::new(std::sync::Barrier::new(8));
|
||||
let workers: Vec<_> = (0..8)
|
||||
.map(|_| {
|
||||
let registry = registry.clone();
|
||||
let active = active.clone();
|
||||
let barrier = barrier.clone();
|
||||
std::thread::spawn(move || {
|
||||
barrier.wait();
|
||||
for _ in 0..500 {
|
||||
if let Some(admission) = registry.admit() {
|
||||
let count = active.fetch_add(1, Ordering::SeqCst) + 1;
|
||||
assert!(count <= MAX_REQUESTS);
|
||||
std::thread::yield_now();
|
||||
active.fetch_sub(1, Ordering::SeqCst);
|
||||
drop(admission);
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
for worker in workers {
|
||||
worker.join().unwrap();
|
||||
}
|
||||
assert_eq!(active.load(Ordering::SeqCst), 0);
|
||||
assert_eq!(registry.requests.load(Ordering::SeqCst), 0);
|
||||
let first = registry.admit().unwrap();
|
||||
let interrupted = registry.clone();
|
||||
assert!(std::panic::catch_unwind(move || {
|
||||
let _second = interrupted.admit().unwrap();
|
||||
panic!("injected preview worker panic");
|
||||
})
|
||||
.is_err());
|
||||
let second = registry
|
||||
.admit()
|
||||
.expect("Unwinding must release the second slot");
|
||||
assert!(registry.admit().is_none());
|
||||
drop(first);
|
||||
drop(second);
|
||||
assert_eq!(registry.requests.load(Ordering::SeqCst), 0);
|
||||
}
|
||||
|
||||
struct Fixture {
|
||||
_directory: tempfile::TempDir,
|
||||
database: PathBuf,
|
||||
|
||||
Reference in new issue
Block a user