Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cannot use with tokio::run() #20

Open
njaard opened this issue Nov 3, 2018 · 5 comments
Open

cannot use with tokio::run() #20

njaard opened this issue Nov 3, 2018 · 5 comments

Comments

@njaard
Copy link

njaard commented Nov 3, 2018

There's no way to get Futures from incoming connections. Plain old hyper uses this kind of code:

let s = Server::bind(&addr.parse().unwrap())
  .serve(new_service)
  .map_err(|e| eprintln!("server error: {}", e));
hyper::rt::run(s);

But hyperlocal doesn't allow it. Even if you do into_future() (after mapping the outputs to ()), then it doesn't work because it never actually processes requests.

This feature is necessary because hyperlocal's event loop doesn't work at all with threadpooling and the tokio_threadpool::blocking function.

@njaard
Copy link
Author

njaard commented Nov 3, 2018

Here's a test program that doesn't respond to incoming requests.

You can connect to it like so: curl --unix-socket socket 'http://localhost:3000/'

extern crate hyper;
extern crate hyperlocal;
extern crate tokio_threadpool;
extern crate futures;

use hyper::{Body};
use std::sync::Arc;

type Response = hyper::Response<Body>;
type Request = hyper::Request<Body>;

use futures::future::{Future, lazy};
use tokio_threadpool::blocking;
use hyper::rt::poll_fn;
use futures::Stream;

fn main()
{
  let addr = "socket";
  let new_service =
    move ||
    {
      let pool = Arc::new(tokio_threadpool::ThreadPool::new());
      hyper::service::service_fn(
        move |_req: Request|
        {
          pool.spawn_handle(
            lazy(move ||
              poll_fn( move || blocking(
                || Response::new(Body::from("hello"))
              ))
            )
          )
        }
      )
    };

  let s = hyperlocal::server::Http::new().serve_path(
    addr, new_service
  ).unwrap().into_future().map(|_| ()).map_err(|e| panic!("{:?}" ,e.0));

  hyper::rt::run(s);
}

@njaard
Copy link
Author

njaard commented Nov 3, 2018

And here's a program that doesn't use a threadpool properly.

You can test this program with:
for i in $(seq 1 20); do { curl --unix-socket socket 'http://localhost:3000/' & } ; done; time for i in $(seq 1 20); do wait; done

Expected behavior: this command completes in about 1s.
Actual behavior: this command completes in about 20s.

extern crate hyper;
extern crate hyperlocal;
extern crate tokio_threadpool;
extern crate futures;

use hyper::{Body};
use std::sync::Arc;

type Response = hyper::Response<Body>;
type Request = hyper::Request<Body>;

use futures::future::{lazy};
use tokio_threadpool::blocking;
use hyper::rt::poll_fn;

fn main()
{
  let addr = "socket";
  let new_service =
    move ||
    {
      let pool = Arc::new(tokio_threadpool::ThreadPool::new());
      hyper::service::service_fn(
        move |_req: Request|
        {
          pool.spawn_handle(
            lazy(move ||
              poll_fn( move || blocking(
                ||
                {
                  std::thread::sleep_ms(1000);
                  Response::new(Body::from("hello"))
                }
              ))
            )
          )
        }
      )
    };

  let s = hyperlocal::server::Server::bind(addr, new_service)
    .unwrap();

  s.run().unwrap();
}

@softprops
Copy link
Owner

Thanks for reporting the issue @njaard. I'm open to pull requests if you have ideas for the api you'd like to see.

@njaard
Copy link
Author

njaard commented Nov 4, 2018

There's no way I could write you a patch, because my understanding of tokio is too poor.

I guess there should be an Api that provides a Future<(),()> for incoming connection, as that's what hyper::rt::run() wants.

@softprops
Copy link
Owner

That's cool. I can dig into this. Thanks for the sample code. I'll try an use this example code under the examples dir when I figure this out

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants