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

Client timeout #62

Merged
merged 2 commits into from
Mar 14, 2017
Merged

Client timeout #62

merged 2 commits into from
Mar 14, 2017

Conversation

gsquire
Copy link
Contributor

@gsquire gsquire commented Feb 28, 2017

This is a rough attempt at adding timeout to a Client. For ergonomics, it uses the timeout for both read and write portions of a hyper::Client.

Closes #36

@seanmonstar
Copy link
Owner

I like that it's a single timeout, for now. What do you think of having a mutator method instead of a constructor? So people would write:

let mut client = Client::new()?;
client.timeout(Duration::from_secs(30));
// or
client.set_timeout(dur);

@gsquire
Copy link
Contributor Author

gsquire commented Mar 1, 2017

I had originally wanted to do something just like that but ran into issues with borrowing.

e.g. Inside the Client implementation:

pub fn timeout(&mut self, time: Duration) {
    self.inner.hyper.set_read_timeout(Some(time));
}

This approach yields the error:

error: cannot borrow immutable field as mutable
  --> src/client.rs:72:9
   |
72 |         self.inner.hyper.set_read_timeout(Some(time));
   |         ^^^^^^^^^^^^^^^^

error: aborting due to previous error

Unless I have a fundamental misunderstanding of borrowing, this seems like it can't be done. Feel free to prove me wrong.

@seanmonstar
Copy link
Owner

Oh right, the client is behind an Arc. We could change ClientRef to put the hyper::Client inside a Mutex, which would allow us to update it then.

@gsquire
Copy link
Contributor Author

gsquire commented Mar 1, 2017

Ok I can do that then, just like the RedirectPolicy.

@gsquire gsquire force-pushed the timeout branch 2 times, most recently from bb25602 to 5d9c79f Compare March 2, 2017 18:02
Copy link
Owner

@seanmonstar seanmonstar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm sorry I didn't notice the changes earlier. Looks like one change would be needed, and we're good to go!

src/client.rs Outdated
@@ -235,7 +243,8 @@ impl RequestBuilder {
loop {
let res = {
debug!("request {:?} \"{}\"", method, url);
let mut req = client.hyper.request(method.clone(), url.clone())
let c = client.hyper.lock().unwrap();
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So Mutexes are tricky. This code will surprisingly hold on to the locked client while the request is sent over the network, and the response headers have been received. I'd forgotten that a mutex would play badly here.

This is one of the very few times when a RwLock is probably a good idea. The reason is that we have to lock it somehow for when we mutate the Client, in the timeout() method. But besides that, we actually don't want exclusive access, and only require read (&client) access. Making use a RwLock means that making a change to the timeout has to wait until any current requests are done, but the requests don't block each other.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good point. I updated it to use a RwLock.

@gsquire gsquire force-pushed the timeout branch 2 times, most recently from 9fb650e to 745c85f Compare March 13, 2017 03:02
@seanmonstar seanmonstar merged commit ec049fe into seanmonstar:master Mar 14, 2017
@seanmonstar
Copy link
Owner

Thanks!

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

Successfully merging this pull request may close these issues.

2 participants