There are a number of errors that occur when attempting to use a database connection that has suddenly become dead.
PG::ConnectionBad: PQsocket() can't get socket descriptor:,
PG::UnableToSend: no connection to the server,
PG::ConnectionBad: PQconsumeInput() server closed the connection unexpectedly,
PG::UnableToSend: SSL connection has been closed unexpectedly, and so on.
They may be caused by a few different factors, e.g. long command run, or long SSH connection, or closed connection in separate thread(like in 'parallel' gem), or long code processing before save.
If you see errors like that, and do have some slow processing, there are several things to check:
1) Rails's database
idle_timeout setting, which is 300 seconds by default. This means that if a connection is idle for more than 300 seconds, the server will close it.
client_idle_timeout setting. This setting controls how long a connection can be idle before PgBouncer closes it. If this setting is set too low, it can cause the same errors as Rails's idle_timeout.
idle_session_timeout settings (from PostgreSQL 14) and
idle_in_transaction_session_timeout(for sessions that were idle in transaction).
4) TCP or other network or firewall timeouts(e.g. there is a case of the timeout in Azure Cloud)
To solve this problem, there are a few possible solutions:
0) Speed up slow processing
1) Increase the
idle_timeout(or another guilty timeout) setting to a higher value to prevent a server from closing idle connections too soon.
2) Add a database setting called
reaping_frequency: 10, which will clear and restore connections more frequently to prevent them from becoming idle.
3) Add manual reconnection, like the code snippet below, which releases the connection and re-establishes it before saving a record to the database.
ActiveRecord::Base.connection_pool.release_connection ActiveRecord::Base.connection_pool.with_connection do # save record in database end