Skip to content

Commit

Permalink
Add timeout behaviors to the socket module
Browse files Browse the repository at this point in the history
When a remote server becomes unavailable or non-responsive without
properly terminating connections, any requests in-flight will
wait indefinitely.

A optional connection parameter `req_timeout` has been added. The
default value is infinity, which preserves the existing behavior.

If a non-infinite value is specified, it is used internally as a
gen_server timeout value within epgsql_sock. If there are outstanding
requests (determined by looking at the queue state) the timeout is
applied.

This also adds overall timeout to the initialization process.
if the initialization messages - ending with ReadyForQuery - arrive at
intervals greater than the timeout, the epgsql_sock will timeout.

Notes:

One request in queue can represent multiple pipelined requests to the PG
server. In this case a single timeout is applied - and it gets
restarted as the reply to each individual message sent is received. This is
intentional, because any network activity from the postgres server
indicates we have a valid connection to it.

Limitations:

This change only ensures support for the default `epgsql` interface.
Additional behavior consideration is required to support the async
interface.

The timeout is not exact - intervening inbound messages (whether to
perform new actions, or received from the PG server) will restart the timer.
A further refinement will be to only reset the timeout when receiving
messages from the server, and to  reduce remaining time available if
the message is received from another caller. That is not addressed in
this changeset.

Signed-off-by: Marc Paradise <marc@chef.io>
Signed-off-by: Marc Paradise <marc.paradise@gmail.com>
  • Loading branch information
Marc Paradise authored and marcparadise committed Feb 8, 2017
1 parent e87d6d2 commit 7712ee2
Show file tree
Hide file tree
Showing 4 changed files with 149 additions and 81 deletions.
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,13 @@ see `CHANGES` for full list.
-type host() :: inet:ip_address() | inet:hostname().

-type connect_option() ::
{database, DBName :: string()} |
{port, PortNum :: inet:port_number()} |
{ssl, IsEnabled :: boolean() | required} |
{ssl_opts, SslOptions :: [ssl:ssl_option()]} | % @see OTP ssl app, ssl_api.hrl
{timeout, TimeoutMs :: timeout()} | % default: 5000 ms
{async, Receiver :: pid()}. % process to receive LISTEN/NOTIFY msgs
{database, DBName :: string()} |
{port, PortNum :: inet:port_number()} |
{ssl, IsEnabled :: boolean() | required} |
{ssl_opts, SslOptions :: [ssl:ssl_option()]} | % @see OTP ssl app, ssl_api.hrl
{timeout, TimeoutMs :: timeout()} | % default: 5000 ms, initial connection timeout.
{req_timeout, ReqTimeout :: timeout()} | % default: infinity, how long to wait for a response to any given request.
{async, Receiver :: pid()}. % process to receive LISTEN/NOTIFY msgs

-spec connect(host(), string(), string(), [connect_option()])
-> {ok, Connection :: connection()} | {error, Reason :: connect_error()}.
Expand Down
11 changes: 6 additions & 5 deletions src/epgsql.erl
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,12 @@
-type host() :: inet:ip_address() | inet:hostname().
-type connection() :: pid().
-type connect_option() ::
{database, DBName :: string()} |
{port, PortNum :: inet:port_number()} |
{ssl, IsEnabled :: boolean() | required} |
{ssl_opts, SslOptions :: [ssl:ssl_option()]} | % @see OTP ssl app, ssl_api.hrl
{timeout, TimeoutMs :: timeout()} | % default: 5000 ms
{database, DBName :: string()} |
{port, PortNum :: inet:port_number()} |
{ssl, IsEnabled :: boolean() | required} |
{ssl_opts, SslOptions :: [ssl:ssl_option()]} | % @see OTP ssl app, ssl_api.hrl
{timeout, TimeoutMs :: timeout()} | % default: 5000 ms
{req_timeout, ReqTimeout :: timeout()} | % default: infinity
{async, Receiver :: pid()}. % process to receive LISTEN/NOTIFY msgs
-type connect_error() :: #error{}.
-type query_error() :: #error{}.
Expand Down

0 comments on commit 7712ee2

Please sign in to comment.