shio-rs
shio-rs copied to clipboard
Proxy example should use per-thread client
If I am not mistaken, the example regarding the proxying solution will create a new client per request in https://github.com/mehcode/shio-rs/blob/master/examples/proxy/src/main.rs#L19
If I am correct - how would this be done with a per-thread client?
I am also curious about how one would do this with shio...
There is a pattern where you put a core's handle in thread local storage, and then you can put a hyper/reqwest Client in TLS as well based on that handle, but it doesn't seem like that could be used here.
That's basically what it's done here : the Context have the thread core handle, and it create a hyper::Client future on that handle. No thread-local storage involved here.
But that is the point: the Client should be put in thread-local storage (or made reusable in some other way), to take advantage of the internal connection pool, keep-alive (optionally), etc.
I definitely agree that this should be easily possible. A quick work around for a limitation here would be to use a ThreadLocal.
lazy_static! {
pub static CLIENT: ThreadLocal<hyper::Client> = ThreadLocal::new();
}
// [...]
CLIENT.get_or(Client::new).get("....");
That doesn't seem to be quite that straightforward 😕 :
17 | / lazy_static! {
18 | | pub static ref CLIENT: ThreadLocal<Client<HttpConnector>> = ThreadLocal::new();
19 | | }
| |_^ `std::rc::Rc<std::cell::RefCell<hyper::client::pool::PoolInner<tokio_proto::util::client_proxy::ClientProxy<tokio_proto::streaming::message::Message<hyper::proto::MessageHead<hyper::proto::RequestLine>, hyper::Body>, tokio_proto::streaming::message::Message<hyper::proto::MessageHead<hyper::proto::RawStatus>, tokio_proto::streaming::body::Body<hyper::Chunk, hyper::Error>>, hyper::Error>>>>` cannot be sent between threads safely
Maybe use std thread_local! ?
thread_local! {
static CLIENT : RefCell<Option<Client>>,
}
fn client_start<F>(handle: &Handle, callback: F) -> hyper::client::FutureResponse
where F: Fn(&Client) -> hyper::client::FutureResponse
{
CLIENT.with(|rf| {
let should_be_init = rf.borrow().is_none();
if should_be_init {
*rf.borrow_mut() = Some(Client::new(handle));
}
callback(rf.borrow().as_ref().unwrap())
})
}