use tonic::transport::NamedService;
use log::warn;
use tower::Service;
#[derive(Debug, Clone)]
pub struct RpcWaitService<S> {
rpc_path: std::path::PathBuf,
inner: S,
}
impl<S> RpcWaitService<S> {
pub fn new(inner: S, rpc_path: std::path::PathBuf) -> Self {
RpcWaitService { rpc_path, inner }
}
}
impl<S> Service<hyper::Request<hyper::Body>> for RpcWaitService<S>
where
S: Service<hyper::Request<hyper::Body>, Response = hyper::Response<tonic::body::BoxBody>>
+ Clone
+ Send
+ 'static,
S::Future: Send + 'static,
{
type Response = S::Response;
type Error = S::Error;
type Future = futures::future::BoxFuture<'static, Result<Self::Response, Self::Error>>;
fn poll_ready(
&mut self,
cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Result<(), Self::Error>> {
self.inner.poll_ready(cx)
}
fn call(&mut self, request: hyper::Request<hyper::Body>) -> Self::Future {
let clone = self.inner.clone();
let mut inner = std::mem::replace(&mut self.inner, clone);
let path = self.rpc_path.clone();
Box::pin(async move {
let deadline = tokio::time::Instant::now() + tokio::time::Duration::from_secs(5);
loop {
if deadline < tokio::time::Instant::now() {
warn!("Deadline reached, letting the call fail");
break;
}
match path.metadata() {
Ok(_) => break,
Err(_) => tokio::time::sleep(tokio::time::Duration::from_millis(500)).await,
}
}
inner.call(request).await
})
}
}
impl<S> NamedService for RpcWaitService<S> {
const NAME: &'static str = "cln.Node";
}