public inbox for [email protected]help / color / mirror / Atom feed
[pgAdmin][RM4818] Unable to handle loss of connection to server 7+ messages / 2 participants [nested] [flat]
* [pgAdmin][RM4818] Unable to handle loss of connection to server @ 2019-11-14 06:44 Aditya Toshniwal <[email protected]> 0 siblings, 1 reply; 7+ messages in thread From: Aditya Toshniwal @ 2019-11-14 06:44 UTC (permalink / raw) To: pgadmin-hackers 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" Attachments: [application/x-patch] RM4818.patch (8.1K, 3-RM4818.patch) download | inline diff: 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 { ^ permalink raw reply [nested|flat] 7+ messages in thread
* Re: [pgAdmin][RM4818] Unable to handle loss of connection to server @ 2019-11-15 09:04 Akshay Joshi <[email protected]> parent: Aditya Toshniwal <[email protected]> 0 siblings, 1 reply; 7+ messages in thread From: Akshay Joshi @ 2019-11-15 09:04 UTC (permalink / raw) To: Aditya Toshniwal <[email protected]>; +Cc: pgadmin-hackers Hi Aditya Following are the review comments: 1. The default connection timeout should be *10* seconds. 2. In case the network is disabled and when we expand the "Servers" node the database server(for which network is disabled) should be shown in the disconnected state. 3. For the above case when you try to connect to the server and at the same time trying to fetch the properties of the valid database server, it takes long time to fetch it. 4. Case when the network is disabled, the database servers password is saved and pgAdmin4 tries to connect the server, after connection timeout, there is no message to the user, only spinner gets disappeared. We should show a message. 5. We should improve the error messages "timeout expired" and "Connection to the servers has been lost." to the more meaningful messages like "Check the network settings, check the firewall status." 6. Install database server on Windows and Enable Windows Firewall. Try to connect to the same database server. Spinner is not showing, as a user I am not able to understand is there any action started at the backend or not. As a user, I'll keep trying to connect multiple times and after the connection timeout of each request dialog pops up. On Thu, Nov 14, 2019 at 12:15 PM Aditya Toshniwal < [email protected]> wrote: > 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" > -- *Thanks & Regards* *Akshay Joshi* *Sr. Software Architect* *EnterpriseDB Software India Private Limited* *Mobile: +91 976-788-8246* ^ permalink raw reply [nested|flat] 7+ messages in thread
* Re: [pgAdmin][RM4818] Unable to handle loss of connection to server @ 2019-11-21 06:20 Aditya Toshniwal <[email protected]> parent: Akshay Joshi <[email protected]> 0 siblings, 1 reply; 7+ messages in thread From: Aditya Toshniwal @ 2019-11-21 06:20 UTC (permalink / raw) To: pgadmin-hackers; +Cc: Akshay Joshi <[email protected]> Hi Hackers, Attached is the updated patch to fix the review comments. Please note, there is some problem with psycopg2/libpq where it hangs when network is lost - https://github.com/psycopg/psycopg2/issues/561 I've also changed the code to make connections after the "Servers" node is expanded to fix - RM4933, so that the servers are listed first. Kindly review. On Fri, Nov 15, 2019 at 2:34 PM Akshay Joshi <[email protected]> wrote: > Hi Aditya > > Following are the review comments: > > 1. The default connection timeout should be *10* seconds. > 2. In case the network is disabled and when we expand the "Servers" > node the database server(for which network is disabled) should be shown in > the disconnected state. > 3. For the above case when you try to connect to the server and at > the same time trying to fetch the properties of the valid database server, > it takes long time to fetch it. > 4. Case when the network is disabled, the database servers password > is saved and pgAdmin4 tries to connect the server, after connection > timeout, there is no message to the user, only spinner gets disappeared. We > should show a message. > 5. We should improve the error messages "timeout expired" and > "Connection to the servers has been lost." to the more meaningful messages > like "Check the network settings, check the firewall status." > 6. Install database server on Windows and Enable Windows Firewall. Try > to connect to the same database server. Spinner is not showing, as a user I > am not able to understand is there any action started at the backend or > not. As a user, I'll keep trying to connect multiple times and after the > connection timeout of each request dialog pops up. > > > On Thu, Nov 14, 2019 at 12:15 PM Aditya Toshniwal < > [email protected]> wrote: > >> 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" >> > > > -- > *Thanks & Regards* > *Akshay Joshi* > > *Sr. Software Architect* > *EnterpriseDB Software India Private Limited* > *Mobile: +91 976-788-8246* > -- Thanks and Regards, Aditya Toshniwal Sr. Software Engineer | EnterpriseDB India | Pune "Don't Complain about Heat, Plant a TREE" Attachments: [application/octet-stream] RM4818_v2.patch (30.4K, 3-RM4818_v2.patch) download | inline diff: diff --git a/web/migrations/versions/aff1436e3c8c_.py b/web/migrations/versions/aff1436e3c8c_.py new file mode 100644 index 000000000..45cfb9b3d --- /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=10 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..6b6ae4c53 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 Error as psycopg2_Error def has_any(data, keys): @@ -58,7 +59,7 @@ def recovery_state(connection, postgres_version): else: in_recovery = None wal_paused = None - return in_recovery, wal_paused + return status, result, in_recovery, wal_paused def server_icon_and_background(is_connected, manager, server): @@ -121,19 +122,21 @@ class ServerModule(sg.ServerGroupPluginModule): for server in servers: connected = False manager = None + errmsg = None + was_connected = False + in_recovery = None + wal_paused = None try: manager = driver.connection_manager(server.id) conn = manager.connection() - connected = conn.connected() + was_connected = conn.wasConnected except CryptKeyMissing: # show the nodes at least even if not able to connect. pass + except psycopg2_Error as e: + current_app.logger.exception(e) + errmsg = str(e) - in_recovery = None - wal_paused = None - - if connected: - in_recovery, wal_paused = recovery_state(conn, manager.version) yield self.generate_browser_node( "%d" % (server.id), gid, @@ -151,7 +154,9 @@ class ServerModule(sg.ServerGroupPluginModule): is_password_saved=True if server.password is not None else False, is_tunnel_password_saved=True - if server.tunnel_password is not None else False + if server.tunnel_password is not None else False, + was_connected=was_connected, + errmsg=errmsg ) @property @@ -352,12 +357,16 @@ class ServerNode(PGChildNodeView): manager = driver.connection_manager(server.id) conn = manager.connection() connected = conn.connected() - + errmsg = None + in_recovery = None + wal_paused = None if connected: - in_recovery, wal_paused = recovery_state(conn, manager.version) - else: - in_recovery = None - wal_paused = None + status, result, in_recovery, wal_paused =\ + recovery_state(conn, manager.version) + if not status: + connected = False + manager.release() + errmsg = "{0} : {1}".format(server.name, result) res.append( self.blueprint.generate_browser_node( @@ -377,7 +386,8 @@ class ServerNode(PGChildNodeView): is_password_saved=True if server.password is not None else False, is_tunnel_password_saved=True - if server.tunnel_password is not None else False + if server.tunnel_password is not None else False, + errmsg=errmsg ) ) @@ -409,12 +419,16 @@ class ServerNode(PGChildNodeView): manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(server.id) conn = manager.connection() connected = conn.connected() - + errmsg = None + in_recovery = None + wal_paused = None if connected: - in_recovery, wal_paused = recovery_state(conn, manager.version) - else: - in_recovery = None - wal_paused = None + status, result, in_recovery, wal_paused =\ + recovery_state(conn, manager.version) + if not status: + connected = False + manager.release() + errmsg = "{0} : {1}".format(server.name, result) return make_json_response( result=self.blueprint.generate_browser_node( @@ -434,8 +448,9 @@ class ServerNode(PGChildNodeView): is_password_saved=True if server.password is not None else False, is_tunnel_password_saved=True - if server.tunnel_password is not None else False - ) + if server.tunnel_password is not None else False, + errmsg=errmsg + ), ) @login_required @@ -949,19 +964,33 @@ class ServerNode(PGChildNodeView): def connect_status(self, gid, sid): """Check and return the connection status.""" + server = Server.query.filter_by(id=sid).first() manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(sid) conn = manager.connection() - res = conn.connected() + connected = conn.connected() + in_recovery = None + wal_paused = None + errmsg = None + if connected: + status, result, in_recovery, wal_paused =\ + recovery_state(conn, manager.version) - if res: - from pgadmin.utils.exception import ConnectionLost, \ - SSHTunnelConnectionLost - try: - conn.execute_scalar('SELECT 1') - except (ConnectionLost, SSHTunnelConnectionLost): - res = False + if not status: + connected = False + manager.release() + errmsg = "{0} : {1}".format(server.name, result) - return make_json_response(data={'connected': res}) + return make_json_response( + data={ + 'icon': server_icon_and_background(connected, manager, server), + 'connected': connected, + 'in_recovery': in_recovery, + 'wal_pause': wal_paused, + 'server_type': manager.server_type if connected else "pg", + 'user': manager.user_info if connected else None, + 'errmsg': errmsg + } + ) def connect(self, gid, sid): """ @@ -1125,7 +1154,8 @@ class ServerNode(PGChildNodeView): %s - %s' % (server.id, server.name)) # Update the recovery and wal pause option for the server # if connected successfully - in_recovery, wal_paused = recovery_state(conn, manager.version) + _, _, in_recovery, wal_paused =\ + recovery_state(conn, manager.version) return make_json_response( success=1, 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..08364783e 100644 --- a/web/pgadmin/browser/server_groups/servers/static/js/server.js +++ b/web/pgadmin/browser/server_groups/servers/static/js/server.js @@ -292,6 +292,10 @@ define('pgadmin.node.server', [ // Call added method of node.js pgAdmin.Browser.Node.callbacks.added.apply(this, arguments); + + if(data.was_connected) { + fetch_connection_status(this, data, pgBrowser.tree, item); + } return true; }, /* Reload configuration */ @@ -732,7 +736,7 @@ define('pgadmin.node.server', [ tunnel_password: undefined, tunnel_authentication: 0, save_tunnel_password: false, - connect_timeout: 0, + connect_timeout: 10, }, // Default values! initialize: function(attrs, args) { @@ -1273,7 +1277,14 @@ define('pgadmin.node.server', [ } }; + /* Wait till the existing request completes */ + if(data.is_connecting) { + return; + } data.is_connecting = true; + tree.setLeaf(item); + tree.removeIcon(item); + tree.addIcon(item, {icon: 'icon-server-connecting'}); var url = obj.generate_url(item, 'connect', data, true); $.post(url) .done(function(res) { @@ -1289,6 +1300,37 @@ define('pgadmin.node.server', [ ); }); }; + var fetch_connection_status = function(obj, data, tree, item) { + var url = obj.generate_url(item, 'connect', data, true); + + tree.setLeaf(item); + tree.removeIcon(item); + tree.addIcon(item, {icon: 'icon-server-connecting'}); + $.get(url) + .done(function(res) { + tree.setInode(item); + if (res && res.data) { + if (typeof res.data.icon == 'string') { + tree.removeIcon(item); + data.icon = res.data.icon; + tree.addIcon(item, {icon: data.icon}); + } + _.extend(data, res.data); + + var serverInfo = pgBrowser.serverInfo = pgBrowser.serverInfo || {}; + serverInfo[data._id] = _.extend({}, data); + + if(data.errmsg) { + Alertify.error(data.errmsg); + } + } + }) + .fail(function(xhr, status, error) { + tree.setInode(item); + tree.addIcon(item, {icon: 'icon-server-not-connected'}); + Alertify.pgRespErrorNotify(xhr, error); + }); + }; } return pgBrowser.Nodes['server']; diff --git a/web/pgadmin/browser/utils.py b/web/pgadmin/browser/utils.py index 2a17b3a2d..67dce0942 100644 --- a/web/pgadmin/browser/utils.py +++ b/web/pgadmin/browser/utils.py @@ -17,7 +17,8 @@ from flask.views import View, MethodViewType, with_metaclass from flask_babelex import gettext from config import PG_DEFAULT_DRIVER -from pgadmin.utils.ajax import make_json_response, precondition_required +from pgadmin.utils.ajax import make_json_response, precondition_required,\ + internal_server_error from pgadmin.utils.exception import ConnectionLost, SSHTunnelConnectionLost,\ CryptKeyMissing @@ -377,11 +378,7 @@ class PGChildNodeView(NodeView): if not conn.connected(): status, msg = conn.connect() if not status: - return precondition_required( - gettext( - "Connection to the server has been lost." - ) - ) + return internal_server_error(errormsg=msg) except (ConnectionLost, SSHTunnelConnectionLost, CryptKeyMissing): raise except Exception as e: diff --git a/web/pgadmin/dashboard/static/js/dashboard.js b/web/pgadmin/dashboard/static/js/dashboard.js index 42d2eca4b..6e466052a 100644 --- a/web/pgadmin/dashboard/static/js/dashboard.js +++ b/web/pgadmin/dashboard/static/js/dashboard.js @@ -543,6 +543,7 @@ define('pgadmin.dashboard', [ ); const WAIT_COUNTER = 3; let last_poll_wait_counter = 0; + let resp_not_received_counter = 0; /* Stop if running, only one poller lives */ self.stopChartsPoller(); @@ -563,7 +564,7 @@ define('pgadmin.dashboard', [ /* If none of the chart wants data, don't trouble * If response not received from prev poll, don't trouble !! */ - if(chart_names_to_get.length == 0 || last_poll_wait_counter > 0) { + if(chart_names_to_get.length == 0 || last_poll_wait_counter > 0 || resp_not_received_counter >= WAIT_COUNTER) { /* reduce the number of tries, request should be sent if last_poll_wait_counter * completes WAIT_COUNTER times.*/ last_poll_wait_counter--; @@ -571,12 +572,12 @@ define('pgadmin.dashboard', [ } var path = self.getStatsUrl(sid, did, chart_names_to_get); + resp_not_received_counter++; $.ajax({ url: path, type: 'GET', }) .done(function(resp) { - last_poll_wait_counter = 0; for(let chart_name in resp) { let chart_obj = chart_store[chart_name].chart_obj; $(chart_obj.getContainer()).removeClass('graph-error'); @@ -584,7 +585,6 @@ define('pgadmin.dashboard', [ } }) .fail(function(xhr) { - last_poll_wait_counter = 0; let err = ''; let msg = ''; let cls = 'info'; @@ -613,6 +613,10 @@ define('pgadmin.dashboard', [ '<div class="alert alert-' + cls + ' pg-panel-message" role="alert">' + msg + '</div>' ); } + }) + .always(function() { + last_poll_wait_counter = 0; + resp_not_received_counter--; }); last_poll_wait_counter = WAIT_COUNTER; }; 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/static/js/tree/tree.js b/web/pgadmin/static/js/tree/tree.js index 33397e80d..e317aeb81 100644 --- a/web/pgadmin/static/js/tree/tree.js +++ b/web/pgadmin/static/js/tree/tree.js @@ -9,6 +9,7 @@ import {isValidData} from 'sources/utils'; import $ from 'jquery'; +import Alertify from 'pgadmin.alertifyjs'; export class TreeNode { constructor(id, data, domNode, parent) { @@ -261,6 +262,9 @@ export class Tree { const parentId = this.translateTreeNodeIdFromACITree(api.parent(item)); this.addNewNode(id, data, item, parentId); + if(data.errmsg) { + Alertify.error(data.errmsg); + } } } }.bind(this)); diff --git a/web/pgadmin/tools/sqleditor/static/js/sqleditor.js b/web/pgadmin/tools/sqleditor/static/js/sqleditor.js index 9d9ab5c84..8f5897f3f 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) @@ -4182,8 +4183,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 { diff --git a/web/pgadmin/utils/driver/psycopg2/__init__.py b/web/pgadmin/utils/driver/psycopg2/__init__.py index 4b3e2204b..94dc2976c 100644 --- a/web/pgadmin/utils/driver/psycopg2/__init__.py +++ b/web/pgadmin/utils/driver/psycopg2/__init__.py @@ -14,19 +14,21 @@ object. """ import datetime -from flask import session, request +from flask import session from flask_login import current_user -from flask_babelex import gettext import psycopg2 from psycopg2.extensions import adapt +from threading import Lock import config -from pgadmin.model import Server, User +from pgadmin.model import Server from .keywords import ScanKeyword from ..abstract import BaseDriver from .connection import Connection from .server_manager import ServerManager +connection_restore_lock = Lock() + class Driver(BaseDriver): """ @@ -80,21 +82,30 @@ class Driver(BaseDriver): return None if session.sid not in self.managers: - self.managers[session.sid] = managers = dict() - if '__pgsql_server_managers' in session: - session_managers = session['__pgsql_server_managers'].copy() - - for server in Server.query.filter_by(user_id=current_user.id): - manager = managers[str(server.id)] = ServerManager(server) - if server.id in session_managers: - manager._restore(session_managers[server.id]) - manager.update_session() + with connection_restore_lock: + # The wait is over but the object might have been loaded + # by some other thread check again + if session.sid not in self.managers: + self.managers[session.sid] = managers = dict() + if '__pgsql_server_managers' in session: + session_managers =\ + session['__pgsql_server_managers'].copy() + for server in \ + Server.query.filter_by( + user_id=current_user.id): + manager = managers[str(server.id)] =\ + ServerManager(server) + if server.id in session_managers: + manager._restore(session_managers[server.id]) + manager.update_session() + else: managers = self.managers[session.sid] if str(sid) in managers: manager = managers[str(sid)] - manager._restore_connections() - manager.update_session() + with connection_restore_lock: + manager._restore_connections() + manager.update_session() managers['pinged'] = datetime.datetime.now() if str(sid) not in managers: diff --git a/web/pgadmin/utils/driver/psycopg2/server_manager.py b/web/pgadmin/utils/driver/psycopg2/server_manager.py index 8ae46c2ee..1676f7e38 100644 --- a/web/pgadmin/utils/driver/psycopg2/server_manager.py +++ b/web/pgadmin/utils/driver/psycopg2/server_manager.py @@ -25,13 +25,10 @@ from pgadmin.model import Server, User from pgadmin.utils.exception import ConnectionLost, SSHTunnelConnectionLost,\ CryptKeyMissing from pgadmin.utils.master_password import get_crypt_key -from threading import Lock if config.SUPPORT_SSH_TUNNEL: from sshtunnel import SSHTunnelForwarder, BaseSSHTunnelForwarderError -connection_restore_lock = Lock() - class ServerManager(object): """ @@ -292,80 +289,79 @@ WHERE db.oid = {0}""".format(did)) connections = data['connections'] - with connection_restore_lock: - for conn_id in connections: - conn_info = connections[conn_id] - if conn_info['conn_id'] in self.connections: - conn = self.connections[conn_info['conn_id']] - else: - conn = self.connections[conn_info['conn_id']] = Connection( - self, conn_info['conn_id'], conn_info['database'], - conn_info['auto_reconnect'], conn_info['async_'], - use_binary_placeholder=conn_info[ - 'use_binary_placeholder'], - array_to_string=conn_info['array_to_string'] - ) + for conn_id in connections: + conn_info = connections[conn_id] + if conn_info['conn_id'] in self.connections: + conn = self.connections[conn_info['conn_id']] + else: + conn = self.connections[conn_info['conn_id']] = Connection( + self, conn_info['conn_id'], conn_info['database'], + conn_info['auto_reconnect'], conn_info['async_'], + use_binary_placeholder=conn_info[ + 'use_binary_placeholder'], + array_to_string=conn_info['array_to_string'] + ) - # only try to reconnect if connection was connected previously - # and auto_reconnect is true. - if conn_info['wasConnected'] and conn_info['auto_reconnect']: - try: - # Check SSH Tunnel needs to be created - if self.use_ssh_tunnel == 1 and \ - not self.tunnel_created: - status, error = self.create_ssh_tunnel( - data['tunnel_password']) - - # Check SSH Tunnel is alive or not. - self.check_ssh_tunnel_alive() - - conn.connect( - password=data['password'], - server_types=ServerType.types() - ) - # This will also update wasConnected flag in - # connection so no need to update the flag manually. - except CryptKeyMissing: - # maintain the status as this will help to restore once - # the key is available - conn.wasConnected = conn_info['wasConnected'] - conn.auto_reconnect = conn_info['auto_reconnect'] - except Exception as e: - current_app.logger.exception(e) - self.connections.pop(conn_info['conn_id']) - raise + # only try to reconnect if connection was connected previously + # and auto_reconnect is true. + if conn_info['wasConnected'] and conn_info['auto_reconnect']: + try: + # Check SSH Tunnel needs to be created + if self.use_ssh_tunnel == 1 and \ + not self.tunnel_created: + status, error = self.create_ssh_tunnel( + data['tunnel_password']) + + # Check SSH Tunnel is alive or not. + self.check_ssh_tunnel_alive() + + conn.connect( + password=data['password'], + server_types=ServerType.types() + ) + # This will also update wasConnected flag in + # connection so no need to update the flag manually. + except CryptKeyMissing: + # maintain the status as this will help to restore once + # the key is available + conn.wasConnected = conn_info['wasConnected'] + conn.auto_reconnect = conn_info['auto_reconnect'] + except Exception as e: + current_app.logger.exception(e) + self.connections.pop(conn_info['conn_id']) + raise def _restore_connections(self): - with connection_restore_lock: - for conn_id in self.connections: - conn = self.connections[conn_id] - # only try to reconnect if connection was connected previously - # and auto_reconnect is true. - wasConnected = conn.wasConnected - auto_reconnect = conn.auto_reconnect - if conn.wasConnected and conn.auto_reconnect: - try: - # Check SSH Tunnel needs to be created - if self.use_ssh_tunnel == 1 and \ - not self.tunnel_created: - status, error = self.create_ssh_tunnel( - self.tunnel_password - ) - - # Check SSH Tunnel is alive or not. - self.check_ssh_tunnel_alive() + for conn_id in self.connections: + conn = self.connections[conn_id] + # only try to reconnect if connection was connected previously + # and auto_reconnect is true. + wasConnected = conn.wasConnected + auto_reconnect = conn.auto_reconnect + if conn.wasConnected and conn.auto_reconnect: + try: + # Check SSH Tunnel needs to be created + if self.use_ssh_tunnel == 1 and \ + not self.tunnel_created: + status, error = self.create_ssh_tunnel( + self.tunnel_password + ) - conn.connect() - # This will also update wasConnected flag in - # connection so no need to update the flag manually. - except CryptKeyMissing: - # maintain the status as this will help to restore once - # the key is available - conn.wasConnected = wasConnected - conn.auto_reconnect = auto_reconnect - except Exception as e: - current_app.logger.exception(e) - raise + # Check SSH Tunnel is alive or not. + self.check_ssh_tunnel_alive() + + conn.connect() + # This will also update wasConnected flag in + # connection so no need to update the flag manually. + except CryptKeyMissing: + # maintain the status as this will help to restore once + # the key is available + conn.wasConnected = wasConnected + conn.auto_reconnect = auto_reconnect + except Exception as e: + self.connections.pop(conn_id) + current_app.logger.exception(e) + raise def release(self, database=None, conn_id=None, did=None): # Stop the SSH tunnel if release() function calls without ^ permalink raw reply [nested|flat] 7+ messages in thread
* Re: [pgAdmin][RM4818] Unable to handle loss of connection to server @ 2019-11-21 06:28 Aditya Toshniwal <[email protected]> parent: Aditya Toshniwal <[email protected]> 0 siblings, 1 reply; 7+ messages in thread From: Aditya Toshniwal @ 2019-11-21 06:28 UTC (permalink / raw) To: pgadmin-hackers; +Cc: Akshay Joshi <[email protected]> Hi, I forgot to mention, I've also changed the dashboard code. The dashboard was sending graph data requests, but when the server lost connection the requests remains pending for longer time. Because of this the server gets flooded with lot of pending request and in turn slowing down the entire application. Code is changed so that only a certain number of requests remain pending (currently 3), above which the request won't be sent. On Thu, Nov 21, 2019 at 11:50 AM Aditya Toshniwal < [email protected]> wrote: > Hi Hackers, > > Attached is the updated patch to fix the review comments. > Please note, there is some problem with psycopg2/libpq where it hangs when > network is lost - https://github.com/psycopg/psycopg2/issues/561 > I've also changed the code to make connections after the "Servers" node is > expanded to fix - RM4933, so that the servers are listed first. > > Kindly review. > > On Fri, Nov 15, 2019 at 2:34 PM Akshay Joshi < > [email protected]> wrote: > >> Hi Aditya >> >> Following are the review comments: >> >> 1. The default connection timeout should be *10* seconds. >> 2. In case the network is disabled and when we expand the "Servers" >> node the database server(for which network is disabled) should be shown in >> the disconnected state. >> 3. For the above case when you try to connect to the server and at >> the same time trying to fetch the properties of the valid database server, >> it takes long time to fetch it. >> 4. Case when the network is disabled, the database servers password >> is saved and pgAdmin4 tries to connect the server, after connection >> timeout, there is no message to the user, only spinner gets disappeared. We >> should show a message. >> 5. We should improve the error messages "timeout expired" and >> "Connection to the servers has been lost." to the more meaningful messages >> like "Check the network settings, check the firewall status." >> 6. Install database server on Windows and Enable Windows Firewall. >> Try to connect to the same database server. Spinner is not showing, as a >> user I am not able to understand is there any action started at the backend >> or not. As a user, I'll keep trying to connect multiple times and after the >> connection timeout of each request dialog pops up. >> >> >> On Thu, Nov 14, 2019 at 12:15 PM Aditya Toshniwal < >> [email protected]> wrote: >> >>> 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" >>> >> >> >> -- >> *Thanks & Regards* >> *Akshay Joshi* >> >> *Sr. Software Architect* >> *EnterpriseDB Software India Private Limited* >> *Mobile: +91 976-788-8246* >> > > > -- > Thanks and Regards, > Aditya Toshniwal > Sr. Software Engineer | EnterpriseDB India | Pune > "Don't Complain about Heat, Plant a TREE" > -- Thanks and Regards, Aditya Toshniwal Sr. Software Engineer | EnterpriseDB India | Pune "Don't Complain about Heat, Plant a TREE" ^ permalink raw reply [nested|flat] 7+ messages in thread
* Re: [pgAdmin][RM4818] Unable to handle loss of connection to server @ 2019-11-21 11:18 Akshay Joshi <[email protected]> parent: Aditya Toshniwal <[email protected]> 0 siblings, 1 reply; 7+ messages in thread From: Akshay Joshi @ 2019-11-21 11:18 UTC (permalink / raw) To: Aditya Toshniwal <[email protected]>; +Cc: pgadmin-hackers Hi Aditya Following are the review comments: - Update the timeout in the comment section from 30 seconds to 10 seconds in aff1436e3c8c_.py. - Asking for the database server password even if it is saved. Reproduction steps: - Connect to the database server, saved the password. - Disabled the network. Try to connect to the database server. - Enable the network, try to connect to the database server. - No error/spinner visible on GUI when the database server is connected using SSH Tunnel. Reproduction steps: - Connect to the database server with SSH Tunnel, saved both the password. - Disabled the network and Reset the Layout. - Expand the Servers node and try to connect the same database server. On Thu, Nov 21, 2019 at 11:58 AM Aditya Toshniwal < [email protected]> wrote: > Hi, > > I forgot to mention, I've also changed the dashboard code. The dashboard > was sending graph data requests, but when the server lost connection the > requests remains pending for longer time. Because of this the server gets > flooded with lot of pending request and in turn slowing down the entire > application. > Code is changed so that only a certain number of requests remain pending > (currently 3), above which the request won't be sent. > > On Thu, Nov 21, 2019 at 11:50 AM Aditya Toshniwal < > [email protected]> wrote: > >> Hi Hackers, >> >> Attached is the updated patch to fix the review comments. >> Please note, there is some problem with psycopg2/libpq where it hangs >> when network is lost - https://github.com/psycopg/psycopg2/issues/561 >> I've also changed the code to make connections after the "Servers" node >> is expanded to fix - RM4933, so that the servers are listed first. >> >> Kindly review. >> >> On Fri, Nov 15, 2019 at 2:34 PM Akshay Joshi < >> [email protected]> wrote: >> >>> Hi Aditya >>> >>> Following are the review comments: >>> >>> 1. The default connection timeout should be *10* seconds. >>> 2. In case the network is disabled and when we expand the "Servers" >>> node the database server(for which network is disabled) should be shown in >>> the disconnected state. >>> 3. For the above case when you try to connect to the server and at >>> the same time trying to fetch the properties of the valid database server, >>> it takes long time to fetch it. >>> 4. Case when the network is disabled, the database servers password >>> is saved and pgAdmin4 tries to connect the server, after connection >>> timeout, there is no message to the user, only spinner gets disappeared. We >>> should show a message. >>> 5. We should improve the error messages "timeout expired" and >>> "Connection to the servers has been lost." to the more meaningful messages >>> like "Check the network settings, check the firewall status." >>> 6. Install database server on Windows and Enable Windows Firewall. >>> Try to connect to the same database server. Spinner is not showing, as a >>> user I am not able to understand is there any action started at the backend >>> or not. As a user, I'll keep trying to connect multiple times and after the >>> connection timeout of each request dialog pops up. >>> >>> >>> On Thu, Nov 14, 2019 at 12:15 PM Aditya Toshniwal < >>> [email protected]> wrote: >>> >>>> 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" >>>> >>> >>> >>> -- >>> *Thanks & Regards* >>> *Akshay Joshi* >>> >>> *Sr. Software Architect* >>> *EnterpriseDB Software India Private Limited* >>> *Mobile: +91 976-788-8246* >>> >> >> >> -- >> Thanks and Regards, >> Aditya Toshniwal >> Sr. Software Engineer | EnterpriseDB India | Pune >> "Don't Complain about Heat, Plant a TREE" >> > > > -- > Thanks and Regards, > Aditya Toshniwal > Sr. Software Engineer | EnterpriseDB India | Pune > "Don't Complain about Heat, Plant a TREE" > -- *Thanks & Regards* *Akshay Joshi* *Sr. Software Architect* *EnterpriseDB Software India Private Limited* *Mobile: +91 976-788-8246* ^ permalink raw reply [nested|flat] 7+ messages in thread
* Re: [pgAdmin][RM4818] Unable to handle loss of connection to server @ 2019-11-25 07:06 Aditya Toshniwal <[email protected]> parent: Akshay Joshi <[email protected]> 0 siblings, 1 reply; 7+ messages in thread From: Aditya Toshniwal @ 2019-11-25 07:06 UTC (permalink / raw) To: pgadmin-hackers; +Cc: Akshay Joshi <[email protected]> Hi Hackers, Attached is the updated patch to fix the review comments. On Thu, Nov 21, 2019 at 4:48 PM Akshay Joshi <[email protected]> wrote: > Hi Aditya > > Following are the review comments: > > > - Update the timeout in the comment section from 30 seconds to 10 > seconds in aff1436e3c8c_.py. > > > - Asking for the database server password even if it is saved. > Reproduction steps: > > > - Connect to the database server, saved the password. > - Disabled the network. Try to connect to the database server. > - Enable the network, try to connect to the database server. > > > - No error/spinner visible on GUI when the database server is > connected using SSH Tunnel. Reproduction steps: > > > - Connect to the database server with SSH Tunnel, saved both the > password. > - Disabled the network and Reset the Layout. > - Expand the Servers node and try to connect the same database > server. > > > On Thu, Nov 21, 2019 at 11:58 AM Aditya Toshniwal < > [email protected]> wrote: > >> Hi, >> >> I forgot to mention, I've also changed the dashboard code. The dashboard >> was sending graph data requests, but when the server lost connection the >> requests remains pending for longer time. Because of this the server gets >> flooded with lot of pending request and in turn slowing down the entire >> application. >> Code is changed so that only a certain number of requests remain pending >> (currently 3), above which the request won't be sent. >> >> On Thu, Nov 21, 2019 at 11:50 AM Aditya Toshniwal < >> [email protected]> wrote: >> >>> Hi Hackers, >>> >>> Attached is the updated patch to fix the review comments. >>> Please note, there is some problem with psycopg2/libpq where it hangs >>> when network is lost - https://github.com/psycopg/psycopg2/issues/561 >>> I've also changed the code to make connections after the "Servers" node >>> is expanded to fix - RM4933, so that the servers are listed first. >>> >>> Kindly review. >>> >>> On Fri, Nov 15, 2019 at 2:34 PM Akshay Joshi < >>> [email protected]> wrote: >>> >>>> Hi Aditya >>>> >>>> Following are the review comments: >>>> >>>> 1. The default connection timeout should be *10* seconds. >>>> 2. In case the network is disabled and when we expand the "Servers" >>>> node the database server(for which network is disabled) should be shown in >>>> the disconnected state. >>>> 3. For the above case when you try to connect to the server and at >>>> the same time trying to fetch the properties of the valid database server, >>>> it takes long time to fetch it. >>>> 4. Case when the network is disabled, the database servers >>>> password is saved and pgAdmin4 tries to connect the server, after >>>> connection timeout, there is no message to the user, only spinner gets >>>> disappeared. We should show a message. >>>> 5. We should improve the error messages "timeout expired" and >>>> "Connection to the servers has been lost." to the more meaningful messages >>>> like "Check the network settings, check the firewall status." >>>> 6. Install database server on Windows and Enable Windows Firewall. >>>> Try to connect to the same database server. Spinner is not showing, as a >>>> user I am not able to understand is there any action started at the backend >>>> or not. As a user, I'll keep trying to connect multiple times and after the >>>> connection timeout of each request dialog pops up. >>>> >>>> >>>> On Thu, Nov 14, 2019 at 12:15 PM Aditya Toshniwal < >>>> [email protected]> wrote: >>>> >>>>> 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" >>>>> >>>> >>>> >>>> -- >>>> *Thanks & Regards* >>>> *Akshay Joshi* >>>> >>>> *Sr. Software Architect* >>>> *EnterpriseDB Software India Private Limited* >>>> *Mobile: +91 976-788-8246* >>>> >>> >>> >>> -- >>> Thanks and Regards, >>> Aditya Toshniwal >>> Sr. Software Engineer | EnterpriseDB India | Pune >>> "Don't Complain about Heat, Plant a TREE" >>> >> >> >> -- >> Thanks and Regards, >> Aditya Toshniwal >> Sr. Software Engineer | EnterpriseDB India | Pune >> "Don't Complain about Heat, Plant a TREE" >> > > > -- > *Thanks & Regards* > *Akshay Joshi* > > *Sr. Software Architect* > *EnterpriseDB Software India Private Limited* > *Mobile: +91 976-788-8246* > -- Thanks and Regards, Aditya Toshniwal Sr. Software Engineer | EnterpriseDB India | Pune "Don't Complain about Heat, Plant a TREE" Attachments: [application/octet-stream] RM4818_v3.patch (150.2K, 3-RM4818_v3.patch) download | inline diff: diff --git a/docs/en_US/images/server_advanced.png b/docs/en_US/images/server_advanced.png old mode 100755 new mode 100644 index d7e9919e897131d86e10471dd2152cd91a45c06d..83a7ad1788bdb6691ca19a568ae09e384210caa8 GIT binary patch literal 56042 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 literal 42899 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 LwN*+Uo4xrT5_9Tc diff --git a/docs/en_US/server_dialog.rst b/docs/en_US/server_dialog.rst index 4016ba6fd..bd57e68b0 100644 --- a/docs/en_US/server_dialog.rst +++ b/docs/en_US/server_dialog.rst @@ -170,7 +170,8 @@ Use the fields in the *Advanced* tab to configure a connection: `Section 33.15 of the Postgres documentation <https://www.postgresql.org/docs/current/libpq-pgpass.html>`_. * Use the *Connection timeout* field to specify the maximum wait for connection, in seconds. Zero or not specified means wait indefinitely. It is not - recommended to use a timeout of less than 2 seconds. + recommended to use a timeout of less than 2 seconds. By default it is set to + 10 seconds. .. note:: The password file option is only supported when pgAdmin is using libpq v10.0 or later to connect to the server. diff --git a/web/migrations/versions/aff1436e3c8c_.py b/web/migrations/versions/aff1436e3c8c_.py new file mode 100644 index 000000000..7a7c3017d --- /dev/null +++ b/web/migrations/versions/aff1436e3c8c_.py @@ -0,0 +1,27 @@ + +""" Update the default timeout to 10 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=10 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..a813f7a7c 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 Error as psycopg2_Error, OperationalError def has_any(data, keys): @@ -58,7 +59,7 @@ def recovery_state(connection, postgres_version): else: in_recovery = None wal_paused = None - return in_recovery, wal_paused + return status, result, in_recovery, wal_paused def server_icon_and_background(is_connected, manager, server): @@ -121,19 +122,21 @@ class ServerModule(sg.ServerGroupPluginModule): for server in servers: connected = False manager = None + errmsg = None + was_connected = False + in_recovery = None + wal_paused = None try: manager = driver.connection_manager(server.id) conn = manager.connection() - connected = conn.connected() + was_connected = conn.wasConnected except CryptKeyMissing: # show the nodes at least even if not able to connect. pass + except psycopg2_Error as e: + current_app.logger.exception(e) + errmsg = str(e) - in_recovery = None - wal_paused = None - - if connected: - in_recovery, wal_paused = recovery_state(conn, manager.version) yield self.generate_browser_node( "%d" % (server.id), gid, @@ -151,7 +154,9 @@ class ServerModule(sg.ServerGroupPluginModule): is_password_saved=True if server.password is not None else False, is_tunnel_password_saved=True - if server.tunnel_password is not None else False + if server.tunnel_password is not None else False, + was_connected=was_connected, + errmsg=errmsg ) @property @@ -352,12 +357,16 @@ class ServerNode(PGChildNodeView): manager = driver.connection_manager(server.id) conn = manager.connection() connected = conn.connected() - + errmsg = None + in_recovery = None + wal_paused = None if connected: - in_recovery, wal_paused = recovery_state(conn, manager.version) - else: - in_recovery = None - wal_paused = None + status, result, in_recovery, wal_paused =\ + recovery_state(conn, manager.version) + if not status: + connected = False + manager.release() + errmsg = "{0} : {1}".format(server.name, result) res.append( self.blueprint.generate_browser_node( @@ -377,7 +386,8 @@ class ServerNode(PGChildNodeView): is_password_saved=True if server.password is not None else False, is_tunnel_password_saved=True - if server.tunnel_password is not None else False + if server.tunnel_password is not None else False, + errmsg=errmsg ) ) @@ -409,12 +419,16 @@ class ServerNode(PGChildNodeView): manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(server.id) conn = manager.connection() connected = conn.connected() - + errmsg = None + in_recovery = None + wal_paused = None if connected: - in_recovery, wal_paused = recovery_state(conn, manager.version) - else: - in_recovery = None - wal_paused = None + status, result, in_recovery, wal_paused =\ + recovery_state(conn, manager.version) + if not status: + connected = False + manager.release() + errmsg = "{0} : {1}".format(server.name, result) return make_json_response( result=self.blueprint.generate_browser_node( @@ -434,8 +448,9 @@ class ServerNode(PGChildNodeView): is_password_saved=True if server.password is not None else False, is_tunnel_password_saved=True - if server.tunnel_password is not None else False - ) + if server.tunnel_password is not None else False, + errmsg=errmsg + ), ) @login_required @@ -949,19 +964,33 @@ class ServerNode(PGChildNodeView): def connect_status(self, gid, sid): """Check and return the connection status.""" + server = Server.query.filter_by(id=sid).first() manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(sid) conn = manager.connection() - res = conn.connected() + connected = conn.connected() + in_recovery = None + wal_paused = None + errmsg = None + if connected: + status, result, in_recovery, wal_paused =\ + recovery_state(conn, manager.version) - if res: - from pgadmin.utils.exception import ConnectionLost, \ - SSHTunnelConnectionLost - try: - conn.execute_scalar('SELECT 1') - except (ConnectionLost, SSHTunnelConnectionLost): - res = False + if not status: + connected = False + manager.release() + errmsg = "{0} : {1}".format(server.name, result) - return make_json_response(data={'connected': res}) + return make_json_response( + data={ + 'icon': server_icon_and_background(connected, manager, server), + 'connected': connected, + 'in_recovery': in_recovery, + 'wal_pause': wal_paused, + 'server_type': manager.server_type if connected else "pg", + 'user': manager.user_info if connected else None, + 'errmsg': errmsg + } + ) def connect(self, gid, sid): """ @@ -1078,6 +1107,8 @@ class ServerNode(PGChildNodeView): tunnel_password=tunnel_password, server_types=ServerType.types() ) + except OperationalError as e: + return internal_server_error(errormsg=str(e)) except Exception as e: current_app.logger.exception(e) return self.get_response_for_password( @@ -1088,7 +1119,7 @@ class ServerNode(PGChildNodeView): errmsg = errmsg.decode('utf-8') current_app.logger.error( - "Could not connected to server(#{0}) - '{1}'.\nError: {2}" + "Could not connect to server(#{0}) - '{1}'.\nError: {2}" .format(server.id, server.name, errmsg) ) return self.get_response_for_password(server, 401, True, @@ -1125,7 +1156,8 @@ class ServerNode(PGChildNodeView): %s - %s' % (server.id, server.name)) # Update the recovery and wal pause option for the server # if connected successfully - in_recovery, wal_paused = recovery_state(conn, manager.version) + _, _, in_recovery, wal_paused =\ + recovery_state(conn, manager.version) return make_json_response( success=1, 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..843794d53 100644 --- a/web/pgadmin/browser/server_groups/servers/static/js/server.js +++ b/web/pgadmin/browser/server_groups/servers/static/js/server.js @@ -292,6 +292,10 @@ define('pgadmin.node.server', [ // Call added method of node.js pgAdmin.Browser.Node.callbacks.added.apply(this, arguments); + + if(data.was_connected) { + fetch_connection_status(this, data, pgBrowser.tree, item); + } return true; }, /* Reload configuration */ @@ -732,7 +736,7 @@ define('pgadmin.node.server', [ tunnel_password: undefined, tunnel_authentication: 0, save_tunnel_password: false, - connect_timeout: 0, + connect_timeout: 10, }, // Default values! initialize: function(attrs, args) { @@ -1273,7 +1277,14 @@ define('pgadmin.node.server', [ } }; + /* Wait till the existing request completes */ + if(data.is_connecting) { + return; + } data.is_connecting = true; + tree.setLeaf(item); + tree.removeIcon(item); + tree.addIcon(item, {icon: 'icon-server-connecting'}); var url = obj.generate_url(item, 'connect', data, true); $.post(url) .done(function(res) { @@ -1287,6 +1298,40 @@ define('pgadmin.node.server', [ return onFailure( xhr, status, error, obj, data, tree, item, wasConnected ); + }) + .always(function(){ + data.is_connecting = false; + }); + }; + var fetch_connection_status = function(obj, data, tree, item) { + var url = obj.generate_url(item, 'connect', data, true); + + tree.setLeaf(item); + tree.removeIcon(item); + tree.addIcon(item, {icon: 'icon-server-connecting'}); + $.get(url) + .done(function(res) { + tree.setInode(item); + if (res && res.data) { + if (typeof res.data.icon == 'string') { + tree.removeIcon(item); + data.icon = res.data.icon; + tree.addIcon(item, {icon: data.icon}); + } + _.extend(data, res.data); + + var serverInfo = pgBrowser.serverInfo = pgBrowser.serverInfo || {}; + serverInfo[data._id] = _.extend({}, data); + + if(data.errmsg) { + Alertify.error(data.errmsg); + } + } + }) + .fail(function(xhr, status, error) { + tree.setInode(item); + tree.addIcon(item, {icon: 'icon-server-not-connected'}); + Alertify.pgRespErrorNotify(xhr, error); }); }; } diff --git a/web/pgadmin/browser/utils.py b/web/pgadmin/browser/utils.py index 2a17b3a2d..67dce0942 100644 --- a/web/pgadmin/browser/utils.py +++ b/web/pgadmin/browser/utils.py @@ -17,7 +17,8 @@ from flask.views import View, MethodViewType, with_metaclass from flask_babelex import gettext from config import PG_DEFAULT_DRIVER -from pgadmin.utils.ajax import make_json_response, precondition_required +from pgadmin.utils.ajax import make_json_response, precondition_required,\ + internal_server_error from pgadmin.utils.exception import ConnectionLost, SSHTunnelConnectionLost,\ CryptKeyMissing @@ -377,11 +378,7 @@ class PGChildNodeView(NodeView): if not conn.connected(): status, msg = conn.connect() if not status: - return precondition_required( - gettext( - "Connection to the server has been lost." - ) - ) + return internal_server_error(errormsg=msg) except (ConnectionLost, SSHTunnelConnectionLost, CryptKeyMissing): raise except Exception as e: diff --git a/web/pgadmin/dashboard/static/js/dashboard.js b/web/pgadmin/dashboard/static/js/dashboard.js index 42d2eca4b..6e466052a 100644 --- a/web/pgadmin/dashboard/static/js/dashboard.js +++ b/web/pgadmin/dashboard/static/js/dashboard.js @@ -543,6 +543,7 @@ define('pgadmin.dashboard', [ ); const WAIT_COUNTER = 3; let last_poll_wait_counter = 0; + let resp_not_received_counter = 0; /* Stop if running, only one poller lives */ self.stopChartsPoller(); @@ -563,7 +564,7 @@ define('pgadmin.dashboard', [ /* If none of the chart wants data, don't trouble * If response not received from prev poll, don't trouble !! */ - if(chart_names_to_get.length == 0 || last_poll_wait_counter > 0) { + if(chart_names_to_get.length == 0 || last_poll_wait_counter > 0 || resp_not_received_counter >= WAIT_COUNTER) { /* reduce the number of tries, request should be sent if last_poll_wait_counter * completes WAIT_COUNTER times.*/ last_poll_wait_counter--; @@ -571,12 +572,12 @@ define('pgadmin.dashboard', [ } var path = self.getStatsUrl(sid, did, chart_names_to_get); + resp_not_received_counter++; $.ajax({ url: path, type: 'GET', }) .done(function(resp) { - last_poll_wait_counter = 0; for(let chart_name in resp) { let chart_obj = chart_store[chart_name].chart_obj; $(chart_obj.getContainer()).removeClass('graph-error'); @@ -584,7 +585,6 @@ define('pgadmin.dashboard', [ } }) .fail(function(xhr) { - last_poll_wait_counter = 0; let err = ''; let msg = ''; let cls = 'info'; @@ -613,6 +613,10 @@ define('pgadmin.dashboard', [ '<div class="alert alert-' + cls + ' pg-panel-message" role="alert">' + msg + '</div>' ); } + }) + .always(function() { + last_poll_wait_counter = 0; + resp_not_received_counter--; }); last_poll_wait_counter = WAIT_COUNTER; }; 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/static/js/tree/tree.js b/web/pgadmin/static/js/tree/tree.js index 33397e80d..e317aeb81 100644 --- a/web/pgadmin/static/js/tree/tree.js +++ b/web/pgadmin/static/js/tree/tree.js @@ -9,6 +9,7 @@ import {isValidData} from 'sources/utils'; import $ from 'jquery'; +import Alertify from 'pgadmin.alertifyjs'; export class TreeNode { constructor(id, data, domNode, parent) { @@ -261,6 +262,9 @@ export class Tree { const parentId = this.translateTreeNodeIdFromACITree(api.parent(item)); this.addNewNode(id, data, item, parentId); + if(data.errmsg) { + Alertify.error(data.errmsg); + } } } }.bind(this)); diff --git a/web/pgadmin/tools/sqleditor/static/js/sqleditor.js b/web/pgadmin/tools/sqleditor/static/js/sqleditor.js index 9d9ab5c84..8f5897f3f 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) @@ -4182,8 +4183,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 { diff --git a/web/pgadmin/utils/driver/psycopg2/__init__.py b/web/pgadmin/utils/driver/psycopg2/__init__.py index 4b3e2204b..94dc2976c 100644 --- a/web/pgadmin/utils/driver/psycopg2/__init__.py +++ b/web/pgadmin/utils/driver/psycopg2/__init__.py @@ -14,19 +14,21 @@ object. """ import datetime -from flask import session, request +from flask import session from flask_login import current_user -from flask_babelex import gettext import psycopg2 from psycopg2.extensions import adapt +from threading import Lock import config -from pgadmin.model import Server, User +from pgadmin.model import Server from .keywords import ScanKeyword from ..abstract import BaseDriver from .connection import Connection from .server_manager import ServerManager +connection_restore_lock = Lock() + class Driver(BaseDriver): """ @@ -80,21 +82,30 @@ class Driver(BaseDriver): return None if session.sid not in self.managers: - self.managers[session.sid] = managers = dict() - if '__pgsql_server_managers' in session: - session_managers = session['__pgsql_server_managers'].copy() - - for server in Server.query.filter_by(user_id=current_user.id): - manager = managers[str(server.id)] = ServerManager(server) - if server.id in session_managers: - manager._restore(session_managers[server.id]) - manager.update_session() + with connection_restore_lock: + # The wait is over but the object might have been loaded + # by some other thread check again + if session.sid not in self.managers: + self.managers[session.sid] = managers = dict() + if '__pgsql_server_managers' in session: + session_managers =\ + session['__pgsql_server_managers'].copy() + for server in \ + Server.query.filter_by( + user_id=current_user.id): + manager = managers[str(server.id)] =\ + ServerManager(server) + if server.id in session_managers: + manager._restore(session_managers[server.id]) + manager.update_session() + else: managers = self.managers[session.sid] if str(sid) in managers: manager = managers[str(sid)] - manager._restore_connections() - manager.update_session() + with connection_restore_lock: + manager._restore_connections() + manager.update_session() managers['pinged'] = datetime.datetime.now() if str(sid) not in managers: diff --git a/web/pgadmin/utils/driver/psycopg2/server_manager.py b/web/pgadmin/utils/driver/psycopg2/server_manager.py index 8ae46c2ee..1676f7e38 100644 --- a/web/pgadmin/utils/driver/psycopg2/server_manager.py +++ b/web/pgadmin/utils/driver/psycopg2/server_manager.py @@ -25,13 +25,10 @@ from pgadmin.model import Server, User from pgadmin.utils.exception import ConnectionLost, SSHTunnelConnectionLost,\ CryptKeyMissing from pgadmin.utils.master_password import get_crypt_key -from threading import Lock if config.SUPPORT_SSH_TUNNEL: from sshtunnel import SSHTunnelForwarder, BaseSSHTunnelForwarderError -connection_restore_lock = Lock() - class ServerManager(object): """ @@ -292,80 +289,79 @@ WHERE db.oid = {0}""".format(did)) connections = data['connections'] - with connection_restore_lock: - for conn_id in connections: - conn_info = connections[conn_id] - if conn_info['conn_id'] in self.connections: - conn = self.connections[conn_info['conn_id']] - else: - conn = self.connections[conn_info['conn_id']] = Connection( - self, conn_info['conn_id'], conn_info['database'], - conn_info['auto_reconnect'], conn_info['async_'], - use_binary_placeholder=conn_info[ - 'use_binary_placeholder'], - array_to_string=conn_info['array_to_string'] - ) + for conn_id in connections: + conn_info = connections[conn_id] + if conn_info['conn_id'] in self.connections: + conn = self.connections[conn_info['conn_id']] + else: + conn = self.connections[conn_info['conn_id']] = Connection( + self, conn_info['conn_id'], conn_info['database'], + conn_info['auto_reconnect'], conn_info['async_'], + use_binary_placeholder=conn_info[ + 'use_binary_placeholder'], + array_to_string=conn_info['array_to_string'] + ) - # only try to reconnect if connection was connected previously - # and auto_reconnect is true. - if conn_info['wasConnected'] and conn_info['auto_reconnect']: - try: - # Check SSH Tunnel needs to be created - if self.use_ssh_tunnel == 1 and \ - not self.tunnel_created: - status, error = self.create_ssh_tunnel( - data['tunnel_password']) - - # Check SSH Tunnel is alive or not. - self.check_ssh_tunnel_alive() - - conn.connect( - password=data['password'], - server_types=ServerType.types() - ) - # This will also update wasConnected flag in - # connection so no need to update the flag manually. - except CryptKeyMissing: - # maintain the status as this will help to restore once - # the key is available - conn.wasConnected = conn_info['wasConnected'] - conn.auto_reconnect = conn_info['auto_reconnect'] - except Exception as e: - current_app.logger.exception(e) - self.connections.pop(conn_info['conn_id']) - raise + # only try to reconnect if connection was connected previously + # and auto_reconnect is true. + if conn_info['wasConnected'] and conn_info['auto_reconnect']: + try: + # Check SSH Tunnel needs to be created + if self.use_ssh_tunnel == 1 and \ + not self.tunnel_created: + status, error = self.create_ssh_tunnel( + data['tunnel_password']) + + # Check SSH Tunnel is alive or not. + self.check_ssh_tunnel_alive() + + conn.connect( + password=data['password'], + server_types=ServerType.types() + ) + # This will also update wasConnected flag in + # connection so no need to update the flag manually. + except CryptKeyMissing: + # maintain the status as this will help to restore once + # the key is available + conn.wasConnected = conn_info['wasConnected'] + conn.auto_reconnect = conn_info['auto_reconnect'] + except Exception as e: + current_app.logger.exception(e) + self.connections.pop(conn_info['conn_id']) + raise def _restore_connections(self): - with connection_restore_lock: - for conn_id in self.connections: - conn = self.connections[conn_id] - # only try to reconnect if connection was connected previously - # and auto_reconnect is true. - wasConnected = conn.wasConnected - auto_reconnect = conn.auto_reconnect - if conn.wasConnected and conn.auto_reconnect: - try: - # Check SSH Tunnel needs to be created - if self.use_ssh_tunnel == 1 and \ - not self.tunnel_created: - status, error = self.create_ssh_tunnel( - self.tunnel_password - ) - - # Check SSH Tunnel is alive or not. - self.check_ssh_tunnel_alive() + for conn_id in self.connections: + conn = self.connections[conn_id] + # only try to reconnect if connection was connected previously + # and auto_reconnect is true. + wasConnected = conn.wasConnected + auto_reconnect = conn.auto_reconnect + if conn.wasConnected and conn.auto_reconnect: + try: + # Check SSH Tunnel needs to be created + if self.use_ssh_tunnel == 1 and \ + not self.tunnel_created: + status, error = self.create_ssh_tunnel( + self.tunnel_password + ) - conn.connect() - # This will also update wasConnected flag in - # connection so no need to update the flag manually. - except CryptKeyMissing: - # maintain the status as this will help to restore once - # the key is available - conn.wasConnected = wasConnected - conn.auto_reconnect = auto_reconnect - except Exception as e: - current_app.logger.exception(e) - raise + # Check SSH Tunnel is alive or not. + self.check_ssh_tunnel_alive() + + conn.connect() + # This will also update wasConnected flag in + # connection so no need to update the flag manually. + except CryptKeyMissing: + # maintain the status as this will help to restore once + # the key is available + conn.wasConnected = wasConnected + conn.auto_reconnect = auto_reconnect + except Exception as e: + self.connections.pop(conn_id) + current_app.logger.exception(e) + raise def release(self, database=None, conn_id=None, did=None): # Stop the SSH tunnel if release() function calls without ^ permalink raw reply [nested|flat] 7+ messages in thread
* Re: [pgAdmin][RM4818] Unable to handle loss of connection to server @ 2019-11-26 03:37 Akshay Joshi <[email protected]> parent: Aditya Toshniwal <[email protected]> 0 siblings, 0 replies; 7+ messages in thread From: Akshay Joshi @ 2019-11-26 03:37 UTC (permalink / raw) To: Aditya Toshniwal <[email protected]>; +Cc: pgadmin-hackers Thanks, patch applied. On Mon, Nov 25, 2019 at 12:37 PM Aditya Toshniwal < [email protected]> wrote: > Hi Hackers, > > Attached is the updated patch to fix the review comments. > > On Thu, Nov 21, 2019 at 4:48 PM Akshay Joshi < > [email protected]> wrote: > >> Hi Aditya >> >> Following are the review comments: >> >> >> - Update the timeout in the comment section from 30 seconds to 10 >> seconds in aff1436e3c8c_.py. >> >> >> - Asking for the database server password even if it is saved. >> Reproduction steps: >> >> >> - Connect to the database server, saved the password. >> - Disabled the network. Try to connect to the database server. >> - Enable the network, try to connect to the database server. >> >> >> - No error/spinner visible on GUI when the database server is >> connected using SSH Tunnel. Reproduction steps: >> >> >> - Connect to the database server with SSH Tunnel, saved both the >> password. >> - Disabled the network and Reset the Layout. >> - Expand the Servers node and try to connect the same database >> server. >> >> >> On Thu, Nov 21, 2019 at 11:58 AM Aditya Toshniwal < >> [email protected]> wrote: >> >>> Hi, >>> >>> I forgot to mention, I've also changed the dashboard code. The dashboard >>> was sending graph data requests, but when the server lost connection the >>> requests remains pending for longer time. Because of this the server gets >>> flooded with lot of pending request and in turn slowing down the entire >>> application. >>> Code is changed so that only a certain number of requests remain pending >>> (currently 3), above which the request won't be sent. >>> >>> On Thu, Nov 21, 2019 at 11:50 AM Aditya Toshniwal < >>> [email protected]> wrote: >>> >>>> Hi Hackers, >>>> >>>> Attached is the updated patch to fix the review comments. >>>> Please note, there is some problem with psycopg2/libpq where it hangs >>>> when network is lost - https://github.com/psycopg/psycopg2/issues/561 >>>> I've also changed the code to make connections after the "Servers" node >>>> is expanded to fix - RM4933, so that the servers are listed first. >>>> >>>> Kindly review. >>>> >>>> On Fri, Nov 15, 2019 at 2:34 PM Akshay Joshi < >>>> [email protected]> wrote: >>>> >>>>> Hi Aditya >>>>> >>>>> Following are the review comments: >>>>> >>>>> 1. The default connection timeout should be *10* seconds. >>>>> 2. In case the network is disabled and when we expand the >>>>> "Servers" node the database server(for which network is disabled) should be >>>>> shown in the disconnected state. >>>>> 3. For the above case when you try to connect to the server and >>>>> at the same time trying to fetch the properties of the valid database >>>>> server, it takes long time to fetch it. >>>>> 4. Case when the network is disabled, the database servers >>>>> password is saved and pgAdmin4 tries to connect the server, after >>>>> connection timeout, there is no message to the user, only spinner gets >>>>> disappeared. We should show a message. >>>>> 5. We should improve the error messages "timeout expired" and >>>>> "Connection to the servers has been lost." to the more meaningful messages >>>>> like "Check the network settings, check the firewall status." >>>>> 6. Install database server on Windows and Enable Windows Firewall. >>>>> Try to connect to the same database server. Spinner is not showing, as a >>>>> user I am not able to understand is there any action started at the backend >>>>> or not. As a user, I'll keep trying to connect multiple times and after the >>>>> connection timeout of each request dialog pops up. >>>>> >>>>> >>>>> On Thu, Nov 14, 2019 at 12:15 PM Aditya Toshniwal < >>>>> [email protected]> wrote: >>>>> >>>>>> 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" >>>>>> >>>>> >>>>> >>>>> -- >>>>> *Thanks & Regards* >>>>> *Akshay Joshi* >>>>> >>>>> *Sr. Software Architect* >>>>> *EnterpriseDB Software India Private Limited* >>>>> *Mobile: +91 976-788-8246* >>>>> >>>> >>>> >>>> -- >>>> Thanks and Regards, >>>> Aditya Toshniwal >>>> Sr. Software Engineer | EnterpriseDB India | Pune >>>> "Don't Complain about Heat, Plant a TREE" >>>> >>> >>> >>> -- >>> Thanks and Regards, >>> Aditya Toshniwal >>> Sr. Software Engineer | EnterpriseDB India | Pune >>> "Don't Complain about Heat, Plant a TREE" >>> >> >> >> -- >> *Thanks & Regards* >> *Akshay Joshi* >> >> *Sr. Software Architect* >> *EnterpriseDB Software India Private Limited* >> *Mobile: +91 976-788-8246* >> > > > -- > Thanks and Regards, > Aditya Toshniwal > Sr. Software Engineer | EnterpriseDB India | Pune > "Don't Complain about Heat, Plant a TREE" > -- *Thanks & Regards* *Akshay Joshi* *Sr. Software Architect* *EnterpriseDB Software India Private Limited* *Mobile: +91 976-788-8246* ^ permalink raw reply [nested|flat] 7+ messages in thread
end of thread, other threads:[~2019-11-26 03:37 UTC | newest] Thread overview: 7+ messages (download: mbox mbox.gz follow: Atom feed) -- links below jump to the message on this page -- 2019-11-14 06:44 [pgAdmin][RM4818] Unable to handle loss of connection to server Aditya Toshniwal <[email protected]> 2019-11-15 09:04 ` Akshay Joshi <[email protected]> 2019-11-21 06:20 ` Aditya Toshniwal <[email protected]> 2019-11-21 06:28 ` Aditya Toshniwal <[email protected]> 2019-11-21 11:18 ` Akshay Joshi <[email protected]> 2019-11-25 07:06 ` Aditya Toshniwal <[email protected]> 2019-11-26 03:37 ` Akshay Joshi <[email protected]>
This inbox is served by agora; see mirroring instructions for how to clone and mirror all data and code used for this inbox