feature: CancellationToken-based shutdowns (#5325)

* initial stub for ShutdownToken

* attempting to start using new ShutdownManager in NymNode

* migrated verloc tasks

* added custom shutdown signal registration

* integrated legacy task support

* migrated additional tasks inside nym-node

* removed import thats unused in wasm

* apply review comments

* windows fixes
This commit is contained in:
Jędrzej Stuczyński
2025-01-13 09:13:13 +00:00
committed by GitHub
parent 11d6ee2fdb
commit 102cd1033c
18 changed files with 515 additions and 191 deletions
+32 -25
View File
@@ -43,7 +43,7 @@ use nym_node_metrics::NymNodeMetrics;
use nym_node_requests::api::v1::node::models::{AnnouncePorts, NodeDescription};
use nym_sphinx_acknowledgements::AckKey;
use nym_sphinx_addressing::Recipient;
use nym_task::{TaskClient, TaskManager};
use nym_task::{ShutdownManager, ShutdownToken, TaskClient};
use nym_validator_client::client::NymApiClientExt;
use nym_validator_client::models::NodeRefreshBody;
use nym_validator_client::{NymApiClient, UserAgent};
@@ -351,6 +351,7 @@ impl From<WireguardData> for nym_wireguard::WireguardData {
pub(crate) struct NymNode {
config: Config,
accepted_operator_terms_and_conditions: bool,
shutdown_manager: ShutdownManager,
description: NodeDescription,
@@ -447,6 +448,10 @@ impl NymNode {
wireguard: Some(wireguard_data),
config,
accepted_operator_terms_and_conditions: false,
shutdown_manager: ShutdownManager::new("NymNode")
.with_legacy_task_manager()
.with_default_shutdown_signals()
.map_err(|source| NymNodeError::ShutdownSignalFailure { source })?,
})
}
@@ -823,7 +828,7 @@ impl NymNode {
}
}
pub(crate) fn start_verloc_measurements(&self, shutdown: TaskClient) {
pub(crate) fn start_verloc_measurements(&self) {
info!(
"Starting the [verloc] round-trip-time measurer on {} ...",
self.config.verloc.bind_address
@@ -845,8 +850,11 @@ impl NymNode {
.retry_timeout(self.config.verloc.debug.retry_timeout)
.build();
let mut verloc_measurer =
VerlocMeasurer::new(config, self.ed25519_identity_keys.clone(), shutdown);
let mut verloc_measurer = VerlocMeasurer::new(
config,
self.ed25519_identity_keys.clone(),
self.shutdown_manager.clone_token("verloc"),
);
verloc_measurer.set_shared_state(self.verloc_stats.clone());
tokio::spawn(async move { verloc_measurer.run().await });
}
@@ -855,14 +863,14 @@ impl NymNode {
&self,
active_clients_store: ActiveClientsStore,
active_egress_mixnet_connections: ActiveConnections,
shutdown: TaskClient,
shutdown: ShutdownToken,
) -> MetricEventsSender {
info!("setting up node metrics...");
// aggregator (to listen for any metrics events)
let mut metrics_aggregator = MetricsAggregator::new(
self.config.metrics.debug.aggregator_update_rate,
shutdown.fork("aggregator"),
shutdown.clone_with_suffix("aggregator"),
);
// >>>> START: register all relevant handlers for custom events
@@ -924,12 +932,9 @@ impl NymNode {
ConsoleLogger::new(
self.config.metrics.debug.console_logging_update_interval,
self.metrics.clone(),
shutdown.named("metrics-console-logger"),
shutdown.clone_with_suffix("metrics-console-logger"),
)
.start();
} else {
let mut shutdown = shutdown;
shutdown.disarm()
}
let events_sender = metrics_aggregator.sender();
@@ -943,7 +948,7 @@ impl NymNode {
pub(crate) fn start_mixnet_listener(
&self,
active_clients_store: &ActiveClientsStore,
shutdown: TaskClient,
shutdown: ShutdownToken,
) -> (MixForwardingSender, ActiveConnections) {
let processing_config = ProcessingConfig::new(&self.config);
@@ -972,7 +977,7 @@ impl NymNode {
let mut packet_forwarder = PacketForwarder::new(
mixnet_client,
self.metrics.clone(),
shutdown.fork("mix-packet-forwarder"),
shutdown.clone_with_suffix("mix-packet-forwarder"),
);
let mix_packet_sender = packet_forwarder.sender();
tokio::spawn(async move { packet_forwarder.run().await });
@@ -1005,45 +1010,47 @@ impl NymNode {
);
debug!("config: {:#?}", self.config);
let mut task_manager = TaskManager::default().named("NymNode");
let http_server = self
.build_http_server()
.await?
.with_task_client(task_manager.subscribe_named("http-server"));
let http_server = self.build_http_server().await?;
let bind_address = self.config.http.bind_address;
tokio::spawn(async move {
let server_shutdown = self.shutdown_manager.clone_token("http-server");
self.shutdown_manager.spawn(async move {
{
info!("started NymNodeHTTPServer on {bind_address}");
http_server.run().await
info!("starting NymNodeHTTPServer on {bind_address}");
http_server
.with_graceful_shutdown(async move { server_shutdown.cancelled().await })
.await
}
});
self.try_refresh_remote_nym_api_cache().await;
self.start_verloc_measurements(task_manager.subscribe_named("verloc-measurements"));
self.start_verloc_measurements();
let active_clients_store = ActiveClientsStore::new();
let (mix_packet_sender, active_egress_mixnet_connections) = self.start_mixnet_listener(
&active_clients_store,
task_manager.subscribe_named("mixnet-traffic"),
self.shutdown_manager.clone_token("mixnet-traffic"),
);
let metrics_sender = self.setup_metrics_backend(
active_clients_store.clone(),
active_egress_mixnet_connections,
task_manager.subscribe_named("metrics"),
self.shutdown_manager.clone_token("metrics"),
);
self.start_gateway_tasks(
metrics_sender,
active_clients_store,
mix_packet_sender,
task_manager.subscribe_named("gateway-tasks"),
self.shutdown_manager.subscribe_legacy("gateway-tasks"),
)
.await?;
let _ = task_manager.catch_interrupt().await;
self.shutdown_manager.close();
self.shutdown_manager.wait_for_shutdown_signal().await;
Ok(())
}
}