Rename RpcNodeUnhealthy error to NodeUnhealthy, generalize getHealth RPC error object for the future (#14656)
				
					
				
			(cherry picked from commit 5d9dc609b1)
Co-authored-by: Michael Vines <mvines@gmail.com>
			
			
This commit is contained in:
		| @@ -86,8 +86,8 @@ impl RpcSender for HttpSender { | |||||||
|                                         } |                                         } | ||||||
|                                     }, |                                     }, | ||||||
|                                     rpc_custom_error::JSON_RPC_SERVER_ERROR_NODE_UNHEALTHLY => { |                                     rpc_custom_error::JSON_RPC_SERVER_ERROR_NODE_UNHEALTHLY => { | ||||||
|                                         match serde_json::from_value::<rpc_custom_error::RpcNodeUnhealthyErrorData>(json["error"]["data"].clone()) { |                                         match serde_json::from_value::<rpc_custom_error::NodeUnhealthyErrorData>(json["error"]["data"].clone()) { | ||||||
|                                             Ok(rpc_custom_error::RpcNodeUnhealthyErrorData { num_slots_behind}) => RpcResponseErrorData::NodeUnhealthy {num_slots_behind}, |                                             Ok(rpc_custom_error::NodeUnhealthyErrorData {num_slots_behind}) => RpcResponseErrorData::NodeUnhealthy {num_slots_behind}, | ||||||
|                                             Err(_err) => { |                                             Err(_err) => { | ||||||
|                                                 RpcResponseErrorData::Empty |                                                 RpcResponseErrorData::Empty | ||||||
|                                             } |                                             } | ||||||
|   | |||||||
| @@ -26,8 +26,8 @@ pub enum RpcCustomError { | |||||||
|     BlockNotAvailable { |     BlockNotAvailable { | ||||||
|         slot: Slot, |         slot: Slot, | ||||||
|     }, |     }, | ||||||
|     RpcNodeUnhealthy { |     NodeUnhealthy { | ||||||
|         num_slots_behind: Slot, |         num_slots_behind: Option<Slot>, | ||||||
|     }, |     }, | ||||||
|     TransactionPrecompileVerificationFailure(solana_sdk::transaction::TransactionError), |     TransactionPrecompileVerificationFailure(solana_sdk::transaction::TransactionError), | ||||||
|     SlotSkipped { |     SlotSkipped { | ||||||
| @@ -38,8 +38,8 @@ pub enum RpcCustomError { | |||||||
|  |  | ||||||
| #[derive(Debug, Serialize, Deserialize)] | #[derive(Debug, Serialize, Deserialize)] | ||||||
| #[serde(rename_all = "camelCase")] | #[serde(rename_all = "camelCase")] | ||||||
| pub struct RpcNodeUnhealthyErrorData { | pub struct NodeUnhealthyErrorData { | ||||||
|     pub num_slots_behind: Slot, |     pub num_slots_behind: Option<Slot>, | ||||||
| } | } | ||||||
|  |  | ||||||
| impl From<RpcCustomError> for Error { | impl From<RpcCustomError> for Error { | ||||||
| @@ -75,10 +75,14 @@ impl From<RpcCustomError> for Error { | |||||||
|                 message: format!("Block not available for slot {}", slot), |                 message: format!("Block not available for slot {}", slot), | ||||||
|                 data: None, |                 data: None, | ||||||
|             }, |             }, | ||||||
|             RpcCustomError::RpcNodeUnhealthy { num_slots_behind } => Self { |             RpcCustomError::NodeUnhealthy { num_slots_behind } => Self { | ||||||
|                 code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_NODE_UNHEALTHLY), |                 code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_NODE_UNHEALTHLY), | ||||||
|                 message: format!("RPC node is behind by {} slots", num_slots_behind), |                 message: if let Some(num_slots_behind) = num_slots_behind { | ||||||
|                 data: Some(serde_json::json!(RpcNodeUnhealthyErrorData { |                     format!("Node is behind by {} slots", num_slots_behind) | ||||||
|  |                 } else { | ||||||
|  |                     "Node is unhealthy".to_string() | ||||||
|  |                 }, | ||||||
|  |                 data: Some(serde_json::json!(NodeUnhealthyErrorData { | ||||||
|                     num_slots_behind |                     num_slots_behind | ||||||
|                 })), |                 })), | ||||||
|             }, |             }, | ||||||
|   | |||||||
| @@ -147,7 +147,7 @@ impl RpcRequest { | |||||||
| pub enum RpcResponseErrorData { | pub enum RpcResponseErrorData { | ||||||
|     Empty, |     Empty, | ||||||
|     SendTransactionPreflightFailure(RpcSimulateTransactionResult), |     SendTransactionPreflightFailure(RpcSimulateTransactionResult), | ||||||
|     NodeUnhealthy { num_slots_behind: Slot }, |     NodeUnhealthy { num_slots_behind: Option<Slot> }, | ||||||
| } | } | ||||||
|  |  | ||||||
| impl fmt::Display for RpcResponseErrorData { | impl fmt::Display for RpcResponseErrorData { | ||||||
|   | |||||||
| @@ -2265,9 +2265,10 @@ impl RpcSol for RpcSolImpl { | |||||||
|     fn get_health(&self, meta: Self::Metadata) -> Result<String> { |     fn get_health(&self, meta: Self::Metadata) -> Result<String> { | ||||||
|         match meta.health.check() { |         match meta.health.check() { | ||||||
|             RpcHealthStatus::Ok => Ok("ok".to_string()), |             RpcHealthStatus::Ok => Ok("ok".to_string()), | ||||||
|             RpcHealthStatus::Behind { |             RpcHealthStatus::Behind { num_slots } => Err(RpcCustomError::NodeUnhealthy { | ||||||
|                 num_slots: num_slots_behind, |                 num_slots_behind: Some(num_slots), | ||||||
|             } => Err(RpcCustomError::RpcNodeUnhealthy { num_slots_behind }.into()), |             } | ||||||
|  |             .into()), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -2523,10 +2524,11 @@ impl RpcSol for RpcSolImpl { | |||||||
|  |  | ||||||
|             match meta.health.check() { |             match meta.health.check() { | ||||||
|                 RpcHealthStatus::Ok => (), |                 RpcHealthStatus::Ok => (), | ||||||
|                 RpcHealthStatus::Behind { |                 RpcHealthStatus::Behind { num_slots } => { | ||||||
|                     num_slots: num_slots_behind, |                     return Err(RpcCustomError::NodeUnhealthy { | ||||||
|                 } => { |                         num_slots_behind: Some(num_slots), | ||||||
|                     return Err(RpcCustomError::RpcNodeUnhealthy { num_slots_behind }.into()); |                     } | ||||||
|  |                     .into()); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |  | ||||||
| @@ -4570,7 +4572,7 @@ pub mod tests { | |||||||
|         assert_eq!( |         assert_eq!( | ||||||
|             res, |             res, | ||||||
|             Some( |             Some( | ||||||
|                 r#"{"jsonrpc":"2.0","error":{"code":-32005,"message":"RPC node is behind by 42 slots","data":{"numSlotsBehind":42}},"id":1}"#.to_string(), |                 r#"{"jsonrpc":"2.0","error":{"code":-32005,"message":"Node is behind by 42 slots","data":{"numSlotsBehind":42}},"id":1}"#.to_string(), | ||||||
|             ) |             ) | ||||||
|         ); |         ); | ||||||
|         health.stub_set_health_status(None); |         health.stub_set_health_status(None); | ||||||
|   | |||||||
| @@ -1294,7 +1294,9 @@ None | |||||||
| #### Results: | #### Results: | ||||||
|  |  | ||||||
| If the node is healthy: "ok" | If the node is healthy: "ok" | ||||||
| If the node is unhealthy, a JSON RPC error response is returned indicating how far behind the node is. | If the node is unhealthy, a JSON RPC error response is returned.  The specifics | ||||||
|  | of the error response are **UNSTABLE** and may change in the future | ||||||
|  |  | ||||||
|  |  | ||||||
| #### Example: | #### Example: | ||||||
|  |  | ||||||
| @@ -1310,13 +1312,26 @@ Healthy Result: | |||||||
| {"jsonrpc":"2.0","result": "ok","id":1} | {"jsonrpc":"2.0","result": "ok","id":1} | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| Unhealthy Result: | Unhealthy Result (generic): | ||||||
| ```json | ```json | ||||||
| { | { | ||||||
|   "jsonrpc": "2.0", |   "jsonrpc": "2.0", | ||||||
|   "error": { |   "error": { | ||||||
|     "code": -32005, |     "code": -32005, | ||||||
|     "message": "RPC node is behind by 42 slots", |     "message": "Node is unhealthy", | ||||||
|  |     "data": {} | ||||||
|  |   }, | ||||||
|  |   "id": 1 | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Unhealthy Result (if additional information is available) | ||||||
|  | ```json | ||||||
|  | { | ||||||
|  |   "jsonrpc": "2.0", | ||||||
|  |   "error": { | ||||||
|  |     "code": -32005, | ||||||
|  |     "message": "Node is behind by 42 slots", | ||||||
|     "data": { |     "data": { | ||||||
|       "numSlotsBehind": 42 |       "numSlotsBehind": 42 | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -358,7 +358,9 @@ fn main() { | |||||||
|                             code: _, |                             code: _, | ||||||
|                             message: _, |                             message: _, | ||||||
|                             data: |                             data: | ||||||
|                                 rpc_request::RpcResponseErrorData::NodeUnhealthy { num_slots_behind }, |                                 rpc_request::RpcResponseErrorData::NodeUnhealthy { | ||||||
|  |                                     num_slots_behind: Some(num_slots_behind), | ||||||
|  |                                 }, | ||||||
|                         }, |                         }, | ||||||
|                     ) = &err.kind |                     ) = &err.kind | ||||||
|                     { |                     { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user