Skip to content

Commit d905902

Browse files
committed
Fix connection_ping() to check transaction_status before SELECT 1 and return 503 CONNECTION_LOST
- Check transaction_status before executing ping query to avoid disrupting long-running queries or active transactions (addresses review feedback). Moved the check inside try-except to handle race conditions where the connection drops between connected() and transaction_status access. - Return 503 service_unavailable with CONNECTION_LOST info instead of 500 internal_server_error when reconnect fails in children() endpoint, so the tree_nodes.ts reconnect dialog is properly triggered.
1 parent 9c30a41 commit d905902

File tree

2 files changed

+19
-2
lines changed

2 files changed

+19
-2
lines changed

web/pgadmin/browser/utils.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
from config import PG_DEFAULT_DRIVER
2020
from pgadmin.utils.ajax import make_json_response, precondition_required,\
21-
internal_server_error
21+
internal_server_error, service_unavailable
2222
from pgadmin.utils.exception import ConnectionLost, SSHTunnelConnectionLost,\
2323
CryptKeyMissing
2424
from pgadmin.utils.constants import DATABASE_LAST_SYSTEM_OID
@@ -441,7 +441,9 @@ def children(self, **kwargs):
441441
if not conn.connection_ping():
442442
status, msg = conn.connect()
443443
if not status:
444-
return internal_server_error(errormsg=msg)
444+
return service_unavailable(
445+
msg, info="CONNECTION_LOST"
446+
)
445447
except (ConnectionLost, SSHTunnelConnectionLost, CryptKeyMissing):
446448
raise
447449
except Exception:

web/pgadmin/utils/driver/psycopg3/connection.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1425,7 +1425,22 @@ def connection_ping(self):
14251425
"""
14261426
if not self.connected():
14271427
return False
1428+
14281429
try:
1430+
# Check the transaction status before executing the ping
1431+
# query. If a query is already in progress (ACTIVE) or we
1432+
# are inside a transaction block (INTRANS / INERROR), running
1433+
# SELECT 1 would fail or disrupt the ongoing operation. In
1434+
# those states the connection is evidently alive, so just
1435+
# return True.
1436+
txn_status = self.conn.info.transaction_status
1437+
if txn_status != 0:
1438+
# 0 = IDLE — safe to send a query
1439+
# 1 = ACTIVE — command in progress, connection is alive
1440+
# 2 = INTRANS — in transaction block, connection is alive
1441+
# 3 = INERROR — in failed transaction, connection is alive
1442+
return True
1443+
14291444
cur = self.conn.cursor()
14301445
cur.execute("SELECT 1")
14311446
cur.close()

0 commit comments

Comments
 (0)