Новая зависимость Tokio + от старшего гипер - PullRequest
0 голосов
/ 30 января 2020

Я использую Tokio 0.2.x, но мне нужно использовать зависимость, которая зависит от гипер 0.12.35.

Это приводит к SpawnError { is_shutdown: true } панике.

Мне удалось воспроизвести это изолированно:

машина go .toml

[dependencies]
tokio = { version = "0.2.11", features = ["full"] }
hyper = "0.12.35"
futures = "0.1.29"

и это код:

use hyper::rt;
use futures::future as future01;

fn future_01() -> impl future01::Future<Item = (), Error = ()> {
    future01::ok(())
}

#[tokio::main]
async fn main() -> Result<(), std::io::Error> {
    rt::spawn(future_01());
    Ok(())
}

Моя зависимость имеет это rt::spawn глубоко в реализации, так что я не могу изменить это.

В идеале я бы хотел установить исполнителя по умолчанию, используемого rt::spawn, таким же, как тот, который предоставляет tokio::main. Это возможно?

1 Ответ

2 голосов
/ 30 января 2020

В идеале я бы хотел установить исполнителя по умолчанию, используемого rt::spawn, таким же, как тот, который предоставляет tokio::main. Это возможно?

Невозможно, tokio = "0.2.11" может порождать задачи, только если они реализуют std::future::Future, вы не можете создавать эти задачи с помощью futures = "0.1.29", для чего вам нужно используйте версию 0.3.x или вам нужно использовать функцию compat для преобразования старого фьючерса в новый ( подробности см. в разделе «Вопросы и ответы» OP ).

Этот результат в SpawnError { is_shutdown: true } паникует.

Используемый вами Hyper использует внутреннюю среду исполнения Tokio, которая является более старой версией Tokio (она также имеется в вашей Cargo.lock с более новой версией). В Tokio невозможно порождать задачи без инициализированной среды выполнения, поэтому вам нужно создавать свою задачу следующим образом:

fn main() -> Result<(), std::io::Error> {
    rt::run(future_01());
    Ok(())
}

Предупреждение:

Если вы все еще хотите использовать две разные среды выполнения, одну из новой и другую из старой версии, не используйте ее, как показано ниже! Вам нужно будет запустить их в отдельных потоках.

//don't use this code!
#[tokio::main]
async fn main() -> Result<(), std::io::Error> {
    rt::run(future_01());
    Ok(())
}

Поскольку main является асинхронным c и rt::run является блокирующей функцией (, почему не следует вызывать долго выполняющийся код внутри асинхронного c fn )

...