Skip to content

Commit

Permalink
chore: await PocketIC HTTP gateway shutdown (#2709)
Browse files Browse the repository at this point in the history
This PR ensures that the PocketIC server awaits the PocketIC HTTP
gateway shutdown by shutting down the axum server handle in a drop
handler invoked in the methods `ApiState::stop_http_gateway` and
`ApiState::stop_all_http_gateways` after setting the `HttpGateway`
struct to `None`.

In particular, the function `ApiState::stop_all_http_gateways` is
awaited in the signal handler of the PocketIC server and thus all
PocketIC HTTP gateways are shut down gracefully before the PocketIC main
axum server is shut down and the main function exits (terminating the
PocketIC server process).
  • Loading branch information
mraszyk authored Nov 20, 2024
1 parent 58f2b9f commit ea50dd2
Showing 1 changed file with 26 additions and 19 deletions.
45 changes: 26 additions & 19 deletions rs/pocket_ic_server/src/state_api/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,26 @@ struct Instance {
state: InstanceState,
}

struct HttpGateway {
details: HttpGatewayDetails,
shutdown_handle: Handle,
}

impl HttpGateway {
fn new(details: HttpGatewayDetails, shutdown_handle: Handle) -> Self {
Self {
details,
shutdown_handle,
}
}
}

impl Drop for HttpGateway {
fn drop(&mut self) {
self.shutdown_handle.shutdown();
}
}

/// The state of the PocketIC API.
pub struct ApiState {
// impl note: If locks are acquired on both fields, acquire first on `instances` and then on `graph`.
Expand All @@ -136,7 +156,7 @@ pub struct ApiState {
// PocketIC server port
port: Option<u16>,
// HTTP gateway infos (`None` = stopped)
http_gateways: Arc<RwLock<Vec<Option<HttpGatewayDetails>>>>,
http_gateways: Arc<RwLock<Vec<Option<HttpGateway>>>>,
}

#[derive(Default)]
Expand Down Expand Up @@ -1063,22 +1083,10 @@ impl ApiState {
domains: http_gateway_config.domains.clone(),
https_config: http_gateway_config.https_config.clone(),
};
http_gateways.push(Some(http_gateway_details));
drop(http_gateways);

let http_gateways_for_shutdown = self.http_gateways.clone();
let shutdown_handle = handle.clone();
tokio::spawn(async move {
loop {
let guard = http_gateways_for_shutdown.read().await;
if guard[instance_id].is_none() {
shutdown_handle.shutdown();
break;
}
drop(guard);
tokio::time::sleep(Duration::from_secs(1)).await;
}
});
let http_gateway = HttpGateway::new(http_gateway_details, shutdown_handle);
http_gateways.push(Some(http_gateway));
drop(http_gateways);

Ok(HttpGatewayInfo {
instance_id,
Expand Down Expand Up @@ -1197,9 +1205,8 @@ impl ApiState {
self.http_gateways
.read()
.await
.clone()
.into_iter()
.flatten()
.iter()
.filter_map(|gateway| gateway.as_ref().map(|g| g.details.clone()))
.collect()
}

Expand Down

0 comments on commit ea50dd2

Please sign in to comment.