copiousfreetime/kjess — pull request #9 by eric (2012-11-19 06:37:33+00:00)
Title: Implement socket timeouts

## Overview

I believe very strongly that having short connect, read and write timeouts are vital in creating a robust distributed platform. Waiting for TCP socket timeouts of 120 seconds in the case of catastrophic hardware failure of one of the kestrel servers can lead to large delays in processing that otherwise could be resolved with short timeouts.

## The Solution

After reading [`redis/redis-rb`](https://github.com/redis/redis-rb) and many other libraries, I've decided the best way to provide configurable socket timeouts is by using non-blocking IO and using `IO.select()`.

## The Highlights

The `KJess::Connection` class provides `connect_timeout`, `read_timeout` and `write_timeout`. They can be updated with accessors at any time.

One problem with read timeouts in the ruby [`kestrel-client`](https://github.com/twitter/kestrel-client) is that they do not take into account the timeout provided to `get` operations, which means if the read timeout provided to the client is not greater than the largest get timeout, you can run into issues.

This solution adds the specified `get` timeout to the `read_timeout` to ensure that enough time is allowed when `KJess::Connection#with_read_timeout()` is called.

This pull request provides two methods:

* `KJess::Connection#with_read_timeout()`
* `KJess::Connection#with_write_timeout()`

which records a "deadline" (a time) in the connection for when the timeout will expire to make calculating the specific timeouts to pass to `IO.select()` easier.

`KJess::Connection#with_read_timeout()` is called in `KJess::Client#get()` to provide the additional timeout that should be added to the standard connection timeout.

`KJess::Connection#with_write_timeout()` is only called internally by `KJess::Connection#write()` to record the deadline timer.