Какой тип подходит для blocker
в следующей функции?
fn f(blocker: ???) {
let future1: impl Future<Output = T1> = ...
let future2: impl Future<Output = T2> = ...
let value1: T1 = blocker.block_on(future1);
let value2: T2 = blocker.block_on(future2);
...
}
Я использую juniper для сервера GraphQL, у которого нет asyn c интерфейс на данный момент, поэтому он требует, чтобы мои обработчики возвращали значения синхронно.
В моих обработчиках я вызываю асин c библиотеки (например, rusoto и reqwest ), которые возвращают std::future::Future
.
Каждый обработчик принимает параметр контекста, поэтому в моей структуре контекста я могу включить tokio_compat::runtime::Runtime
(из tokio-compat ), что мои обработчики затем используйте для блокировки любого из этих фьючерсов с runtime.block_on_std(future)
.
Но как мне абстрагироваться над block_on_std
самой? Как передать функцию, которая при любом будущем типа F
возвращает F::Output
? Есть ли синтаксис для типа аргумента, ограниченный «для всех типов F, реализующих черту Future»?
После того, как я не смог найти способ express тип функции этой формы, я попытался вместо этого с trait:
pub trait Blocker {
fn block_on_std<F: std::future::Future>(&self, future: F) -> F::Output;
}
и реализация Tokio-compat:
pub struct TokioCompatBlocker {
rt: std::sync::Mutex<tokio_compat::runtime::current_thread::Runtime>,
}
impl Blocker for TokioCompatBlocker {
fn block_on_std<F: std::future::Future>(&self, future: F) -> <F as Future>::Output {
self
.rt
.lock()
.expect("failed to lock rt")
.block_on_std(future)
}
}
, но добавление его в структуру сталкивается с ограничениями объекта trait:
pub struct Context {
pub blocker: Box<dyn Blocker>,
// more fields...
}
impl Context {
pub fn new(blocker: Box<dyn Blocker>) -> Context {
Context { blocker, /* more fields... */ }
}
}
--> .../example.rs:
|
| fn block_on_std<F: std::future::Future>(&self, future: F) -> F::Output;
| ------------ method `block_on_std` has generic type parameters
...
| pub blocker: Box<dyn Blocker>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `schema::Blocker` cannot be made into an object
Каков был бы подходящий способ абстрагироваться над функцией, такой как block_on_std?