0

I am learning Tokio/futures and can't find a way to return the error up to the caller in the main function; is this possible?

My use case is for AWS Lambda with the runtime being synchronous and would like to return any errors from the async parts.

use futures::Future; // 0.1.26
use reqwest::r#async::Client; // 0.9.14
use reqwest::Error; // 0.1.18
use serde::Deserialize;
use tokio;

fn main() {
    let call = synchronous_function();
    if let Err(e) = call {
        println!("{:?}", e);
    }
}

fn synchronous_function() -> Result<(), Error> {
    let fut = async_function()
        .and_then(|res| {
            println!("{:?}", res);
            Ok(())
        })
        .map_err(|_| ());

    tokio::run(fut);
    Ok(())
}

fn async_function() -> impl Future<Item = Json, Error = Error> {
    let client = Client::new();
    client
        .get("https://jsonplaceholder.typicode.com/todos/1")
        .send()
        .map_err(Into::into)
        .and_then(|mut res| res.json().and_then(|j| Ok(j)))
}

#[derive(Debug, Deserialize)]
struct Json {
    userId: u16,
    id: u16,
    title: String,
    completed: bool,
}
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
James
  • 693
  • 1
  • 13
  • 27

1 Answers1

0

If you want to "return" something from tokio::run, you can use a communications channel that will transport your result back to the main thread, like so:

fn run_sync<T, E, F>(fut: F) -> Result<T, E>
where
    T: Debug + Send + 'static,
    E: Debug + Send + 'static,
    F: Future<Item = T, Error = E> + Send + 'static,
{
    let (sender, receiver) = tokio::sync::oneshot::channel();
    let exec = fut.then(move |result| {
        sender.send(result).expect("Unable to send result");
        Ok(())
    });
    tokio::run(exec);
    receiver.wait().expect("Receive error")
}
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
darkwisebear
  • 131
  • 5