Poll for incoming events and drive futures on the same thread?

I have got hyper http server. Processed requests issue async hyper requests to inner service, wait for async inner response, which is then mapped to the response for the original external request. Schematically it looks like external-request to inner-request to inner-response to external-response. I understand that constructed future chain is driven by hyper server as well as poll for incoming requests on the same single thread.

Now I would like to issue external-response without waiting for inner-response. I have attempted to change the logic but it seems Inner-response futures now require a separate driver for poll, like thread pool executor in scala.

I have tried to use futures_cpupool.spawn but got compiler error that hyper: client: request future is not send'able.

I have tried to use channel like mpsc from STD library or futures. Where inner request is issued by a consumer, and producers submit enough data to the channel from the external-request and respond with external-response immediately.
This seems better path forward but I have got the same problem: a thread should either poll for channel consumer events or drive inner request futures calling core.run() . Now I am thinking to do limited time poll for consumer and limited time poll for futures sequentially one after the other in the infinite loop on the same single thread, but it seems very low level solution. Is there better way? What is the right API to do limited time, interruptible poll for the channel consumer and futures result?

You hopefully have access (or can get) to handle (or remote.) Use that to send your inner and then the rest of that code block is for the external-response.

I thought to spawn inner request using handle of the Tokio core of the server, but it is private variable member of the hyper Server, which I do not have access to use for my other inner futures, except the one (external-response future) I return from call() method on the hyper server.

You can launch hyper with bind_connection which takes a Handle from you. This means you create the Core yourself and can stash a Handle clone in your own code.

1 Like

Thanks. Will the hyper server drive my inner futures to completion? Or I need to call something like core:run(my_future)?

After thinking more maybe handle is overkill. join might be all that you need.

Not sure what you mean with join...

If you Handle::spawn the inner future, then the event loop/reactor (i.e. Core) will drive your future to completion; the event loop will be shared with hyper, and it's all single threaded.

Perhaps I'm not understanding your requirements correctly though. It seems like you want to return a response to a hyper request without waiting for some internal future to resolve, and you want that internal future to make progress independent of the response to the client.

That is correct.

I will try to figure out the way you proposed. Still not sure where the main event loop is launched / started when the hyper server is created with bind_connection

join (Better doc link this time.) Actually maybe bad since if one errors then the other stops.

Oh, I see what you're asking now. Yes, you'll need to run the server future yourself. So it would be something like this:

let mut core = Core::new().unwrap();
let handle = core.handle();
let listener = TcpListener::bind(...).unwrap();
let server = listener.incoming().for_each(|sock, addr| {
      Http::new().bind_connection(&handle, sock, addr, <your_service>);
      Ok(())
});
core.run(server).unwrap();

So you bootstrap the inbound socket accept stream yourself, and then manually serve each accepted connection with the hyper service you wrote.

1 Like

Thank you for your help!

Great. This works too. And futures are completed now! Thank you for your help.

Unfortunately, this thing was not obvious to come up with without asking for help here!

I have got a warning on bind_connection: use of deprecated item: All usage of the tokio-proto crate is going away.. What is the recommended alternative to achieve the same?

Iā€™m guessing hyper::server::Http - Rust