[13.x] Prevent recursive reconnects while a connection is reconnecting
Fixes #61987
Since 13.21.0, a refused PostgreSQL connection can exhaust memory instead of throwing a QueryException:
PHP Fatal error: Allowed memory size of 536870912 bytes exhausted (tried to allocate 20480 bytes) in .../Illuminate/Database/Connection.php
Cause
When a query fails with a lost connection, Connection::tryAgainIfCausedByLostConnection() calls reconnect(), and DatabaseManager::reconnect() dispatches ConnectionEstablished. The PDO is still a lazy closure at that point, so a listener that runs a query (for example SET application_name ...) fails on the same unreachable server. That failure is also detected as a lost connection, which reconnects again, dispatches the event again, and so on until memory runs out.
#60819 added failed: Connection refused to the lost connection messages, which exposed this for PostgreSQL. The recursion itself is older: MySQL's SQLSTATE[HY000] [2002] Connection refused was already detected as a lost connection and recurses the same way on 13.20.0.
Without a listener that queries, the connection still gives up after one retry, so the problem only shows up in apps (or packages) that query from ConnectionEstablished.
Fix
The connection now tracks whether it is reconnecting. A query that fails with a lost connection during a reconnect throws instead of reconnecting again. The normal single retry outside of a reconnect is unchanged, so transient refusals (failover, PgBouncer restarts) are still retried as #60819 intended.
Test
testQueriesRunWhileReconnectingDoNotReconnectAgain uses a reconnector that queries the same connection, as a ConnectionEstablished listener would. It asserts a QueryException after exactly one reconnect, and fails cleanly instead of exhausting memory when the guard is missing.