mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-25 21:11:07 +00:00
Changed how relay loops are started (#840)
* slightly changed relay loop initialization * git mv * clippy * more clippy * loop_run -> run_loop * review and clippy * clippy
This commit is contained in:
committed by
Bastian Köcher
parent
8d122b03f1
commit
a17c7eb80c
@@ -14,10 +14,12 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::metrics::{Metrics, MetricsParams, StandaloneMetrics};
|
||||
use crate::{FailedClient, MaybeConnectionError};
|
||||
|
||||
use async_trait::async_trait;
|
||||
use std::{fmt::Debug, future::Future, time::Duration};
|
||||
use std::{fmt::Debug, future::Future, net::SocketAddr, time::Duration};
|
||||
use substrate_prometheus_endpoint::{init_prometheus, Registry};
|
||||
|
||||
/// Default pause between reconnect attempts.
|
||||
pub const RECONNECT_DELAY: Duration = Duration::from_secs(10);
|
||||
@@ -32,60 +34,164 @@ pub trait Client: Clone + Send + Sync {
|
||||
async fn reconnect(&mut self) -> Result<(), Self::Error>;
|
||||
}
|
||||
|
||||
/// Run relay loop.
|
||||
///
|
||||
/// This function represents an outer loop, which in turn calls provided `loop_run` function to do
|
||||
/// actual job. When `loop_run` returns, this outer loop reconnects to failed client (source,
|
||||
/// target or both) and calls `loop_run` again.
|
||||
pub async fn run<SC: Client, TC: Client, R, F>(
|
||||
reconnect_delay: Duration,
|
||||
mut source_client: SC,
|
||||
mut target_client: TC,
|
||||
loop_run: R,
|
||||
) where
|
||||
R: Fn(SC, TC) -> F,
|
||||
F: Future<Output = Result<(), FailedClient>>,
|
||||
{
|
||||
loop {
|
||||
let result = loop_run(source_client.clone(), target_client.clone()).await;
|
||||
|
||||
match result {
|
||||
Ok(()) => break,
|
||||
Err(failed_client) => loop {
|
||||
async_std::task::sleep(reconnect_delay).await;
|
||||
if failed_client == FailedClient::Both || failed_client == FailedClient::Source {
|
||||
match source_client.reconnect().await {
|
||||
Ok(()) => (),
|
||||
Err(error) => {
|
||||
log::warn!(
|
||||
target: "bridge",
|
||||
"Failed to reconnect to source client. Going to retry in {}s: {:?}",
|
||||
reconnect_delay.as_secs(),
|
||||
error,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
if failed_client == FailedClient::Both || failed_client == FailedClient::Target {
|
||||
match target_client.reconnect().await {
|
||||
Ok(()) => (),
|
||||
Err(error) => {
|
||||
log::warn!(
|
||||
target: "bridge",
|
||||
"Failed to reconnect to target client. Going to retry in {}s: {:?}",
|
||||
reconnect_delay.as_secs(),
|
||||
error,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
},
|
||||
}
|
||||
|
||||
log::debug!(target: "bridge", "Restarting relay loop");
|
||||
/// Returns generic loop that may be customized and started.
|
||||
pub fn relay_loop<SC, TC>(source_client: SC, target_client: TC) -> Loop<SC, TC, ()> {
|
||||
Loop {
|
||||
source_client,
|
||||
target_client,
|
||||
loop_metric: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Generic relay loop.
|
||||
pub struct Loop<SC, TC, LM> {
|
||||
source_client: SC,
|
||||
target_client: TC,
|
||||
loop_metric: Option<LM>,
|
||||
}
|
||||
|
||||
/// Relay loop metrics builder.
|
||||
pub struct LoopMetrics<SC, TC, LM> {
|
||||
relay_loop: Loop<SC, TC, ()>,
|
||||
registry: Registry,
|
||||
loop_metric: Option<LM>,
|
||||
}
|
||||
|
||||
impl<SC, TC, LM> Loop<SC, TC, LM> {
|
||||
/// Start building loop metrics using given prefix.
|
||||
///
|
||||
/// Panics if `prefix` is empty.
|
||||
pub fn with_metrics(self, prefix: String) -> LoopMetrics<SC, TC, ()> {
|
||||
assert!(!prefix.is_empty(), "Metrics prefix can not be empty");
|
||||
|
||||
LoopMetrics {
|
||||
relay_loop: Loop {
|
||||
source_client: self.source_client,
|
||||
target_client: self.target_client,
|
||||
loop_metric: None,
|
||||
},
|
||||
registry: Registry::new_custom(Some(prefix), None)
|
||||
.expect("only fails if prefix is empty; prefix is not empty; qed"),
|
||||
loop_metric: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Run relay loop.
|
||||
///
|
||||
/// This function represents an outer loop, which in turn calls provided `run_loop` function to do
|
||||
/// actual job. When `run_loop` returns, this outer loop reconnects to failed client (source,
|
||||
/// target or both) and calls `run_loop` again.
|
||||
pub async fn run<R, F>(mut self, run_loop: R) -> Result<(), String>
|
||||
where
|
||||
R: Fn(SC, TC, Option<LM>) -> F,
|
||||
F: Future<Output = Result<(), FailedClient>>,
|
||||
SC: Client,
|
||||
TC: Client,
|
||||
LM: Clone,
|
||||
{
|
||||
loop {
|
||||
let result = run_loop(
|
||||
self.source_client.clone(),
|
||||
self.target_client.clone(),
|
||||
self.loop_metric.clone(),
|
||||
)
|
||||
.await;
|
||||
|
||||
match result {
|
||||
Ok(()) => break,
|
||||
Err(failed_client) => loop {
|
||||
async_std::task::sleep(RECONNECT_DELAY).await;
|
||||
if failed_client == FailedClient::Both || failed_client == FailedClient::Source {
|
||||
match self.source_client.reconnect().await {
|
||||
Ok(()) => (),
|
||||
Err(error) => {
|
||||
log::warn!(
|
||||
target: "bridge",
|
||||
"Failed to reconnect to source client. Going to retry in {}s: {:?}",
|
||||
RECONNECT_DELAY.as_secs(),
|
||||
error,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
if failed_client == FailedClient::Both || failed_client == FailedClient::Target {
|
||||
match self.target_client.reconnect().await {
|
||||
Ok(()) => (),
|
||||
Err(error) => {
|
||||
log::warn!(
|
||||
target: "bridge",
|
||||
"Failed to reconnect to target client. Going to retry in {}s: {:?}",
|
||||
RECONNECT_DELAY.as_secs(),
|
||||
error,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
},
|
||||
}
|
||||
|
||||
log::debug!(target: "bridge", "Restarting relay loop");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<SC, TC, LM> LoopMetrics<SC, TC, LM> {
|
||||
/// Add relay loop metrics.
|
||||
///
|
||||
/// Loop metrics will be passed to the loop callback.
|
||||
pub fn loop_metric<NewLM: Metrics>(self, loop_metric: NewLM) -> Result<LoopMetrics<SC, TC, NewLM>, String> {
|
||||
loop_metric.register(&self.registry)?;
|
||||
|
||||
Ok(LoopMetrics {
|
||||
relay_loop: self.relay_loop,
|
||||
registry: self.registry,
|
||||
loop_metric: Some(loop_metric),
|
||||
})
|
||||
}
|
||||
|
||||
/// Add standalone metrics.
|
||||
pub fn standalone_metric<M: StandaloneMetrics>(self, standalone_metrics: M) -> Result<Self, String> {
|
||||
standalone_metrics.register(&self.registry)?;
|
||||
standalone_metrics.spawn();
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Expose metrics using given params.
|
||||
///
|
||||
/// If `params` is `None`, metrics are not exposed.
|
||||
pub async fn expose(self, params: Option<MetricsParams>) -> Result<Loop<SC, TC, LM>, String> {
|
||||
if let Some(params) = params {
|
||||
let socket_addr = SocketAddr::new(
|
||||
params.host.parse().map_err(|err| {
|
||||
format!(
|
||||
"Invalid host {} is used to expose Prometheus metrics: {}",
|
||||
params.host, err,
|
||||
)
|
||||
})?,
|
||||
params.port,
|
||||
);
|
||||
|
||||
let registry = self.registry;
|
||||
async_std::task::spawn(async move {
|
||||
let result = init_prometheus(socket_addr, registry).await;
|
||||
log::trace!(
|
||||
target: "bridge-metrics",
|
||||
"Prometheus endpoint has exited with result: {:?}",
|
||||
result,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Ok(Loop {
|
||||
source_client: self.relay_loop.source_client,
|
||||
target_client: self.relay_loop.target_client,
|
||||
loop_metric: self.loop_metric,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user