feat: use ShutdownToken (CancellationToken inside) for nym-api (#5997)
* make nym-api use ShutdownToken instead of TaskClient * ignore public-api tests if env is not set * removed default features to avoid pulling in openssl
This commit is contained in:
committed by
GitHub
parent
8e7d1d510d
commit
e95aca715c
Generated
+43
-13
@@ -1373,7 +1373,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"windows-sys 0.48.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2352,12 +2352,6 @@ version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
|
||||
|
||||
[[package]]
|
||||
name = "dotenv"
|
||||
version = "0.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f"
|
||||
|
||||
[[package]]
|
||||
name = "dotenvy"
|
||||
version = "0.15.7"
|
||||
@@ -4030,7 +4024,7 @@ checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4907,7 +4901,7 @@ dependencies = [
|
||||
"cw3",
|
||||
"cw4",
|
||||
"dashmap",
|
||||
"dotenv",
|
||||
"dotenvy",
|
||||
"futures",
|
||||
"humantime-serde",
|
||||
"moka",
|
||||
@@ -4952,6 +4946,7 @@ dependencies = [
|
||||
"sqlx",
|
||||
"tempfile",
|
||||
"tendermint",
|
||||
"test-with",
|
||||
"thiserror 2.0.12",
|
||||
"time",
|
||||
"tokio",
|
||||
@@ -8229,6 +8224,28 @@ dependencies = [
|
||||
"elliptic-curve",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error-attr2"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error2"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802"
|
||||
dependencies = [
|
||||
"proc-macro-error-attr2",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.95"
|
||||
@@ -8397,7 +8414,7 @@ dependencies = [
|
||||
"once_cell",
|
||||
"socket2 0.5.10",
|
||||
"tracing",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -8882,7 +8899,7 @@ dependencies = [
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys 0.4.15",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -10189,7 +10206,7 @@ dependencies = [
|
||||
"getrandom 0.3.3",
|
||||
"once_cell",
|
||||
"rustix 1.0.8",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -10305,6 +10322,19 @@ dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "test-with"
|
||||
version = "0.15.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e0f370b9efbfbbc5f057cbce9888373eaeb146a3095bb8cc869b199c94d15559"
|
||||
dependencies = [
|
||||
"proc-macro-error2",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "testnet-manager"
|
||||
version = "0.1.0"
|
||||
@@ -11879,7 +11909,7 @@ version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
|
||||
dependencies = [
|
||||
"windows-sys 0.48.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -330,6 +330,7 @@ syn = "2"
|
||||
sysinfo = "0.37.0"
|
||||
tap = "1.0.1"
|
||||
tar = "0.4.44"
|
||||
test-with = { version = "0.15.4", default-features = false }
|
||||
tempfile = "3.20"
|
||||
thiserror = "2.0"
|
||||
time = "0.3.41"
|
||||
|
||||
@@ -110,6 +110,7 @@ impl ShutdownToken {
|
||||
// exposed method with the old name for easier migration
|
||||
// it will eventually be removed so please try to use `.clone_with_suffix` instead
|
||||
#[must_use]
|
||||
#[deprecated(note = "use .clone_with_suffix instead")]
|
||||
pub fn fork<S: Into<String>>(&self, child_suffix: S) -> Self {
|
||||
self.clone_with_suffix(child_suffix)
|
||||
}
|
||||
@@ -117,6 +118,7 @@ impl ShutdownToken {
|
||||
// exposed method with the old name for easier migration
|
||||
// it will eventually be removed so please try to use `.clone().named(name)` instead
|
||||
#[must_use]
|
||||
#[deprecated(note = "use .clone().named(name) instead")]
|
||||
pub fn fork_named<S: Into<String>>(&self, name: S) -> Self {
|
||||
self.clone().named(name)
|
||||
}
|
||||
@@ -232,6 +234,16 @@ impl ShutdownManager {
|
||||
manager.with_shutdown(async move { cancel_watcher.cancelled().await })
|
||||
}
|
||||
|
||||
pub fn empty_mock() -> Self {
|
||||
ShutdownManager {
|
||||
root_token: ShutdownToken::ephemeral(),
|
||||
legacy_task_manager: None,
|
||||
shutdown_signals: Default::default(),
|
||||
tracker: Default::default(),
|
||||
max_shutdown_duration: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_legacy_task_manager(mut self) -> Self {
|
||||
let mut legacy_manager =
|
||||
TaskManager::default().named(format!("{}-legacy", self.root_token.name()));
|
||||
|
||||
@@ -119,7 +119,6 @@ exceptions = [
|
||||
#{ allow = ["Zlib"], crate = "adler32" },
|
||||
{ allow = ["GPL-3.0"], crate = "nym-api" },
|
||||
{ allow = ["GPL-3.0"], crate = "nym-gateway" },
|
||||
{ allow = ["GPL-3.0"], crate = "nym-mixnode" },
|
||||
{ allow = ["GPL-3.0"], crate = "nym-network-requester" },
|
||||
{ allow = ["GPL-3.0"], crate = "nym-node" },
|
||||
{ allow = ["GPL-3.0"], crate = "nym-validator-rewarder" },
|
||||
|
||||
+2
-1
@@ -126,7 +126,8 @@ cw3 = { workspace = true }
|
||||
cw-utils = { workspace = true }
|
||||
rand_chacha = { workspace = true }
|
||||
sha2 = { workspace = true }
|
||||
dotenv = "0.15"
|
||||
dotenvy = { workspace = true }
|
||||
test-with = { workspace = true, default-features = false }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
@@ -11,7 +11,7 @@ use anyhow::{bail, Result};
|
||||
use nym_coconut_dkg_common::types::{Epoch, EpochId, EpochState};
|
||||
use nym_crypto::asymmetric::ed25519;
|
||||
use nym_dkg::bte::keys::KeyPair as DkgKeyPair;
|
||||
use nym_task::{TaskClient, TaskManager};
|
||||
use nym_task::{ShutdownManager, ShutdownToken};
|
||||
use rand::rngs::OsRng;
|
||||
use rand::{CryptoRng, Rng, RngCore};
|
||||
use std::path::PathBuf;
|
||||
@@ -273,7 +273,7 @@ impl<R: RngCore + CryptoRng + Clone> DkgController<R> {
|
||||
tick_duration < min
|
||||
}
|
||||
|
||||
pub(crate) async fn run(mut self, mut shutdown: TaskClient) {
|
||||
pub(crate) async fn run(mut self, shutdown: ShutdownToken) {
|
||||
let mut interval = interval(self.polling_rate);
|
||||
interval.set_missed_tick_behavior(MissedTickBehavior::Delay);
|
||||
|
||||
@@ -282,7 +282,7 @@ impl<R: RngCore + CryptoRng + Clone> DkgController<R> {
|
||||
let mut last_polled = OffsetDateTime::now_utc();
|
||||
let mut last_tick_duration = Default::default();
|
||||
|
||||
while !shutdown.is_shutdown() {
|
||||
while !shutdown.is_cancelled() {
|
||||
tokio::select! {
|
||||
_ = interval.tick() => {
|
||||
let now = OffsetDateTime::now_utc();
|
||||
@@ -300,7 +300,7 @@ impl<R: RngCore + CryptoRng + Clone> DkgController<R> {
|
||||
error!("failed to update the DKG state: {err}")
|
||||
}
|
||||
}
|
||||
_ = shutdown.recv() => {
|
||||
_ = shutdown.cancelled() => {
|
||||
trace!("DkgController: Received shutdown");
|
||||
}
|
||||
}
|
||||
@@ -314,12 +314,12 @@ impl<R: RngCore + CryptoRng + Clone> DkgController<R> {
|
||||
dkg_bte_keypair: DkgKeyPair,
|
||||
identity_key: ed25519::PublicKey,
|
||||
rng: R,
|
||||
shutdown: &TaskManager,
|
||||
shutdown_manager: &ShutdownManager,
|
||||
) -> Result<()>
|
||||
where
|
||||
R: Sync + Send + 'static,
|
||||
{
|
||||
let shutdown_listener = shutdown.subscribe();
|
||||
let shutdown_listener = shutdown_manager.clone_token("DKG controller");
|
||||
let dkg_controller = DkgController::new(
|
||||
config,
|
||||
nyxd_client,
|
||||
|
||||
@@ -6,7 +6,7 @@ use crate::node_status_api::models::NymApiStorageError;
|
||||
use crate::support::config::Config;
|
||||
use crate::support::storage::NymApiStorage;
|
||||
use nym_ecash_time::ecash_today_date;
|
||||
use nym_task::TaskClient;
|
||||
use nym_task::ShutdownToken;
|
||||
use std::time::Duration;
|
||||
use time::Date;
|
||||
use tokio::task::JoinHandle;
|
||||
@@ -20,11 +20,15 @@ pub struct EcashBackgroundStateCleaner {
|
||||
verified_tickets_retention_period_days: u32,
|
||||
|
||||
storage: NymApiStorage,
|
||||
task_client: TaskClient,
|
||||
shutdown_token: ShutdownToken,
|
||||
}
|
||||
|
||||
impl EcashBackgroundStateCleaner {
|
||||
pub fn new(global_config: &Config, storage: NymApiStorage, task_client: TaskClient) -> Self {
|
||||
pub fn new(
|
||||
global_config: &Config,
|
||||
storage: NymApiStorage,
|
||||
shutdown_token: ShutdownToken,
|
||||
) -> Self {
|
||||
EcashBackgroundStateCleaner {
|
||||
run_interval: global_config.ecash_signer.debug.stale_data_cleaner_interval,
|
||||
issued_ticketbooks_retention_period_days: global_config
|
||||
@@ -36,7 +40,7 @@ impl EcashBackgroundStateCleaner {
|
||||
.debug
|
||||
.verified_tickets_retention_period_days,
|
||||
storage,
|
||||
task_client,
|
||||
shutdown_token,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +72,7 @@ impl EcashBackgroundStateCleaner {
|
||||
let mut ticker = tokio::time::interval(self.run_interval);
|
||||
loop {
|
||||
tokio::select! {
|
||||
_ = self.task_client.recv() => {
|
||||
_ = self.shutdown_token.cancelled() => {
|
||||
trace!("EcashBackgroundStateCleaner: Received shutdown");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ use nym_ecash_contract_common::deposit::{Deposit, DepositId};
|
||||
use nym_ecash_contract_common::msg::ExecuteMsg;
|
||||
use nym_ecash_contract_common::redeem_credential::BATCH_REDEMPTION_PROPOSAL_TITLE;
|
||||
use nym_ecash_time::{ecash_default_expiration_date, ecash_today_date};
|
||||
use nym_task::TaskClient;
|
||||
use nym_task::ShutdownManager;
|
||||
use nym_ticketbooks_merkle::{IssuedTicketbook, IssuedTicketbooksFullMerkleProof, MerkleLeaf};
|
||||
use nym_validator_client::nyxd::AccountId;
|
||||
use nym_validator_client::EcashApiClient;
|
||||
@@ -126,7 +126,7 @@ impl EcashState {
|
||||
key_pair: KeyPair,
|
||||
comm_channel: D,
|
||||
storage: NymApiStorage,
|
||||
task_client: TaskClient,
|
||||
shutdown_manager: &ShutdownManager,
|
||||
) -> Self
|
||||
where
|
||||
C: LocalClient + Send + Sync + 'static,
|
||||
@@ -135,7 +135,11 @@ impl EcashState {
|
||||
Self {
|
||||
config: EcashStateConfig::new(global_config),
|
||||
background_cleaner_state: BackgroundCleanerState::WaitingStartup(
|
||||
EcashBackgroundStateCleaner::new(global_config, storage.clone(), task_client),
|
||||
EcashBackgroundStateCleaner::new(
|
||||
global_config,
|
||||
storage.clone(),
|
||||
shutdown_manager.clone_token("ecash-state-data-cleaner"),
|
||||
),
|
||||
),
|
||||
global: GlobalEcachState::new(contract_address),
|
||||
local: LocalEcashState::new(
|
||||
|
||||
@@ -59,7 +59,7 @@ use nym_crypto::asymmetric::ed25519;
|
||||
use nym_dkg::{NodeIndex, Threshold};
|
||||
use nym_ecash_contract_common::blacklist::{BlacklistedAccountResponse, Blacklisting};
|
||||
use nym_ecash_contract_common::deposit::{Deposit, DepositId, DepositResponse};
|
||||
use nym_task::TaskClient;
|
||||
use nym_task::ShutdownManager;
|
||||
use nym_validator_client::nym_api::routes::{
|
||||
ECASH_BLIND_SIGN, ECASH_ISSUED_TICKETBOOKS_CHALLENGE_COMMITMENT, ECASH_ISSUED_TICKETBOOKS_FOR,
|
||||
ECASH_ROUTES, V1_API_VERSION,
|
||||
@@ -1348,7 +1348,7 @@ impl TestFixture {
|
||||
staged_key_pair,
|
||||
comm_channel,
|
||||
storage.clone(),
|
||||
TaskClient::dummy(),
|
||||
&ShutdownManager::empty_mock(),
|
||||
);
|
||||
|
||||
// ideally this would have been generic, but that's way too much work
|
||||
@@ -1489,7 +1489,6 @@ mod credential_tests {
|
||||
use super::*;
|
||||
use crate::ecash::storage::EcashStorageExt;
|
||||
use axum::http::StatusCode;
|
||||
use nym_task::TaskClient;
|
||||
use nym_ticketbooks_merkle::MerkleLeaf;
|
||||
|
||||
#[tokio::test]
|
||||
@@ -1580,7 +1579,7 @@ mod credential_tests {
|
||||
staged_key_pair,
|
||||
comm_channel,
|
||||
storage.clone(),
|
||||
TaskClient::dummy(),
|
||||
&ShutdownManager::empty_mock(),
|
||||
);
|
||||
|
||||
let deposit_id = 42;
|
||||
|
||||
@@ -21,7 +21,7 @@ use crate::support::storage::NymApiStorage;
|
||||
use error::RewardingError;
|
||||
pub(crate) use helpers::RewardedNodeWithParams;
|
||||
use nym_mixnet_contract_common::{CurrentIntervalResponse, Interval};
|
||||
use nym_task::{TaskClient, TaskManager};
|
||||
use nym_task::{ShutdownManager, ShutdownToken};
|
||||
use std::time::Duration;
|
||||
use tokio::time::sleep;
|
||||
use tracing::{error, info, trace, warn};
|
||||
@@ -164,7 +164,7 @@ impl EpochAdvancer {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn wait_until_epoch_end(&mut self, shutdown: &mut TaskClient) -> Option<Interval> {
|
||||
async fn wait_until_epoch_end(&mut self, shutdown_token: &ShutdownToken) -> Option<Interval> {
|
||||
const POLL_INTERVAL: Duration = Duration::from_secs(120);
|
||||
|
||||
loop {
|
||||
@@ -175,7 +175,7 @@ impl EpochAdvancer {
|
||||
_ = sleep(POLL_INTERVAL) => {
|
||||
continue
|
||||
},
|
||||
_ = shutdown.recv() => {
|
||||
_ = shutdown_token.cancelled() => {
|
||||
trace!("wait_until_epoch_end: Received shutdown");
|
||||
break None
|
||||
}
|
||||
@@ -203,7 +203,7 @@ impl EpochAdvancer {
|
||||
_ = sleep(wait_time) => {
|
||||
|
||||
},
|
||||
_ = shutdown.recv() => {
|
||||
_ = shutdown_token.cancelled() => {
|
||||
trace!("wait_until_epoch_end: Received shutdown");
|
||||
break None
|
||||
}
|
||||
@@ -212,7 +212,10 @@ impl EpochAdvancer {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn run(&mut self, mut shutdown: TaskClient) -> Result<(), RewardingError> {
|
||||
pub(crate) async fn run(
|
||||
&mut self,
|
||||
shutdown_token: ShutdownToken,
|
||||
) -> Result<(), RewardingError> {
|
||||
info!("waiting for initial contract cache values before we can start rewarding");
|
||||
self.nym_contract_cache
|
||||
.naive_wait_for_initial_values()
|
||||
@@ -221,8 +224,8 @@ impl EpochAdvancer {
|
||||
info!("waiting for initial self-described cache values before we can start rewarding");
|
||||
self.described_cache.naive_wait_for_initial_values().await;
|
||||
|
||||
while !shutdown.is_shutdown() {
|
||||
let interval_details = match self.wait_until_epoch_end(&mut shutdown).await {
|
||||
while !shutdown_token.is_cancelled() {
|
||||
let interval_details = match self.wait_until_epoch_end(&shutdown_token).await {
|
||||
// received a shutdown
|
||||
None => return Ok(()),
|
||||
Some(interval) => interval,
|
||||
@@ -243,17 +246,17 @@ impl EpochAdvancer {
|
||||
status_cache: &NodeStatusCache,
|
||||
described_cache: SharedCache<DescribedNodes>,
|
||||
storage: &NymApiStorage,
|
||||
shutdown: &TaskManager,
|
||||
shutdown_manager: &ShutdownManager,
|
||||
) {
|
||||
let mut rewarded_set_updater = EpochAdvancer::new(
|
||||
let mut epoch_advancer = EpochAdvancer::new(
|
||||
nyxd_client,
|
||||
nym_contract_cache.to_owned(),
|
||||
status_cache.to_owned(),
|
||||
described_cache,
|
||||
storage.to_owned(),
|
||||
);
|
||||
let shutdown_listener = shutdown.subscribe();
|
||||
tokio::spawn(async move { rewarded_set_updater.run(shutdown_listener).await });
|
||||
let shutdown_listener = shutdown_manager.clone_token("epoch-advancer");
|
||||
tokio::spawn(async move { epoch_advancer.run(shutdown_listener).await });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
use crate::mixnet_contract_cache::cache::MixnetContractCache;
|
||||
use crate::support::caching::refresher::{CacheUpdateWatcher, RefreshRequester};
|
||||
use nym_mixnet_contract_common::{Interval, KeyRotationState};
|
||||
use nym_task::TaskClient;
|
||||
use nym_task::ShutdownToken;
|
||||
use time::OffsetDateTime;
|
||||
use tracing::{debug, error, info, trace};
|
||||
|
||||
@@ -110,14 +110,14 @@ impl KeyRotationController {
|
||||
}
|
||||
}
|
||||
|
||||
async fn run(&mut self, mut task_client: TaskClient) {
|
||||
async fn run(&mut self, shutdown_token: ShutdownToken) {
|
||||
self.contract_cache.naive_wait_for_initial_values().await;
|
||||
self.handle_contract_cache_update().await;
|
||||
|
||||
while !task_client.is_shutdown() {
|
||||
while !shutdown_token.is_cancelled() {
|
||||
tokio::select! {
|
||||
biased;
|
||||
_ = task_client.recv() => {
|
||||
_ = shutdown_token.cancelled() => {
|
||||
trace!("KeyRotationController: Received shutdown");
|
||||
}
|
||||
_ = self.contract_cache_watcher.changed() => {
|
||||
@@ -129,8 +129,8 @@ impl KeyRotationController {
|
||||
trace!("KeyRotationController: exiting")
|
||||
}
|
||||
|
||||
pub(crate) fn start(mut self, task_client: TaskClient) {
|
||||
tokio::spawn(async move { self.run(task_client).await });
|
||||
pub(crate) fn start(mut self, shutdown_token: ShutdownToken) {
|
||||
tokio::spawn(async move { self.run(shutdown_token).await });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ use nym_crypto::asymmetric::{ed25519, x25519};
|
||||
use nym_sphinx::acknowledgements::AckKey;
|
||||
use nym_sphinx::params::PacketType;
|
||||
use nym_sphinx::receiver::MessageReceiver;
|
||||
use nym_task::TaskManager;
|
||||
use nym_task::ShutdownManager;
|
||||
use std::sync::Arc;
|
||||
use tracing::info;
|
||||
|
||||
@@ -167,12 +167,12 @@ impl<R: MessageReceiver + Send + Sync + 'static> NetworkMonitorRunnables<R> {
|
||||
// TODO: note, that is not exactly doing what we want, because when
|
||||
// `ReceivedProcessor` is constructed, it already spawns a future
|
||||
// this needs to be refactored!
|
||||
pub(crate) fn spawn_tasks(self, shutdown: &TaskManager) {
|
||||
pub(crate) fn spawn_tasks(self, shutdown: &ShutdownManager) {
|
||||
let mut packet_receiver = self.packet_receiver;
|
||||
let mut monitor = self.monitor;
|
||||
let shutdown_listener = shutdown.subscribe();
|
||||
let shutdown_listener = shutdown.clone_token("NM-packet-receiver");
|
||||
tokio::spawn(async move { packet_receiver.run(shutdown_listener).await });
|
||||
let shutdown_listener = shutdown.subscribe();
|
||||
let shutdown_listener = shutdown.clone_token("NM-main");
|
||||
tokio::spawn(async move { monitor.run(shutdown_listener).await });
|
||||
}
|
||||
}
|
||||
@@ -241,7 +241,7 @@ pub(crate) async fn start<R: MessageReceiver + Send + Sync + 'static>(
|
||||
node_status_cache: NodeStatusCache,
|
||||
storage: &NymApiStorage,
|
||||
nyxd_client: nyxd::Client,
|
||||
shutdown: &TaskManager,
|
||||
shutdown: &ShutdownManager,
|
||||
) {
|
||||
let monitor_builder = setup(
|
||||
config,
|
||||
|
||||
@@ -12,7 +12,7 @@ use crate::support::config;
|
||||
use nym_mixnet_contract_common::NodeId;
|
||||
use nym_sphinx::params::PacketType;
|
||||
use nym_sphinx::receiver::MessageReceiver;
|
||||
use nym_task::TaskClient;
|
||||
use nym_task::ShutdownToken;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use tokio::time::{sleep, Duration, Instant};
|
||||
use tracing::{debug, error, info, trace};
|
||||
@@ -325,7 +325,7 @@ impl<R: MessageReceiver + Send + Sync> Monitor<R> {
|
||||
self.test_nonce += 1;
|
||||
}
|
||||
|
||||
pub(crate) async fn run(&mut self, mut shutdown: TaskClient) {
|
||||
pub(crate) async fn run(&mut self, shutdown_token: ShutdownToken) {
|
||||
self.received_processor.start_receiving();
|
||||
|
||||
// wait for validator cache to be ready
|
||||
@@ -334,18 +334,18 @@ impl<R: MessageReceiver + Send + Sync> Monitor<R> {
|
||||
.await;
|
||||
|
||||
let mut run_interval = tokio::time::interval(self.run_interval);
|
||||
while !shutdown.is_shutdown() {
|
||||
while !shutdown_token.is_cancelled() {
|
||||
tokio::select! {
|
||||
_ = run_interval.tick() => {
|
||||
tokio::select! {
|
||||
biased;
|
||||
_ = shutdown.recv() => {
|
||||
_ = shutdown_token.cancelled() => {
|
||||
trace!("UpdateHandler: Received shutdown");
|
||||
}
|
||||
_ = self.test_run() => (),
|
||||
}
|
||||
}
|
||||
_ = shutdown.recv() => {
|
||||
_ = shutdown_token.cancelled() => {
|
||||
trace!("UpdateHandler: Received shutdown");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ use futures::channel::mpsc;
|
||||
use futures::StreamExt;
|
||||
use nym_crypto::asymmetric::ed25519;
|
||||
use nym_gateway_client::{AcknowledgementReceiver, MixnetMessageReceiver};
|
||||
use nym_task::TaskClient;
|
||||
use nym_task::ShutdownToken;
|
||||
use tracing::{error, trace};
|
||||
|
||||
pub(crate) type GatewayClientUpdateSender = mpsc::UnboundedSender<GatewayClientUpdate>;
|
||||
@@ -57,11 +57,11 @@ impl PacketReceiver {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn run(&mut self, mut shutdown: TaskClient) {
|
||||
while !shutdown.is_shutdown() {
|
||||
pub(crate) async fn run(&mut self, shutdown_token: ShutdownToken) {
|
||||
while !shutdown_token.is_cancelled() {
|
||||
tokio::select! {
|
||||
biased;
|
||||
_ = shutdown.recv() => {
|
||||
_ = shutdown_token.cancelled() => {
|
||||
trace!("UpdateHandler: Received shutdown");
|
||||
}
|
||||
// unwrap here is fine as it can only return a `None` if the PacketSender has died
|
||||
|
||||
@@ -10,7 +10,7 @@ use crate::support::caching::cache::SharedCache;
|
||||
use crate::support::caching::refresher::CacheRefresher;
|
||||
use crate::support::{config, nyxd};
|
||||
use anyhow::bail;
|
||||
use nym_task::TaskManager;
|
||||
use nym_task::ShutdownManager;
|
||||
|
||||
pub(crate) mod data;
|
||||
pub(crate) mod refresher;
|
||||
@@ -19,7 +19,7 @@ pub(crate) async fn start_cache_refresher(
|
||||
config: &config::PerformanceProvider,
|
||||
nyxd_client: nyxd::Client,
|
||||
mixnet_contract_cache: MixnetContractCache,
|
||||
task_manager: &TaskManager,
|
||||
shutdown_manager: &ShutdownManager,
|
||||
) -> anyhow::Result<SharedCache<PerformanceContractCacheData>> {
|
||||
let values_to_retain = config.debug.max_epoch_entries_to_retain;
|
||||
|
||||
@@ -45,7 +45,7 @@ pub(crate) async fn start_cache_refresher(
|
||||
.with_update_fn(move |main_cache, update| {
|
||||
refresher_update_fn(main_cache, update, values_to_retain)
|
||||
})
|
||||
.start(task_manager.subscribe_named("performance-contract-cache-refresher"));
|
||||
.start(shutdown_manager.clone_token("performance-contract-cache-refresher"));
|
||||
|
||||
Ok(warmed_up_cache)
|
||||
}
|
||||
|
||||
+7
-7
@@ -21,7 +21,7 @@ use nym_api_requests::models::{
|
||||
NodePerformance,
|
||||
};
|
||||
use nym_mixnet_contract_common::{NodeId, NymNodeDetails, RewardingParams};
|
||||
use nym_task::TaskClient;
|
||||
use nym_task::ShutdownToken;
|
||||
use nym_topology::CachedEpochRewardedSet;
|
||||
use std::collections::HashMap;
|
||||
use std::time::Duration;
|
||||
@@ -66,20 +66,20 @@ impl NodeStatusCacheRefresher {
|
||||
}
|
||||
|
||||
/// Runs the node status cache refresher task.
|
||||
pub async fn run(&mut self, mut shutdown: TaskClient) {
|
||||
pub async fn run(&mut self, shutdown_token: ShutdownToken) {
|
||||
let mut last_update = OffsetDateTime::now_utc();
|
||||
let mut fallback_interval = time::interval(self.fallback_caching_interval);
|
||||
while !shutdown.is_shutdown() {
|
||||
while !shutdown_token.is_cancelled() {
|
||||
tokio::select! {
|
||||
biased;
|
||||
_ = shutdown.recv() => {
|
||||
_ = shutdown_token.cancelled() => {
|
||||
trace!("NodeStatusCacheRefresher: Received shutdown");
|
||||
}
|
||||
// Update node status cache when the contract cache / describe cache is updated
|
||||
Ok(_) = self.mixnet_contract_cache_listener.changed() => {
|
||||
tokio::select! {
|
||||
_ = self.maybe_refresh(&mut fallback_interval, &mut last_update) => (),
|
||||
_ = shutdown.recv() => {
|
||||
_ = shutdown_token.cancelled() => {
|
||||
trace!("NodeStatusCacheRefresher: Received shutdown");
|
||||
}
|
||||
}
|
||||
@@ -87,7 +87,7 @@ impl NodeStatusCacheRefresher {
|
||||
Ok(_) = self.describe_cache_listener.changed() => {
|
||||
tokio::select! {
|
||||
_ = self.maybe_refresh(&mut fallback_interval, &mut last_update) => (),
|
||||
_ = shutdown.recv() => {
|
||||
_ = shutdown_token.cancelled() => {
|
||||
trace!("NodeStatusCacheRefresher: Received shutdown");
|
||||
}
|
||||
}
|
||||
@@ -97,7 +97,7 @@ impl NodeStatusCacheRefresher {
|
||||
_ = fallback_interval.tick() => {
|
||||
tokio::select! {
|
||||
_ = self.maybe_refresh(&mut fallback_interval, &mut last_update) => (),
|
||||
_ = shutdown.recv() => {
|
||||
_ = shutdown_token.cancelled() => {
|
||||
trace!("NodeStatusCacheRefresher: Received shutdown");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ use crate::{
|
||||
support::{self},
|
||||
};
|
||||
pub(crate) use cache::NodeStatusCache;
|
||||
use nym_task::TaskManager;
|
||||
use nym_task::ShutdownManager;
|
||||
use std::time::Duration;
|
||||
use tokio::sync::watch;
|
||||
|
||||
@@ -39,7 +39,7 @@ pub(crate) fn start_cache_refresh(
|
||||
performance_provider: Box<dyn NodePerformanceProvider + Send + Sync>,
|
||||
nym_contract_cache_listener: watch::Receiver<support::caching::CacheNotification>,
|
||||
described_cache_cache_listener: watch::Receiver<support::caching::CacheNotification>,
|
||||
shutdown: &TaskManager,
|
||||
shutdown_manager: &ShutdownManager,
|
||||
) {
|
||||
let mut nym_api_cache_refresher = NodeStatusCacheRefresher::new(
|
||||
node_status_cache_state.to_owned(),
|
||||
@@ -50,6 +50,6 @@ pub(crate) fn start_cache_refresh(
|
||||
described_cache_cache_listener,
|
||||
performance_provider,
|
||||
);
|
||||
let shutdown_listener = shutdown.subscribe();
|
||||
let shutdown_listener = shutdown_manager.clone_token("node-status-refresher");
|
||||
tokio::spawn(async move { nym_api_cache_refresher.run(shutdown_listener).await });
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ use crate::node_status_api::models::{
|
||||
};
|
||||
use crate::node_status_api::ONE_DAY;
|
||||
use crate::storage::NymApiStorage;
|
||||
use nym_task::{TaskClient, TaskManager};
|
||||
use nym_task::{ShutdownManager, ShutdownToken};
|
||||
use std::time::Duration;
|
||||
use time::macros::time;
|
||||
use time::{OffsetDateTime, PrimitiveDateTime};
|
||||
@@ -70,7 +70,7 @@ impl HistoricalUptimeUpdater {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) async fn run(&self, mut shutdown: TaskClient) {
|
||||
pub(crate) async fn run(&self, shutdown_token: ShutdownToken) {
|
||||
// update uptimes at 23:00 UTC each day so that we'd have data from the actual [almost] whole day
|
||||
// and so that we would avoid the edge case of starting validator API at 23:59 and having some
|
||||
// nodes update for different days
|
||||
@@ -98,10 +98,10 @@ impl HistoricalUptimeUpdater {
|
||||
|
||||
let start = Instant::now() + time_left;
|
||||
let mut interval = interval_at(start, ONE_DAY);
|
||||
while !shutdown.is_shutdown() {
|
||||
while !shutdown_token.is_cancelled() {
|
||||
tokio::select! {
|
||||
biased;
|
||||
_ = shutdown.recv() => {
|
||||
_ = shutdown_token.cancelled() => {
|
||||
trace!("UpdateHandler: Received shutdown");
|
||||
}
|
||||
_ = interval.tick() => {
|
||||
@@ -116,9 +116,9 @@ impl HistoricalUptimeUpdater {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn start(storage: NymApiStorage, shutdown: &TaskManager) {
|
||||
pub(crate) fn start(storage: NymApiStorage, shutdown: &ShutdownManager) {
|
||||
let uptime_updater = HistoricalUptimeUpdater::new(storage);
|
||||
let shutdown_listener = shutdown.subscribe();
|
||||
let shutdown_listener = shutdown.child_token("uptime-updater");
|
||||
tokio::spawn(async move { uptime_updater.run(shutdown_listener).await });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ use crate::signers_cache::cache::SignersCacheData;
|
||||
use crate::support::caching::cache::SharedCache;
|
||||
use crate::support::caching::refresher::CacheRefresher;
|
||||
use crate::support::{config, nyxd};
|
||||
use nym_task::TaskManager;
|
||||
use nym_task::ShutdownManager;
|
||||
|
||||
pub(crate) mod cache;
|
||||
pub(crate) mod handlers;
|
||||
@@ -14,7 +14,7 @@ pub(crate) mod handlers;
|
||||
pub(crate) fn start_refresher(
|
||||
config: &config::SignersCache,
|
||||
nyxd_client: nyxd::Client,
|
||||
task_manager: &TaskManager,
|
||||
shutdown_manager: &ShutdownManager,
|
||||
) -> SharedCache<SignersCacheData> {
|
||||
let refresher = CacheRefresher::new(
|
||||
SignersCacheDataProvider::new(nyxd_client),
|
||||
@@ -23,7 +23,7 @@ pub(crate) fn start_refresher(
|
||||
.named("signers-cache-refresher");
|
||||
let shared_cache = refresher.get_shared_cache();
|
||||
refresher.start_with_delay(
|
||||
task_manager.subscribe_named("signers-cache-refresher"),
|
||||
shutdown_manager.clone_token("signers-cache-refresher"),
|
||||
config.debug.refresher_start_delay,
|
||||
);
|
||||
shared_cache
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
use crate::support::caching::cache::SharedCache;
|
||||
use crate::support::caching::CacheNotification;
|
||||
use async_trait::async_trait;
|
||||
use nym_task::TaskClient;
|
||||
use nym_task::ShutdownToken;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use tokio::sync::{watch, Notify};
|
||||
@@ -223,33 +223,33 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn refresh(&mut self, task_client: &mut TaskClient) {
|
||||
pub async fn refresh(&mut self, shutdown_token: &ShutdownToken) {
|
||||
info!("{}: refreshing cache state", self.name);
|
||||
|
||||
tokio::select! {
|
||||
biased;
|
||||
_ = task_client.recv() => {
|
||||
_ = shutdown_token.cancelled() => {
|
||||
trace!("{}: Received shutdown while refreshing cache", self.name)
|
||||
}
|
||||
_ = self.do_refresh_cache() => (),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn run(&mut self, mut task_client: TaskClient) {
|
||||
pub async fn run(&mut self, shutdown_token: ShutdownToken) {
|
||||
self.provider.wait_until_ready().await;
|
||||
|
||||
let mut refresh_interval = interval(self.refreshing_interval);
|
||||
while !task_client.is_shutdown() {
|
||||
while !shutdown_token.is_cancelled() {
|
||||
tokio::select! {
|
||||
biased;
|
||||
_ = task_client.recv() => {
|
||||
_ = shutdown_token.cancelled() => {
|
||||
trace!("{}: Received shutdown", self.name)
|
||||
}
|
||||
_ = refresh_interval.tick() => self.refresh(&mut task_client).await,
|
||||
_ = refresh_interval.tick() => self.refresh(&shutdown_token).await,
|
||||
// note: `Notify` is not cancellation safe, HOWEVER, there's only one listener,
|
||||
// so it doesn't matter if we lose our queue position
|
||||
_ = self.refresh_requester.0.notified() => {
|
||||
self.refresh(&mut task_client).await;
|
||||
self.refresh(&shutdown_token).await;
|
||||
// since we just performed the full request, we can reset our existing interval
|
||||
refresh_interval.reset();
|
||||
}
|
||||
@@ -257,16 +257,16 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start(mut self, task_client: TaskClient)
|
||||
pub fn start(mut self, shutdown_token: ShutdownToken)
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
E: Send + Sync + 'static,
|
||||
S: Send + Sync + 'static,
|
||||
{
|
||||
tokio::spawn(async move { self.run(task_client).await });
|
||||
tokio::spawn(async move { self.run(shutdown_token).await });
|
||||
}
|
||||
|
||||
pub fn start_with_delay(mut self, mut task_client: TaskClient, delay: Duration)
|
||||
pub fn start_with_delay(mut self, shutdown_token: ShutdownToken, delay: Duration)
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
E: Send + Sync + 'static,
|
||||
@@ -276,24 +276,24 @@ where
|
||||
let sleep = tokio::time::sleep(delay);
|
||||
tokio::select! {
|
||||
biased;
|
||||
_ = task_client.recv() => {
|
||||
_ = shutdown_token.cancelled() => {
|
||||
trace!("{}: Received shutdown", self.name);
|
||||
return
|
||||
}
|
||||
_ = sleep => {},
|
||||
}
|
||||
self.run(task_client).await
|
||||
self.run(shutdown_token).await
|
||||
});
|
||||
}
|
||||
|
||||
pub fn start_with_watcher(self, task_client: TaskClient) -> CacheUpdateWatcher
|
||||
pub fn start_with_watcher(self, shutdown_token: ShutdownToken) -> CacheUpdateWatcher
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
E: Send + Sync + 'static,
|
||||
S: Send + Sync + 'static,
|
||||
{
|
||||
let receiver = self.update_watcher();
|
||||
self.start(task_client);
|
||||
self.start(shutdown_token);
|
||||
receiver
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ use crate::support::http::state::chain_status::ChainStatusCache;
|
||||
use crate::support::http::state::contract_details::ContractDetailsCache;
|
||||
use crate::support::http::state::force_refresh::ForcedRefresh;
|
||||
use crate::support::http::state::AppState;
|
||||
use crate::support::http::{RouterBuilder, ShutdownHandles, TASK_MANAGER_TIMEOUT_S};
|
||||
use crate::support::http::{RouterBuilder, TASK_MANAGER_TIMEOUT_S};
|
||||
use crate::support::nyxd;
|
||||
use crate::support::storage::runtime_migrations::m001_directory_services_v2_1::migrate_to_directory_services_v2_1;
|
||||
use crate::support::storage::NymApiStorage;
|
||||
@@ -39,12 +39,12 @@ use crate::{
|
||||
use anyhow::{bail, Context};
|
||||
use nym_config::defaults::NymNetworkDetails;
|
||||
use nym_sphinx::receiver::SphinxMessageReceiver;
|
||||
use nym_task::TaskManager;
|
||||
use nym_task::ShutdownManager;
|
||||
use nym_validator_client::nyxd::Coin;
|
||||
use std::net::SocketAddr;
|
||||
use std::sync::Arc;
|
||||
use tokio_util::sync::CancellationToken;
|
||||
use tracing::{error, info};
|
||||
use std::time::Duration;
|
||||
use tracing::info;
|
||||
|
||||
#[derive(clap::Args, Debug)]
|
||||
pub(crate) struct Args {
|
||||
@@ -119,8 +119,9 @@ pub(crate) struct Args {
|
||||
pub(crate) allow_illegal_ips: bool,
|
||||
}
|
||||
|
||||
async fn start_nym_api_tasks(config: &Config) -> anyhow::Result<ShutdownHandles> {
|
||||
let task_manager = TaskManager::new(TASK_MANAGER_TIMEOUT_S);
|
||||
async fn start_nym_api_tasks(config: &Config) -> anyhow::Result<ShutdownManager> {
|
||||
let shutdown_manager = ShutdownManager::new("nym-api")
|
||||
.with_shutdown_duration(Duration::from_secs(TASK_MANAGER_TIMEOUT_S));
|
||||
|
||||
let nyxd_client = nyxd::Client::new(config)?;
|
||||
let connected_nyxd = config.get_nyxd_url();
|
||||
@@ -171,7 +172,7 @@ async fn start_nym_api_tasks(config: &Config) -> anyhow::Result<ShutdownHandles>
|
||||
ecash_keypair_wrapper.clone(),
|
||||
comm_channel,
|
||||
storage.clone(),
|
||||
task_manager.subscribe_named("ecash-state-data-cleaner"),
|
||||
&shutdown_manager,
|
||||
);
|
||||
|
||||
// if ecash signer is enabled, there are additional constraints on the nym-api,
|
||||
@@ -204,7 +205,11 @@ async fn start_nym_api_tasks(config: &Config) -> anyhow::Result<ShutdownHandles>
|
||||
|
||||
// check if signers cache is enabled, and if so, start the refresher
|
||||
let ecash_signers_cache = if config.signers_cache.enabled {
|
||||
signers_cache::start_refresher(&config.signers_cache, nyxd_client.clone(), &task_manager)
|
||||
signers_cache::start_refresher(
|
||||
&config.signers_cache,
|
||||
nyxd_client.clone(),
|
||||
&shutdown_manager,
|
||||
)
|
||||
} else {
|
||||
SharedCache::new()
|
||||
};
|
||||
@@ -244,7 +249,7 @@ async fn start_nym_api_tasks(config: &Config) -> anyhow::Result<ShutdownHandles>
|
||||
let describe_cache_refresh_requester = describe_cache_refresher.refresh_requester();
|
||||
|
||||
let describe_cache_watcher = describe_cache_refresher
|
||||
.start_with_watcher(task_manager.subscribe_named("node-self-described-data-refresher"));
|
||||
.start_with_watcher(shutdown_manager.clone_token("node-self-described-data-refresher"));
|
||||
|
||||
let performance_provider = if config.performance_provider.use_performance_contract_data {
|
||||
if network_details
|
||||
@@ -260,7 +265,7 @@ async fn start_nym_api_tasks(config: &Config) -> anyhow::Result<ShutdownHandles>
|
||||
&config.performance_provider,
|
||||
nyxd_client.clone(),
|
||||
mixnet_contract_cache_state.clone(),
|
||||
&task_manager,
|
||||
&shutdown_manager,
|
||||
)
|
||||
.await?;
|
||||
let provider = ContractPerformanceProvider::new(
|
||||
@@ -281,8 +286,8 @@ async fn start_nym_api_tasks(config: &Config) -> anyhow::Result<ShutdownHandles>
|
||||
&mixnet_contract_cache_state.clone(),
|
||||
nyxd_client.clone(),
|
||||
);
|
||||
let contract_cache_watcher =
|
||||
mixnet_contract_cache_refresher.start_with_watcher(task_manager.subscribe());
|
||||
let contract_cache_watcher = mixnet_contract_cache_refresher
|
||||
.start_with_watcher(shutdown_manager.clone_token("contracts-data-refresher"));
|
||||
|
||||
node_status_api::start_cache_refresh(
|
||||
&config.node_status_api,
|
||||
@@ -292,7 +297,7 @@ async fn start_nym_api_tasks(config: &Config) -> anyhow::Result<ShutdownHandles>
|
||||
performance_provider,
|
||||
contract_cache_watcher.clone(),
|
||||
describe_cache_watcher,
|
||||
&task_manager,
|
||||
&shutdown_manager,
|
||||
);
|
||||
|
||||
// start dkg task
|
||||
@@ -306,7 +311,7 @@ async fn start_nym_api_tasks(config: &Config) -> anyhow::Result<ShutdownHandles>
|
||||
dkg_bte_keypair,
|
||||
identity_public_key,
|
||||
rand::rngs::OsRng,
|
||||
&task_manager,
|
||||
&shutdown_manager,
|
||||
)?;
|
||||
}
|
||||
|
||||
@@ -323,11 +328,11 @@ async fn start_nym_api_tasks(config: &Config) -> anyhow::Result<ShutdownHandles>
|
||||
node_status_cache_state.clone(),
|
||||
&storage,
|
||||
nyxd_client.clone(),
|
||||
&task_manager,
|
||||
&shutdown_manager,
|
||||
)
|
||||
.await;
|
||||
|
||||
HistoricalUptimeUpdater::start(storage.to_owned(), &task_manager);
|
||||
HistoricalUptimeUpdater::start(storage.to_owned(), &shutdown_manager);
|
||||
}
|
||||
|
||||
// start 'rewarding' if its enabled and there exists source for performance data
|
||||
@@ -339,7 +344,7 @@ async fn start_nym_api_tasks(config: &Config) -> anyhow::Result<ShutdownHandles>
|
||||
&node_status_cache_state,
|
||||
described_nodes_cache.clone(),
|
||||
&storage,
|
||||
&task_manager,
|
||||
&shutdown_manager,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -350,24 +355,22 @@ async fn start_nym_api_tasks(config: &Config) -> anyhow::Result<ShutdownHandles>
|
||||
contract_cache_watcher,
|
||||
mixnet_contract_cache_state,
|
||||
)
|
||||
.start(task_manager.subscribe_named("KeyRotationController"));
|
||||
.start(shutdown_manager.clone_token("KeyRotationController"));
|
||||
|
||||
let bind_address = config.base.bind_address.to_owned();
|
||||
let server = router.build_server(&bind_address).await?;
|
||||
|
||||
let cancellation_token = CancellationToken::new();
|
||||
let shutdown_button = cancellation_token.clone();
|
||||
let axum_shutdown_receiver = cancellation_token.cancelled_owned();
|
||||
let server_handle = tokio::spawn(async move {
|
||||
let http_shutdown = shutdown_manager.clone_token("axum-http");
|
||||
tokio::spawn(async move {
|
||||
{
|
||||
info!("Started Axum HTTP V2 server on {bind_address}");
|
||||
server.run(axum_shutdown_receiver).await
|
||||
server.run(http_shutdown).await
|
||||
}
|
||||
});
|
||||
|
||||
let shutdown = ShutdownHandles::new(task_manager, server_handle, shutdown_button);
|
||||
shutdown_manager.close();
|
||||
|
||||
Ok(shutdown)
|
||||
Ok(shutdown_manager)
|
||||
}
|
||||
|
||||
pub(crate) async fn execute(args: Args) -> anyhow::Result<()> {
|
||||
@@ -378,32 +381,8 @@ pub(crate) async fn execute(args: Args) -> anyhow::Result<()> {
|
||||
|
||||
config.validate()?;
|
||||
|
||||
let mut axum_shutdown = start_nym_api_tasks(&config).await?;
|
||||
|
||||
// it doesn't matter which server catches the interrupt: it needs only be caught once
|
||||
if let Err(err) = axum_shutdown.task_manager_mut().catch_interrupt().await {
|
||||
error!("Error stopping axum tasks: {err}");
|
||||
}
|
||||
|
||||
info!("Stopping nym API");
|
||||
|
||||
axum_shutdown.task_manager_mut().signal_shutdown().ok();
|
||||
axum_shutdown.task_manager_mut().wait_for_shutdown().await;
|
||||
|
||||
let running_server = axum_shutdown.shutdown_axum();
|
||||
|
||||
match running_server.await {
|
||||
Ok(Ok(_)) => {
|
||||
info!("Axum HTTP server shut down without errors");
|
||||
}
|
||||
Ok(Err(err)) => {
|
||||
error!("Axum HTTP server terminated with: {err}");
|
||||
anyhow::bail!(err)
|
||||
}
|
||||
Err(err) => {
|
||||
error!("Server task panicked: {err}");
|
||||
}
|
||||
};
|
||||
let shutdown_manager = start_nym_api_tasks(&config).await?;
|
||||
shutdown_manager.run_until_shutdown().await;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
// Copyright 2022-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use nym_task::TaskManager;
|
||||
use tokio::task::JoinHandle;
|
||||
use tokio_util::sync::CancellationToken;
|
||||
|
||||
pub(crate) mod helpers;
|
||||
pub(crate) mod openapi;
|
||||
pub(crate) mod router;
|
||||
@@ -13,50 +9,3 @@ pub(crate) mod state;
|
||||
pub(crate) use router::RouterBuilder;
|
||||
|
||||
pub(crate) const TASK_MANAGER_TIMEOUT_S: u64 = 10;
|
||||
|
||||
/// Shutdown goes 2 directions:
|
||||
/// 1. signal background tasks to gracefully finish
|
||||
/// 2. signal server itself
|
||||
///
|
||||
/// These are done through separate shutdown handles. Of course, shut down server
|
||||
/// AFTER you have shut down BG tasks (or past their grace period).
|
||||
pub(crate) struct ShutdownHandles {
|
||||
task_manager: TaskManager,
|
||||
axum_shutdown_button: ShutdownAxum,
|
||||
/// Tokio JoinHandle for axum server's task
|
||||
axum_join_handle: AxumJoinHandle,
|
||||
}
|
||||
|
||||
impl ShutdownHandles {
|
||||
/// Cancellation token is given to Axum server constructor. When the token
|
||||
/// receives a shutdown signal, Axum server will shut down gracefully.
|
||||
pub(crate) fn new(
|
||||
task_manager: TaskManager,
|
||||
axum_server_handle: AxumJoinHandle,
|
||||
shutdown_button: CancellationToken,
|
||||
) -> Self {
|
||||
Self {
|
||||
task_manager,
|
||||
axum_shutdown_button: ShutdownAxum(shutdown_button.clone()),
|
||||
axum_join_handle: axum_server_handle,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn task_manager_mut(&mut self) -> &mut TaskManager {
|
||||
&mut self.task_manager
|
||||
}
|
||||
|
||||
/// Signal server to shut down, then return join handle to its
|
||||
/// `tokio` task
|
||||
///
|
||||
/// https://tikv.github.io/doc/tokio/task/struct.JoinHandle.html
|
||||
#[must_use]
|
||||
pub(crate) fn shutdown_axum(self) -> AxumJoinHandle {
|
||||
self.axum_shutdown_button.0.cancel();
|
||||
self.axum_join_handle
|
||||
}
|
||||
}
|
||||
|
||||
struct ShutdownAxum(CancellationToken);
|
||||
|
||||
type AxumJoinHandle = JoinHandle<std::io::Result<()>>;
|
||||
|
||||
@@ -19,8 +19,8 @@ use axum::routing::get;
|
||||
use axum::Router;
|
||||
use core::net::SocketAddr;
|
||||
use nym_http_api_common::middleware::logging::log_request_info;
|
||||
use nym_task::ShutdownToken;
|
||||
use tokio::net::TcpListener;
|
||||
use tokio_util::sync::WaitForCancellationFutureOwned;
|
||||
use tower_http::cors::CorsLayer;
|
||||
use utoipa::OpenApi;
|
||||
use utoipa_swagger_ui::SwaggerUi;
|
||||
@@ -131,14 +131,13 @@ pub(crate) struct ApiHttpServer {
|
||||
}
|
||||
|
||||
impl ApiHttpServer {
|
||||
pub async fn run(self, receiver: WaitForCancellationFutureOwned) -> Result<(), std::io::Error> {
|
||||
// into_make_service_with_connect_info allows us to see client ip address
|
||||
pub async fn run(self, shutdown_token: ShutdownToken) -> Result<(), std::io::Error> {
|
||||
axum::serve(
|
||||
self.listener,
|
||||
self.router
|
||||
.into_make_service_with_connect_info::<SocketAddr>(),
|
||||
)
|
||||
.with_graceful_shutdown(receiver)
|
||||
.with_graceful_shutdown(async move { shutdown_token.cancelled().await })
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use crate::utils::{base_url, make_request, validate_json_response};
|
||||
|
||||
#[tokio::test]
|
||||
#[test_with::env(NYM_API)]
|
||||
async fn test_health() -> Result<(), String> {
|
||||
let url = format!("{}/v1/api-status/health", base_url()?);
|
||||
let res = make_request(&url).await?;
|
||||
@@ -11,6 +12,7 @@ async fn test_health() -> Result<(), String> {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[test_with::env(NYM_API)]
|
||||
async fn test_build_information() -> Result<(), String> {
|
||||
let url = format!("{}/v1/api-status/build-information", base_url()?);
|
||||
let res = make_request(&url).await?;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use crate::utils::{base_url, make_request, validate_json_response};
|
||||
|
||||
#[tokio::test]
|
||||
#[test_with::env(NYM_API)]
|
||||
async fn test_get_circulating_supply() -> Result<(), String> {
|
||||
let url = format!("{}/v1/circulating-supply", base_url()?);
|
||||
let res = make_request(&url).await?;
|
||||
@@ -14,6 +15,7 @@ async fn test_get_circulating_supply() -> Result<(), String> {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[test_with::env(NYM_API)]
|
||||
async fn test_get_circulating_supply_value() -> Result<(), String> {
|
||||
let url = format!(
|
||||
"{}/v1/circulating-supply/circulating-supply-value",
|
||||
@@ -32,6 +34,7 @@ async fn test_get_circulating_supply_value() -> Result<(), String> {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[test_with::env(NYM_API)]
|
||||
async fn test_get_total_supply_value() -> Result<(), String> {
|
||||
let url = format!("{}/v1/circulating-supply/total-supply-value", base_url()?);
|
||||
let res = make_request(&url).await?;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use crate::utils::{base_url, make_request, validate_json_response};
|
||||
|
||||
#[tokio::test]
|
||||
#[test_with::env(NYM_API)]
|
||||
async fn test_get_current_epoch() -> Result<(), String> {
|
||||
let url = format!("{}/v1/epoch/current", base_url()?);
|
||||
let res = make_request(&url).await?;
|
||||
@@ -19,6 +20,7 @@ async fn test_get_current_epoch() -> Result<(), String> {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[test_with::env(NYM_API)]
|
||||
async fn test_get_reward_params() -> Result<(), String> {
|
||||
let url = format!("{}/v1/epoch/reward_params", base_url()?);
|
||||
let res = make_request(&url).await?;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use crate::utils::{base_url, test_client, validate_json_response};
|
||||
|
||||
#[tokio::test]
|
||||
#[test_with::env(NYM_API)]
|
||||
async fn test_get_chain_status() -> Result<(), String> {
|
||||
let url = format!("{}/v1/network/chain-status", base_url()?);
|
||||
let res = test_client()
|
||||
@@ -29,6 +30,7 @@ async fn test_get_chain_status() -> Result<(), String> {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[test_with::env(NYM_API)]
|
||||
async fn test_get_network_details() -> Result<(), String> {
|
||||
let url = format!("{}/v1/network/details", base_url()?);
|
||||
let res = test_client()
|
||||
@@ -54,6 +56,7 @@ async fn test_get_network_details() -> Result<(), String> {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[test_with::env(NYM_API)]
|
||||
async fn test_get_nym_contracts() -> Result<(), String> {
|
||||
let url = format!("{}/v1/network/nym-contracts", base_url()?);
|
||||
let res = test_client()
|
||||
@@ -75,6 +78,7 @@ async fn test_get_nym_contracts() -> Result<(), String> {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[test_with::env(NYM_API)]
|
||||
async fn test_get_nym_contracts_detailed() -> Result<(), String> {
|
||||
let url = format!("{}/v1/network/nym-contracts-detailed", base_url()?);
|
||||
let res = test_client()
|
||||
|
||||
@@ -2,6 +2,7 @@ use crate::utils::{base_url, get_any_node_id, make_request, test_client, validat
|
||||
use time::OffsetDateTime;
|
||||
|
||||
#[tokio::test]
|
||||
#[test_with::env(NYM_API)]
|
||||
async fn test_get_bonded_nodes() -> Result<(), String> {
|
||||
let url = format!("{}/v1/nym-nodes/bonded", base_url()?);
|
||||
let res = make_request(&url).await?;
|
||||
@@ -19,6 +20,7 @@ async fn test_get_bonded_nodes() -> Result<(), String> {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[test_with::env(NYM_API)]
|
||||
async fn test_get_described_nodes() -> Result<(), String> {
|
||||
let url = format!("{}/v1/nym-nodes/described", base_url()?);
|
||||
let res = make_request(&url).await?;
|
||||
@@ -37,13 +39,14 @@ async fn test_get_described_nodes() -> Result<(), String> {
|
||||
|
||||
// TODO enable this once noise is properly integrated
|
||||
// #[tokio::test]
|
||||
#[test_with::env(NYM_API)]
|
||||
// async fn test_get_noise() -> Result<(), String> {
|
||||
// let url = format!("{}/v1/nym-nodes/noise", base_url()?);
|
||||
// let res = test_client().get(&url).send().await.map_err(|err| panic!("Failed to send request to {}: {}", url, err))?;
|
||||
// let json = validate_json_response(res).await;
|
||||
// }
|
||||
|
||||
#[tokio::test]
|
||||
#[test_with::env(NYM_API)]
|
||||
async fn test_get_rewarded_set() -> Result<(), String> {
|
||||
let url = format!("{}/v1/nym-nodes/rewarded-set", base_url()?);
|
||||
let res = make_request(&url).await?;
|
||||
@@ -64,6 +67,7 @@ async fn test_get_rewarded_set() -> Result<(), String> {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[test_with::env(NYM_API)]
|
||||
async fn test_get_annotation_for_node() -> Result<(), String> {
|
||||
let id = get_any_node_id().await?;
|
||||
let url = format!("{}/v1/nym-nodes/annotation/{}", base_url()?, id);
|
||||
@@ -81,6 +85,7 @@ async fn test_get_annotation_for_node() -> Result<(), String> {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[test_with::env(NYM_API)]
|
||||
async fn test_get_historical_performance() -> Result<(), String> {
|
||||
let id = get_any_node_id().await?;
|
||||
let date = OffsetDateTime::now_utc().date().to_string();
|
||||
@@ -101,6 +106,7 @@ async fn test_get_historical_performance() -> Result<(), String> {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[test_with::env(NYM_API)]
|
||||
async fn test_get_performance_history() -> Result<(), String> {
|
||||
let id = get_any_node_id().await?;
|
||||
let url = format!("{}/v1/nym-nodes/performance-history/{}", base_url()?, id);
|
||||
@@ -120,6 +126,7 @@ async fn test_get_performance_history() -> Result<(), String> {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[test_with::env(NYM_API)]
|
||||
async fn test_get_performance() -> Result<(), String> {
|
||||
let id = get_any_node_id().await?;
|
||||
let url = format!("{}/v1/nym-nodes/performance/{}", base_url()?, id);
|
||||
@@ -138,6 +145,7 @@ async fn test_get_performance() -> Result<(), String> {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[test_with::env(NYM_API)]
|
||||
async fn test_get_uptime_history() -> Result<(), String> {
|
||||
let id = get_any_node_id().await?;
|
||||
let url = format!("{}/v1/nym-nodes/uptime-history/{}", base_url()?, id);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use crate::utils::{base_url, make_request, validate_json_response};
|
||||
|
||||
#[tokio::test]
|
||||
#[test_with::env(NYM_API)]
|
||||
async fn test_get_config_score_details() -> Result<(), String> {
|
||||
let url = format!("{}/v1/status/config-score-details", base_url()?);
|
||||
let res = make_request(&url).await?;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use crate::utils::{base_url, make_request, validate_json_response};
|
||||
|
||||
#[tokio::test]
|
||||
#[test_with::env(NYM_API)]
|
||||
async fn test_get_skimmed_nodes_active() -> Result<(), String> {
|
||||
let url = format!("{}/v1/unstable/nym-nodes/skimmed/active", base_url()?);
|
||||
let res = make_request(&url).await?;
|
||||
@@ -19,6 +20,7 @@ async fn test_get_skimmed_nodes_active() -> Result<(), String> {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[test_with::env(NYM_API)]
|
||||
async fn test_get_skimmed_active_mixnodes() -> Result<(), String> {
|
||||
let url = format!(
|
||||
"{}/v1/unstable/nym-nodes/skimmed/mixnodes/active",
|
||||
@@ -44,6 +46,7 @@ async fn test_get_skimmed_active_mixnodes() -> Result<(), String> {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[test_with::env(NYM_API)]
|
||||
async fn test_get_skimmed_all_mixnodes() -> Result<(), String> {
|
||||
let url = format!("{}/v1/unstable/nym-nodes/skimmed/mixnodes/all", base_url()?);
|
||||
let res = make_request(&url).await?;
|
||||
@@ -66,6 +69,7 @@ async fn test_get_skimmed_all_mixnodes() -> Result<(), String> {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[test_with::env(NYM_API)]
|
||||
async fn test_get_skimmed_active_exit_gateways() -> Result<(), String> {
|
||||
let url = format!(
|
||||
"{}/v1/unstable/nym-nodes/skimmed/exit-gateways/active",
|
||||
@@ -91,6 +95,7 @@ async fn test_get_skimmed_active_exit_gateways() -> Result<(), String> {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[test_with::env(NYM_API)]
|
||||
async fn test_get_skimmed_all_exit_gateways() -> Result<(), String> {
|
||||
let url = format!(
|
||||
"{}/v1/unstable/nym-nodes/skimmed/exit-gateways/all",
|
||||
@@ -116,6 +121,7 @@ async fn test_get_skimmed_all_exit_gateways() -> Result<(), String> {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[test_with::env(NYM_API)]
|
||||
async fn test_get_skimmed_active_entry_gateways() -> Result<(), String> {
|
||||
let url = format!(
|
||||
"{}/v1/unstable/nym-nodes/skimmed/entry-gateways/active",
|
||||
@@ -141,6 +147,7 @@ async fn test_get_skimmed_active_entry_gateways() -> Result<(), String> {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[test_with::env(NYM_API)]
|
||||
async fn test_get_skimmed_all_entry_gateways() -> Result<(), String> {
|
||||
let url = format!(
|
||||
"{}/v1/unstable/nym-nodes/skimmed/entry-gateways/all",
|
||||
|
||||
@@ -4,6 +4,7 @@ use crate::utils::{
|
||||
};
|
||||
|
||||
#[tokio::test]
|
||||
#[test_with::env(NYM_API)]
|
||||
async fn test_get_gateway_unstable_test_results() -> Result<(), String> {
|
||||
let identity = get_gateway_identity_key().await?;
|
||||
let url = format!(
|
||||
@@ -35,6 +36,7 @@ async fn test_get_gateway_unstable_test_results() -> Result<(), String> {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[test_with::env(NYM_API)]
|
||||
async fn test_get_mixnode_unstable_test_results() -> Result<(), String> {
|
||||
let mix_id = get_mixnode_node_id().await?;
|
||||
let url = format!(
|
||||
@@ -66,6 +68,7 @@ async fn test_get_mixnode_unstable_test_results() -> Result<(), String> {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[test_with::env(NYM_API)]
|
||||
async fn test_get_latest_network_monitor_run_details() -> Result<(), String> {
|
||||
let url = format!(
|
||||
"{}/v1/status/network-monitor/unstable/run/latest/details",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use dotenv::dotenv;
|
||||
use dotenvy::dotenv;
|
||||
use reqwest::{Client, Response};
|
||||
use serde_json::Value;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user