"не может рекурсивно вызывать` Core` "при попытке достичь вложенного параллелизма с помощью Tokio - PullRequest
0 голосов
/ 01 июня 2018

Я создаю сервис, который периодически делает HTTP-запрос.Я использую tokio::timer::Delay в качестве периодического триггера и гиперссылки для выполнения HTTP-вызова.

Использование их вместе дает мне следующую ошибку:

thread 'tokio-runtime-worker-1' panicked at 'cannot recursively call into `Core`', libcore/option.rs:960:5

Как я могу заставить эту работу?

Ниже приведен упрощенный вариант услуги.

main.rs

extern crate futures;
extern crate hyper;
extern crate tokio;
extern crate tokio_core;
extern crate tokio_timer;

use futures::{Future, Stream};
use hyper::Client;
use tokio_core::reactor::Core;

use std::time::{Duration, Instant};
use tokio::timer::Delay;
use std::io::{self, Write};

fn main() {
    let when = Instant::now() + Duration::from_secs(1);

    tokio::run({
        Delay::new(when)
            .map_err(|e| panic!("timer failed; err={:?}", e))
            .and_then(move |_| {
                let mut core = Core::new().unwrap();
                let client = Client::new(&core.handle());

                let uri = "http://httpbin.org/ip".parse().unwrap();
                let work = client.get(uri).and_then(|res| {
                    println!("Response: {}", res.status());

                    res.body()
                        .for_each(|chunk| io::stdout().write_all(&chunk).map_err(From::from))
                });
                core.run(work).unwrap();
                Ok(())
            })
    })
}

Cargo.toml

[dependencies]
futures = "0.1"
hyper = "0.11"
tokio-core = "0.1"
tokio-timer = "0.1"
tokio = "0.1"
serde = "1.0.19"
serde_derive = "1.0.19"
serde_json = "1.0.19"
hyper-tls = "0.1.3"

1 Ответ

0 голосов
/ 01 июня 2018

Одна основная концептуальная проблема, которую я вижу, состоит в том, что вы не должны создавать произвольные Core s.Вы хотите поделиться ими как можно больше, потому что именно так Tokio обменивается данными между различными фьючерсами.

Создание единого ядра и использование его для HTTP-запроса и всей команды - правильная вещь.

гипер 0,11

гипер 0,11 не совместим с ящиком Токио .Вместо этого вам нужно использовать составляющие Tokio:

extern crate futures;
extern crate hyper;
extern crate tokio_core;
extern crate tokio_timer;

use futures::{Future, Stream};
use hyper::Client;
use std::{
    io::{self, Write}, time::{Duration, Instant},
};
use tokio_core::reactor::Core;
use tokio_timer::Delay;

fn main() {
    let when = Instant::now() + Duration::from_secs(1);

    let mut core = Core::new().expect("Could not achieve criticality");
    let handle = core.handle();

    let command = Delay::new(when)
        .map_err(|e| panic!("timer failed; err={:?}", e))
        .and_then(move |_| {
            let client = Client::new(&handle);

            let uri = "http://httpbin.org/ip".parse().unwrap();
            client.get(uri).and_then(|res| {
                println!("Response: {}", res.status());

                res.body()
                    .for_each(|chunk| io::stdout().write_all(&chunk).map_err(From::from))
            })
        });

    core.run(command).expect("Meltdown occurred");
}
[dependencies]
futures = "0.1"
hyper = "0.11.27"
tokio-core = "0.1.17"
tokio-timer = "0.2.3"

гипер 0,12

При использовании гипер 0,12 это выглядит так:

extern crate hyper;
extern crate tokio;

use hyper::Client;
use std::{
    error::Error, io::{self, Write}, time::{Duration, Instant},
};
use tokio::{
    prelude::{Future, Stream}, timer::Delay,
};

type MyError = Box<Error + Send + Sync>;

fn main() {
    let when = Instant::now() + Duration::from_secs(1);

    let command = Delay::new(when).from_err::<MyError>().and_then(move |_| {
        let client = Client::new();

        let uri = "http://httpbin.org/ip".parse().unwrap();
        client.get(uri).from_err::<MyError>().and_then(|res| {
            println!("Response: {}", res.status());

            res.into_body()
                .from_err::<MyError>()
                .for_each(|chunk| io::stdout().write_all(&chunk).map_err(From::from))
        })
    });

    tokio::run(command.map_err(|e| panic!("Error: {}", e)));
}
[dependencies]
hyper = "0.12.0"
tokio = "0.1.6"
...