I am using this library to implement a jsonrpc server: https://github.com/paritytech/jsonrpc. There is a way to implement a trait and use it as middleware for the server. The function in the trait looks like:
fn on_request<F, X>(&self, request: Request, meta: M, next: F) -> Either<Self::Future, X>
where
F: Fn(Request, M) -> X + Send + Sync,
X: Future<Output = Option<Response>> + Send + 'static,
{
}
In this function I can return a Future for a response immediately, or I can call the "next" Fn to move on to the next layer of the server. I would like the decision of responding in the middleware vs. sending it to the next layer to be an decided asynchronously.
I have done this (simpified for this question):
pub struct SampleMiddleware;
impl Middleware<Meta> for SampleMiddleware {
type Future = FutureResponse;
type CallFuture = middleware::NoopCallFuture;
fn on_request<F, X>(&self, request: Request, meta: Meta, next: F) -> Either<Self::Future, X>
where
F: FnOnce(Request, Meta) -> X + Send,
X: Future<Output = Option<Response>> + Send + 'static,
{
Either::Left(Box::pin(SampleMiddleware::process_async(request, meta, next)))
}
}
impl SampleMiddleware {
async fn process_async<F, X>(req: Request, meta: Meta, next: F) -> Option<Response>
where
F: FnOnce(Request, Meta) -> X + Send,
X: Future<Output = Option<Response>> + Send + 'static,
{
let result = SampleMiddleware::async_fn(&req, &meta).await;
match result {
Some(r) => {
Some(r)
},
None => {
next(req, meta).await
}
}
}
async fn async_fn(req: &Request, meta: &Meta) -> Option<Response>
{
return None
}
}
However on this line:Either::Left(Box::pin(SampleMiddleware::process_async(request, meta, next)))
I get this error from the compiler:
the parameter type `F` may not live long enough
...so that the type `impl futures::Future<Output = std::option::Option<jsonrpc_core::Response>>` will meet its required lifetime bounds
consider adding an explicit lifetime bound...: `F: 'static`
I don't think I can change the lifetime bound to F because that comes from the trait I don't control.
I am pretty new to Rust and haven't quite wrapped my head around how to use lifetimes. I think this question might boil down to how I can call a FnOnce in another thread, but not sure.