fix concurrent reconfigure while TLS configuration is taking place

This commit is contained in:
Conrad Ludgate
2025-06-16 22:43:33 +01:00
committed by Conrad Ludgate
parent ffa9e595b8
commit e288cd2198

View File

@@ -27,32 +27,6 @@ pub(in crate::http) async fn configure(
Err(e) => return JsonResponse::error(StatusCode::BAD_REQUEST, e),
};
// XXX: wrap state update under lock in a code block. Otherwise, we will try
// to `Send` `mut state` into the spawned thread bellow, which will cause
// the following rustc error:
//
// error: future cannot be sent between threads safely
{
let mut state = compute.state.lock().unwrap();
if !matches!(state.status, ComputeStatus::Empty | ComputeStatus::Running) {
return JsonResponse::invalid_status(state.status);
}
// Pass the tracing span to the main thread that performs the startup,
// so that the start_compute operation is considered a child of this
// configure request for tracing purposes.
state.startup_span = Some(tracing::Span::current());
if compute.params.lakebase_mode {
ComputeNode::set_spec(&compute.params, &mut state, pspec);
} else {
state.pspec = Some(pspec);
}
state.set_status(ComputeStatus::ConfigurationPending, &compute.state_changed);
drop(state);
}
// Spawn a blocking thread to wait for compute to become Running. This is
// needed to not block the main pool of workers and to be able to serve
// other requests while some particular request is waiting for compute to
@@ -60,6 +34,24 @@ pub(in crate::http) async fn configure(
let c = compute.clone();
let completed = task::spawn_blocking(move || {
let mut state = c.state.lock().unwrap();
while !matches!(state.status, ComputeStatus::Empty | ComputeStatus::Running) {
// wait until we are not concurrently configuring
state = c.state_changed.wait(state).unwrap();
}
// Pass the tracing span to the main thread that performs the startup,
// so that the start_compute operation is considered a child of this
// configure request for tracing purposes.
state.startup_span = Some(tracing::Span::current());
if c.params.lakebase_mode {
ComputeNode::set_spec(&c.params, &mut state, pspec);
} else {
state.pspec = Some(pspec);
}
state.set_status(ComputeStatus::ConfigurationPending, &c.state_changed);
while state.status != ComputeStatus::Running {
state = c.state_changed.wait(state).unwrap();
info!(