Detect Ecto DB query timeout

Viewed 637

I want to return a specific error response (HTTP 503 with a custom message) when Ecto (or postgrex?) encounters a database query timeout.

When a timeout occurs, the exception thrown looks like this:

** (DBConnection.ConnectionError) tcp recv: closed
    (ecto) lib/ecto/adapters/postgres/connection.ex:86: Ecto.Adapters.Postgres.Connection.prepare_execute/5
    (ecto) lib/ecto/adapters/sql.ex:243: Ecto.Adapters.SQL.sql_call/6
    (ecto) lib/ecto/adapters/sql.ex:431: Ecto.Adapters.SQL.execute_and_cache/7
    (ecto) lib/ecto/repo/queryable.ex:130: Ecto.Repo.Queryable.execute/5
    (ecto) lib/ecto/repo/queryable.ex:35: Ecto.Repo.Queryable.all/4
    (stdlib) timer.erl:166: :timer.tc/1

I defined an implementation for the Plug.Exception protocol to map DBConnection.ConnectionError to a status 503 when the exception message is "tcp recv: closed", which seems to work.

defimpl Plug.Exception, for: DBConnection.ConnectionError do
  def status(exception) do
    if exception.message == "tcp recv: closed" do
      503
    else
      500
    end
  end
end

However, my worry is that the DBConnection.ConnectionError exception along with "tcp recv: closed" is too general for me to assume that a DB timeout occurred. What if the closed connection was caused by something else, like a network failure?

Is there a more specific way to detect when a DB query timeout has occured?

1 Answers

You can make your error message more concrete if you check if the DNS resolution works and if the network connection works when the database connection problems occur.

Sample for checking network connection:

curl --head http://ipaddress/

or

ping ipadress

or

#!/bin/bash

echo -e "GET http://stackoverflow.com HTTP/1.0\n\n" | nc stackoverflow.com 80 > /dev/null 2>&1

if [ $? -eq 0 ]; then
    echo "Online"
else
    echo "Offline"
fi
Related