Абстракция над Tokio block_on_std для фьючерсов на Rust std - PullRequest
0 голосов
/ 29 марта 2020

Какой тип подходит для 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?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...