Postgrex start_link returns {:ok, pid} in case of an error

Hi,
I tried to use Postgrex for the first time and encountered the following problem: if I connect to my PostgresSQL server with correct credentials, everything works like a charm. If I use a wrong password, I‘m struggling with the error handling, because start_link than also returns {:ok, pid}. The error message about the wrong credentials is logged out later. How can I handle this case?

Cheers
Christian

1 Like

Does out connect successfully with the wrong password when you use psql on the command line?

It starts a connection pool and the pool will start (that is the pid you are getting back). If you try to query with that connection poll you will get a error tuple back.

2 Likes

Thanks for your answers. Maybe I’m doing something completely wrong here, because I’m new to elixir. From what I understand, this would be a safe code to handle a simple Postgres query:

  def connect do
    Logger.info("before")
    try do
      with {:ok, con} <-  Postgrex.start_link(hostname: "localhost", username: "my_user", password: "wrong_password", database: "my_db")
      do
        with {:ok, result} <- Postgrex.query(con, "SELECT * FROM books", [])
        do
          Logger.info("Success")
        else
          {:error, q_err} -> Logger.error("Query Error: #{ q_err.message}")

        end
      else
        {:error, c_err} -> Logger.error("Connection Error: #{c_err.message}")
      end
    rescue e in DBConnection.ConnectionError-> e
      Logger.error("Runtime Error")
    end
      Logger.info("end")
  end
end

But I do not end up in one of the “error” branches nor in the rescue section. This is the output I see in iex:

iex(1)> Ql.connect()

08:29:15.900 [info]  before
 
08:29:15.972 [error] Postgrex.Protocol (#PID<0.214.0>) failed to connect: ** (Postgrex.Error) FATAL 28P01 (invalid_password) password authentication failed for user "my_user"
 
08:29:18.250 [error] Postgrex.Protocol (#PID<0.214.0>) failed to connect: ** (Postgrex.Error) FATAL 28P01 (invalid_password) password authentication failed for user "my_user"
 
08:29:18.918 [error] Query Error: connection not available and request was dropped from queue after 2991ms. This means requests are coming in and your connection pool cannot serve them fast enough. ...

:ok

08:29:18.918 [info]  end

The displayed error messages repeat continuously. They are not coming from my error handling. My error handling is completely ignored. What is wrong here? Any help is appreciated. Thanks a lot.

Christian

Because another process is crashing. Not yours.

Also, remember that with expressions usually aren’t used nested, they have been created as a replacement for nested case expressions.

Usually you start the pool as part of your application boot under supervision and use it from your running program.

Usually an operator would realise the crashing pool quickly and restart the program with correct credentials in the configuration.

Currently I’m not aware of a way to verify credentials as part of application boot to shut down with a proper userfacing error message.

1 Like

Postgrex uses the DBConnection library for connecting to the database. By default this uses a “random exponential” back-off strategy when trying to connect. See the DBConnection.start_link/2 options for details. The connection retrying is the source of the error logging that you can see from postgrex.

You could use backoff_type: :stop option to guarantee that the connection is available before querying. But since a database connection can be interrupted at any point it’s usually preferable to handle errors when sending queries. This is how the libary is intended to be used.

3 Likes