Add node health check to transaction preflight
This commit is contained in:
@ -6,6 +6,7 @@ use crate::{
|
|||||||
contact_info::ContactInfo,
|
contact_info::ContactInfo,
|
||||||
non_circulating_supply::calculate_non_circulating_supply,
|
non_circulating_supply::calculate_non_circulating_supply,
|
||||||
rpc_error::RpcCustomError,
|
rpc_error::RpcCustomError,
|
||||||
|
rpc_health::*,
|
||||||
validator::ValidatorExit,
|
validator::ValidatorExit,
|
||||||
};
|
};
|
||||||
use bincode::serialize;
|
use bincode::serialize;
|
||||||
@ -74,6 +75,7 @@ pub struct JsonRpcRequestProcessor {
|
|||||||
blockstore: Arc<Blockstore>,
|
blockstore: Arc<Blockstore>,
|
||||||
config: JsonRpcConfig,
|
config: JsonRpcConfig,
|
||||||
validator_exit: Arc<RwLock<Option<ValidatorExit>>>,
|
validator_exit: Arc<RwLock<Option<ValidatorExit>>>,
|
||||||
|
health: Arc<RpcHealth>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl JsonRpcRequestProcessor {
|
impl JsonRpcRequestProcessor {
|
||||||
@ -128,6 +130,7 @@ impl JsonRpcRequestProcessor {
|
|||||||
block_commitment_cache: Arc<RwLock<BlockCommitmentCache>>,
|
block_commitment_cache: Arc<RwLock<BlockCommitmentCache>>,
|
||||||
blockstore: Arc<Blockstore>,
|
blockstore: Arc<Blockstore>,
|
||||||
validator_exit: Arc<RwLock<Option<ValidatorExit>>>,
|
validator_exit: Arc<RwLock<Option<ValidatorExit>>>,
|
||||||
|
health: Arc<RpcHealth>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
JsonRpcRequestProcessor {
|
JsonRpcRequestProcessor {
|
||||||
config,
|
config,
|
||||||
@ -135,6 +138,7 @@ impl JsonRpcRequestProcessor {
|
|||||||
block_commitment_cache,
|
block_commitment_cache,
|
||||||
blockstore,
|
blockstore,
|
||||||
validator_exit,
|
validator_exit,
|
||||||
|
health,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1442,6 +1446,13 @@ impl RpcSol for RpcSolImpl {
|
|||||||
.into());
|
.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if meta.request_processor.read().unwrap().health.check() != RpcHealthStatus::Ok {
|
||||||
|
return Err(RpcCustomError::SendTransactionPreflightFailure {
|
||||||
|
message: "RPC node is unhealthy, unable to simulate transaction".into(),
|
||||||
|
}
|
||||||
|
.into());
|
||||||
|
}
|
||||||
|
|
||||||
let bank = &*meta.request_processor.read().unwrap().bank(None)?;
|
let bank = &*meta.request_processor.read().unwrap().bank(None)?;
|
||||||
if let Err(err) = run_transaction_simulation(&bank, &[transaction]) {
|
if let Err(err) = run_transaction_simulation(&bank, &[transaction]) {
|
||||||
// Note: it's possible that the transaction simulation failed but the actual
|
// Note: it's possible that the transaction simulation failed but the actual
|
||||||
@ -1832,6 +1843,7 @@ pub mod tests {
|
|||||||
block_commitment_cache.clone(),
|
block_commitment_cache.clone(),
|
||||||
blockstore,
|
blockstore,
|
||||||
validator_exit,
|
validator_exit,
|
||||||
|
RpcHealth::stub(),
|
||||||
)));
|
)));
|
||||||
let cluster_info = Arc::new(ClusterInfo::new_with_invalid_keypair(ContactInfo::default()));
|
let cluster_info = Arc::new(ClusterInfo::new_with_invalid_keypair(ContactInfo::default()));
|
||||||
|
|
||||||
@ -1880,6 +1892,7 @@ pub mod tests {
|
|||||||
block_commitment_cache,
|
block_commitment_cache,
|
||||||
blockstore,
|
blockstore,
|
||||||
validator_exit,
|
validator_exit,
|
||||||
|
RpcHealth::stub(),
|
||||||
);
|
);
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
let blockhash = bank.confirmed_last_blockhash().0;
|
let blockhash = bank.confirmed_last_blockhash().0;
|
||||||
@ -2824,6 +2837,7 @@ pub mod tests {
|
|||||||
block_commitment_cache,
|
block_commitment_cache,
|
||||||
blockstore,
|
blockstore,
|
||||||
validator_exit,
|
validator_exit,
|
||||||
|
RpcHealth::stub(),
|
||||||
);
|
);
|
||||||
Arc::new(RwLock::new(request_processor))
|
Arc::new(RwLock::new(request_processor))
|
||||||
},
|
},
|
||||||
@ -2894,7 +2908,9 @@ pub mod tests {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_validator_exit(exit: &Arc<AtomicBool>) -> Arc<RwLock<Option<ValidatorExit>>> {
|
pub(crate) fn create_validator_exit(
|
||||||
|
exit: &Arc<AtomicBool>,
|
||||||
|
) -> Arc<RwLock<Option<ValidatorExit>>> {
|
||||||
let mut validator_exit = ValidatorExit::default();
|
let mut validator_exit = ValidatorExit::default();
|
||||||
let exit_ = exit.clone();
|
let exit_ = exit.clone();
|
||||||
validator_exit.register_exit(Box::new(move || exit_.store(true, Ordering::Relaxed)));
|
validator_exit.register_exit(Box::new(move || exit_.store(true, Ordering::Relaxed)));
|
||||||
@ -2916,6 +2932,7 @@ pub mod tests {
|
|||||||
block_commitment_cache,
|
block_commitment_cache,
|
||||||
blockstore,
|
blockstore,
|
||||||
validator_exit,
|
validator_exit,
|
||||||
|
RpcHealth::stub(),
|
||||||
);
|
);
|
||||||
assert_eq!(request_processor.validator_exit(), Ok(false));
|
assert_eq!(request_processor.validator_exit(), Ok(false));
|
||||||
assert_eq!(exit.load(Ordering::Relaxed), false);
|
assert_eq!(exit.load(Ordering::Relaxed), false);
|
||||||
@ -2938,6 +2955,7 @@ pub mod tests {
|
|||||||
block_commitment_cache,
|
block_commitment_cache,
|
||||||
blockstore,
|
blockstore,
|
||||||
validator_exit,
|
validator_exit,
|
||||||
|
RpcHealth::stub(),
|
||||||
);
|
);
|
||||||
assert_eq!(request_processor.validator_exit(), Ok(true));
|
assert_eq!(request_processor.validator_exit(), Ok(true));
|
||||||
assert_eq!(exit.load(Ordering::Relaxed), true);
|
assert_eq!(exit.load(Ordering::Relaxed), true);
|
||||||
@ -3020,6 +3038,7 @@ pub mod tests {
|
|||||||
block_commitment_cache,
|
block_commitment_cache,
|
||||||
blockstore,
|
blockstore,
|
||||||
validator_exit,
|
validator_exit,
|
||||||
|
RpcHealth::stub(),
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
request_processor.get_block_commitment(0),
|
request_processor.get_block_commitment(0),
|
||||||
|
@ -6,6 +6,7 @@ use std::{
|
|||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[derive(PartialEq)]
|
||||||
pub enum RpcHealthStatus {
|
pub enum RpcHealthStatus {
|
||||||
Ok,
|
Ok,
|
||||||
Behind, // Validator is behind its trusted validators
|
Behind, // Validator is behind its trusted validators
|
||||||
@ -88,4 +89,16 @@ impl RpcHealth {
|
|||||||
RpcHealthStatus::Ok
|
RpcHealthStatus::Ok
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
pub(crate) fn stub() -> Arc<Self> {
|
||||||
|
Arc::new(Self::new(
|
||||||
|
Arc::new(ClusterInfo::new_with_invalid_keypair(
|
||||||
|
crate::contact_info::ContactInfo::default(),
|
||||||
|
)),
|
||||||
|
None,
|
||||||
|
42,
|
||||||
|
Arc::new(AtomicBool::new(false)),
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -255,6 +255,7 @@ impl JsonRpcService {
|
|||||||
block_commitment_cache,
|
block_commitment_cache,
|
||||||
blockstore,
|
blockstore,
|
||||||
validator_exit.clone(),
|
validator_exit.clone(),
|
||||||
|
health.clone(),
|
||||||
)));
|
)));
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -431,15 +432,12 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_is_file_get_path() {
|
fn test_is_file_get_path() {
|
||||||
let bank_forks = create_bank_forks();
|
let bank_forks = create_bank_forks();
|
||||||
let health = Arc::new(RpcHealth::new(
|
let rrm = RpcRequestMiddleware::new(
|
||||||
Arc::new(ClusterInfo::new_with_invalid_keypair(ContactInfo::default())),
|
PathBuf::from("/"),
|
||||||
None,
|
None,
|
||||||
42,
|
bank_forks.clone(),
|
||||||
Arc::new(AtomicBool::new(false)),
|
RpcHealth::stub(),
|
||||||
));
|
);
|
||||||
|
|
||||||
let rrm =
|
|
||||||
RpcRequestMiddleware::new(PathBuf::from("/"), None, bank_forks.clone(), health.clone());
|
|
||||||
let rrm_with_snapshot_config = RpcRequestMiddleware::new(
|
let rrm_with_snapshot_config = RpcRequestMiddleware::new(
|
||||||
PathBuf::from("/"),
|
PathBuf::from("/"),
|
||||||
Some(SnapshotConfig {
|
Some(SnapshotConfig {
|
||||||
@ -449,7 +447,7 @@ mod tests {
|
|||||||
compression: CompressionType::Bzip2,
|
compression: CompressionType::Bzip2,
|
||||||
}),
|
}),
|
||||||
bank_forks,
|
bank_forks,
|
||||||
health,
|
RpcHealth::stub(),
|
||||||
);
|
);
|
||||||
|
|
||||||
assert!(rrm.is_file_get_path("/genesis.tar.bz2"));
|
assert!(rrm.is_file_get_path("/genesis.tar.bz2"));
|
||||||
@ -475,14 +473,12 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_health_check_with_no_trusted_validators() {
|
fn test_health_check_with_no_trusted_validators() {
|
||||||
let health = Arc::new(RpcHealth::new(
|
let rm = RpcRequestMiddleware::new(
|
||||||
Arc::new(ClusterInfo::new_with_invalid_keypair(ContactInfo::default())),
|
PathBuf::from("/"),
|
||||||
None,
|
None,
|
||||||
42,
|
create_bank_forks(),
|
||||||
Arc::new(AtomicBool::new(false)),
|
RpcHealth::stub(),
|
||||||
));
|
);
|
||||||
|
|
||||||
let rm = RpcRequestMiddleware::new(PathBuf::from("/"), None, create_bank_forks(), health);
|
|
||||||
assert_eq!(rm.health_check(), "ok");
|
assert_eq!(rm.health_check(), "ok");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user