mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-06 10:11:44 +00:00
Simplify error handling after engines fallback removal (#3283)
## Issue Addressed Part of #3118, continuation of #3257 ## Proposed Changes - the [ `first_success_without_retry` ](9c429d0764/beacon_node/execution_layer/src/engines.rs (L348-L351)) function returns a single error. - the [`first_success`](9c429d0764/beacon_node/execution_layer/src/engines.rs (L324)) function returns a single error. - [ `EngineErrors` ](9c429d0764/beacon_node/execution_layer/src/lib.rs (L69)) carries a single error. - [`EngineError`](9c429d0764/beacon_node/execution_layer/src/engines.rs (L173-L177)) now does not need to carry an Id - [`process_multiple_payload_statuses`](9c429d0764/beacon_node/execution_layer/src/payload_status.rs (L46-L50)) now doesn't need to receive an iterator of statuses and weight in different errors ## Additional Info This is built on top of #3294
This commit is contained in:
@@ -57,7 +57,6 @@ struct PayloadIdCacheKey {
|
||||
|
||||
/// An execution engine.
|
||||
pub struct Engine<T> {
|
||||
pub id: String,
|
||||
pub api: HttpJsonRpc<T>,
|
||||
payload_id_cache: Mutex<LruCache<PayloadIdCacheKey, PayloadId>>,
|
||||
state: RwLock<EngineState>,
|
||||
@@ -65,9 +64,8 @@ pub struct Engine<T> {
|
||||
|
||||
impl<T> Engine<T> {
|
||||
/// Creates a new, offline engine.
|
||||
pub fn new(id: String, api: HttpJsonRpc<T>) -> Self {
|
||||
pub fn new(api: HttpJsonRpc<T>) -> Self {
|
||||
Self {
|
||||
id,
|
||||
api,
|
||||
payload_id_cache: Mutex::new(LruCache::new(PAYLOAD_ID_LRU_CACHE_SIZE)),
|
||||
state: RwLock::new(EngineState::Offline),
|
||||
@@ -135,10 +133,10 @@ pub struct Engines {
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum EngineError {
|
||||
Offline { id: String },
|
||||
Api { id: String, error: EngineApiError },
|
||||
Offline,
|
||||
Api { error: EngineApiError },
|
||||
BuilderApi { error: EngineApiError },
|
||||
Auth { id: String },
|
||||
Auth,
|
||||
}
|
||||
|
||||
impl Engines {
|
||||
@@ -159,7 +157,6 @@ impl Engines {
|
||||
self.log,
|
||||
"No need to call forkchoiceUpdated";
|
||||
"msg" => "head does not have execution enabled",
|
||||
"id" => &self.engine.id,
|
||||
);
|
||||
return;
|
||||
}
|
||||
@@ -168,7 +165,6 @@ impl Engines {
|
||||
self.log,
|
||||
"Issuing forkchoiceUpdated";
|
||||
"forkchoice_state" => ?forkchoice_state,
|
||||
"id" => &self.engine.id,
|
||||
);
|
||||
|
||||
// For simplicity, payload attributes are never included in this call. It may be
|
||||
@@ -183,14 +179,12 @@ impl Engines {
|
||||
self.log,
|
||||
"Failed to issue latest head to engine";
|
||||
"error" => ?e,
|
||||
"id" => &self.engine.id,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
debug!(
|
||||
self.log,
|
||||
"No head, not sending to engine";
|
||||
"id" => &self.engine.id,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -261,45 +255,36 @@ impl Engines {
|
||||
}
|
||||
}
|
||||
|
||||
/// Run `func` on all engines, in the order in which they are defined, returning the first
|
||||
/// successful result that is found.
|
||||
/// Run `func` on the node.
|
||||
///
|
||||
/// This function might try to run `func` twice. If all nodes return an error on the first time
|
||||
/// it runs, it will try to upcheck all offline nodes and then run the function again.
|
||||
pub async fn first_success<'a, F, G, H>(&'a self, func: F) -> Result<H, Vec<EngineError>>
|
||||
/// This function might try to run `func` twice. If the node returns an error it will try to
|
||||
/// upcheck it and then run the function again.
|
||||
pub async fn first_success<'a, F, G, H>(&'a self, func: F) -> Result<H, EngineError>
|
||||
where
|
||||
F: Fn(&'a Engine<EngineApi>) -> G + Copy,
|
||||
G: Future<Output = Result<H, EngineApiError>>,
|
||||
{
|
||||
match self.first_success_without_retry(func).await {
|
||||
Ok(result) => Ok(result),
|
||||
Err(mut first_errors) => {
|
||||
// Try to recover some nodes.
|
||||
Err(e) => {
|
||||
debug!(self.log, "First engine call failed. Retrying"; "err" => ?e);
|
||||
// Try to recover the node.
|
||||
self.upcheck_not_synced(Logging::Enabled).await;
|
||||
// Retry the call on all nodes.
|
||||
match self.first_success_without_retry(func).await {
|
||||
Ok(result) => Ok(result),
|
||||
Err(second_errors) => {
|
||||
first_errors.extend(second_errors);
|
||||
Err(first_errors)
|
||||
}
|
||||
}
|
||||
// Try again.
|
||||
self.first_success_without_retry(func).await
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Run `func` on all engines, in the order in which they are defined, returning the first
|
||||
/// successful result that is found.
|
||||
/// Run `func` on the node.
|
||||
pub async fn first_success_without_retry<'a, F, G, H>(
|
||||
&'a self,
|
||||
func: F,
|
||||
) -> Result<H, Vec<EngineError>>
|
||||
) -> Result<H, EngineError>
|
||||
where
|
||||
F: Fn(&'a Engine<EngineApi>) -> G,
|
||||
G: Future<Output = Result<H, EngineApiError>>,
|
||||
{
|
||||
let mut errors = vec![];
|
||||
|
||||
let (engine_synced, engine_auth_failed) = {
|
||||
let state = self.engine.state.read().await;
|
||||
(
|
||||
@@ -309,32 +294,22 @@ impl Engines {
|
||||
};
|
||||
if engine_synced {
|
||||
match func(&self.engine).await {
|
||||
Ok(result) => return Ok(result),
|
||||
Ok(result) => Ok(result),
|
||||
Err(error) => {
|
||||
debug!(
|
||||
self.log,
|
||||
"Execution engine call failed";
|
||||
"error" => ?error,
|
||||
"id" => &&self.engine.id
|
||||
);
|
||||
*self.engine.state.write().await = EngineState::Offline;
|
||||
errors.push(EngineError::Api {
|
||||
id: self.engine.id.clone(),
|
||||
error,
|
||||
})
|
||||
Err(EngineError::Api { error })
|
||||
}
|
||||
}
|
||||
} else if engine_auth_failed {
|
||||
errors.push(EngineError::Auth {
|
||||
id: self.engine.id.clone(),
|
||||
})
|
||||
Err(EngineError::Auth)
|
||||
} else {
|
||||
errors.push(EngineError::Offline {
|
||||
id: self.engine.id.clone(),
|
||||
})
|
||||
Err(EngineError::Offline)
|
||||
}
|
||||
|
||||
Err(errors)
|
||||
}
|
||||
|
||||
/// Runs `func` on the node.
|
||||
@@ -363,9 +338,7 @@ impl Engines {
|
||||
{
|
||||
let func = &func;
|
||||
if *self.engine.state.read().await == EngineState::Offline {
|
||||
Err(EngineError::Offline {
|
||||
id: self.engine.id.clone(),
|
||||
})
|
||||
Err(EngineError::Offline)
|
||||
} else {
|
||||
match func(&self.engine).await {
|
||||
Ok(res) => Ok(res),
|
||||
@@ -376,10 +349,7 @@ impl Engines {
|
||||
"error" => ?error,
|
||||
);
|
||||
*self.engine.state.write().await = EngineState::Offline;
|
||||
Err(EngineError::Api {
|
||||
id: self.engine.id.clone(),
|
||||
error,
|
||||
})
|
||||
Err(EngineError::Api { error })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user