Hi Hackers, Attached is the workaround patch to set the default connection timeout to 30 seconds instead of the current value of infinite - 0, zero. The input is present in the server properties dialogs advanced tab. The workaround applies to the RM4724 as well. The permanent solution would be to expand the nodes asynchronously - https://redmine.postgresql.org/issues/4933
Also fixed a bug where sql editor is not closing if the server is disconnected in between. Kindly review. -- Thanks and Regards, Aditya Toshniwal Sr. Software Engineer | EnterpriseDB India | Pune "Don't Complain about Heat, Plant a TREE"
diff --git a/web/migrations/versions/aff1436e3c8c_.py b/web/migrations/versions/aff1436e3c8c_.py new file mode 100644 index 000000000..b5952418b --- /dev/null +++ b/web/migrations/versions/aff1436e3c8c_.py @@ -0,0 +1,27 @@ + +""" Update the default timeout to 30 seconds instead on 0. +0 indicates wait indefinitely which causes trouble when network connection +to server is lost. + +Revision ID: aff1436e3c8c +Revises: a77a0932a568 +Create Date: 2019-10-28 12:47:36.828709 + +""" +from pgadmin.model import db + +# revision identifiers, used by Alembic. +revision = 'aff1436e3c8c' +down_revision = 'a77a0932a568' +branch_labels = None +depends_on = None + + +def upgrade(): + db.engine.execute( + 'UPDATE server SET connect_timeout=30 WHERE connect_timeout=0 OR connect_timeout IS NULL' + ) + + +def downgrade(): + pass diff --git a/web/pgadmin/browser/server_groups/servers/__init__.py b/web/pgadmin/browser/server_groups/servers/__init__.py index dc39a1393..72f9e11a8 100644 --- a/web/pgadmin/browser/server_groups/servers/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/__init__.py @@ -28,6 +28,7 @@ from pgadmin.model import db, Server, ServerGroup, User from pgadmin.utils.driver import get_driver from pgadmin.utils.master_password import get_crypt_key from pgadmin.utils.exception import CryptKeyMissing +from psycopg2 import OperationalError def has_any(data, keys): @@ -128,12 +129,20 @@ class ServerModule(sg.ServerGroupPluginModule): except CryptKeyMissing: # show the nodes at least even if not able to connect. pass + except OperationalError as e: + current_app.logger.exception(e) + connected = False in_recovery = None wal_paused = None if connected: - in_recovery, wal_paused = recovery_state(conn, manager.version) + try: + in_recovery, wal_paused = recovery_state(conn, manager.version) + except OperationalError as e: + current_app.logger.exception(e) + connected = False + yield self.generate_browser_node( "%d" % (server.id), gid, diff --git a/web/pgadmin/browser/server_groups/servers/static/js/server.js b/web/pgadmin/browser/server_groups/servers/static/js/server.js index 99fed949e..99297d4da 100644 --- a/web/pgadmin/browser/server_groups/servers/static/js/server.js +++ b/web/pgadmin/browser/server_groups/servers/static/js/server.js @@ -732,7 +732,7 @@ define('pgadmin.node.server', [ tunnel_password: undefined, tunnel_authentication: 0, save_tunnel_password: false, - connect_timeout: 0, + connect_timeout: 30, }, // Default values! initialize: function(attrs, args) { diff --git a/web/pgadmin/model/__init__.py b/web/pgadmin/model/__init__.py index 629e98f37..b22868fbb 100644 --- a/web/pgadmin/model/__init__.py +++ b/web/pgadmin/model/__init__.py @@ -29,7 +29,7 @@ from flask_sqlalchemy import SQLAlchemy # ########################################################################## -SCHEMA_VERSION = 23 +SCHEMA_VERSION = 24 ########################################################################## # diff --git a/web/pgadmin/static/js/sqleditor/execute_query.js b/web/pgadmin/static/js/sqleditor/execute_query.js index f714c2b50..63ad7721b 100644 --- a/web/pgadmin/static/js/sqleditor/execute_query.js +++ b/web/pgadmin/static/js/sqleditor/execute_query.js @@ -12,6 +12,7 @@ import $ from 'jquery'; import url_for from '../url_for'; import axios from 'axios'; import * as httpErrorHandler from './query_tool_http_error_handler'; +import * as queryTxnStatus from 'sources/sqleditor/query_txn_status_constants'; class LoadingScreen { constructor(sqlEditor) { @@ -83,7 +84,8 @@ class ExecuteQuery { self.loadingScreen.hide(); self.enableSQLEditorButtons(); // Enable/Disable commit and rollback button. - if (result.data.data.transaction_status == 2 || result.data.data.transaction_status == 3) { + if (result.data.data.transaction_status == queryTxnStatus.TRANSACTION_STATUS_INTRANS + || result.data.data.transaction_status == queryTxnStatus.TRANSACTION_STATUS_INERROR) { self.enableTransactionButtons(); } else { self.disableTransactionButtons(); @@ -123,7 +125,8 @@ class ExecuteQuery { self.updateSqlEditorLastTransactionStatus(httpMessage.data.data.transaction_status); // Enable/Disable commit and rollback button. - if (httpMessage.data.data.transaction_status == 2 || httpMessage.data.data.transaction_status == 3) { + if (httpMessage.data.data.transaction_status == queryTxnStatus.TRANSACTION_STATUS_INTRANS + || httpMessage.data.data.transaction_status == queryTxnStatus.TRANSACTION_STATUS_INERROR) { self.enableTransactionButtons(); } else { self.disableTransactionButtons(); @@ -131,7 +134,7 @@ class ExecuteQuery { if (ExecuteQuery.isQueryFinished(httpMessage)) { if (this.sqlServerObject.close_on_idle_transaction && - httpMessage.data.data.transaction_status == 0) + httpMessage.data.data.transaction_status == queryTxnStatus.TRANSACTION_STATUS_IDLE) this.sqlServerObject.check_needed_confirmations_before_closing_panel(); self.loadingScreen.setMessage('Loading data from the database server and rendering...'); diff --git a/web/pgadmin/static/js/sqleditor/query_txn_status_constants.js b/web/pgadmin/static/js/sqleditor/query_txn_status_constants.js new file mode 100644 index 000000000..075264296 --- /dev/null +++ b/web/pgadmin/static/js/sqleditor/query_txn_status_constants.js @@ -0,0 +1,11 @@ +/* psycopg2 transaction status constants + * http://initd.org/psycopg/docs/extensions.html#transaction-status-constants + */ + +module.exports = { + TRANSACTION_STATUS_IDLE: 0, + TRANSACTION_STATUS_ACTIVE: 1, + TRANSACTION_STATUS_INTRANS: 2, + TRANSACTION_STATUS_INERROR: 3, + TRANSACTION_STATUS_UNKNOWN: 5, +}; diff --git a/web/pgadmin/tools/sqleditor/static/js/sqleditor.js b/web/pgadmin/tools/sqleditor/static/js/sqleditor.js index 70d4bd348..5512382d4 100644 --- a/web/pgadmin/tools/sqleditor/static/js/sqleditor.js +++ b/web/pgadmin/tools/sqleditor/static/js/sqleditor.js @@ -36,6 +36,7 @@ define('tools.querytool', [ 'sources/sqleditor/calculate_query_run_time', 'sources/sqleditor/call_render_after_poll', 'sources/sqleditor/query_tool_preferences', + 'sources/sqleditor/query_txn_status_constants', 'sources/csrf', 'tools/datagrid/static/js/datagrid_panel_title', 'sources/window', @@ -52,7 +53,7 @@ define('tools.querytool', [ XCellSelectionModel, setStagedRows, SqlEditorUtils, ExecuteQuery, httpErrorHandler, FilterHandler, GeometryViewer, historyColl, queryHist, querySources, keyboardShortcuts, queryToolActions, queryToolNotifications, Datagrid, - modifyAnimation, calculateQueryRunTime, callRenderAfterPoll, queryToolPref, csrfToken, panelTitleFunc, + modifyAnimation, calculateQueryRunTime, callRenderAfterPoll, queryToolPref, queryTxnStatus, csrfToken, panelTitleFunc, pgWindow) { /* Return back, this has been called more than once */ if (pgAdmin.SqlEditor) @@ -4178,8 +4179,9 @@ define('tools.querytool', [ self.unsaved_changes_user_confirmation(msg, false); } // If a transaction is currently ongoing else if (self.preferences.prompt_commit_transaction - && self.last_transaction_status > 0) { // 0 -> idle (no transaction) - var is_commit_disabled = self.last_transaction_status == 3; // 3 -> Failed transaction + && (self.last_transaction_status === queryTxnStatus.TRANSACTION_STATUS_INTRANS + || self.last_transaction_status === queryTxnStatus.TRANSACTION_STATUS_INERROR)) { + var is_commit_disabled = self.last_transaction_status == queryTxnStatus.TRANSACTION_STATUS_INERROR; self.uncommitted_transaction_user_confirmation(is_commit_disabled); } else {