fix: synchronize Feature shutdown capacity test on its storage fence
This commit is contained in:
@@ -890,6 +890,18 @@ async fn cancelled_feature_shutdown_keeps_sql_close_owned_without_blocking_contr
|
|||||||
released,
|
released,
|
||||||
};
|
};
|
||||||
observed(waiting).await.unwrap(); // actual SQL transaction owns the Feature connection
|
observed(waiting).await.unwrap(); // actual SQL transaction owns the Feature connection
|
||||||
|
// Force close to be queued before the sole DB worker can start it. Pending
|
||||||
|
// admission alone must not be mistaken for an available second queue slot.
|
||||||
|
let (started, running) = oneshot::channel();
|
||||||
|
let (start_close, held) = mpsc::channel();
|
||||||
|
fixture
|
||||||
|
.executor
|
||||||
|
.dispatch(move || {
|
||||||
|
let _ = started.send(());
|
||||||
|
let _ = held.recv_timeout(WATCHDOG);
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
observed(running).await.unwrap();
|
||||||
let leases = Arc::new(std::sync::atomic::AtomicUsize::new(0));
|
let leases = Arc::new(std::sync::atomic::AtomicUsize::new(0));
|
||||||
let mut close = Box::pin(crate::db_executor::with_operation_lifetime(
|
let mut close = Box::pin(crate::db_executor::with_operation_lifetime(
|
||||||
Arc::new(CountJobLifetime(leases.clone())),
|
Arc::new(CountJobLifetime(leases.clone())),
|
||||||
@@ -899,6 +911,30 @@ async fn cancelled_feature_shutdown_keeps_sql_close_owned_without_blocking_contr
|
|||||||
futures::poll!(&mut close).is_pending(),
|
futures::poll!(&mut close).is_pending(),
|
||||||
"Feature connection close must not wait on Tokio"
|
"Feature connection close must not wait on Tokio"
|
||||||
);
|
);
|
||||||
|
assert!(matches!(
|
||||||
|
fixture.executor.dispatch(|| {}),
|
||||||
|
Err(Error::DbCapacityExceeded)
|
||||||
|
));
|
||||||
|
start_close.send(()).unwrap();
|
||||||
|
let fenced = observed(async {
|
||||||
|
loop {
|
||||||
|
match fixture
|
||||||
|
.api
|
||||||
|
.feature_storage
|
||||||
|
.open(&fixture.api.subjektiv_registration)
|
||||||
|
{
|
||||||
|
Err(crate::FeatureStorageError::ShuttingDown) => break,
|
||||||
|
Ok(_) => tokio::task::yield_now().await,
|
||||||
|
Err(error) => panic!("unexpected Feature admission failure: {error}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
tokio::select! {
|
||||||
|
_ = fenced => {},
|
||||||
|
result = &mut close => panic!("close completed while its connection is held: {result:?}"),
|
||||||
|
}
|
||||||
|
// Observing the real shutdown fence proves close was dequeued and started;
|
||||||
|
// only now can the one waiting slot be filled deterministically.
|
||||||
runtime_progress_while_locked(&lock).await;
|
runtime_progress_while_locked(&lock).await;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
observed(fixture.host_executor.run(|| Ok::<_, Error>("control")))
|
observed(fixture.host_executor.run(|| Ok::<_, Error>("control")))
|
||||||
|
|||||||
Reference in New Issue
Block a user