Fixed the server heartbeat logging issue when server is removed. #5567

This commit is contained in:
Khushboo Vashi
2023-01-30 15:39:34 +05:30
committed by GitHub
parent ea3dffe78d
commit 7a18ceab64
5 changed files with 85 additions and 22 deletions

View File

@@ -227,6 +227,9 @@ define('pgadmin.node.server', [
} }
t.unload(i); t.unload(i);
} }
pgBrowser.Events.trigger(
'pgadmin:server:disconnect', {item: i, data: d}, false
);
}}) }})
.fail(function(xhr, status, error) { .fail(function(xhr, status, error) {
Notify.pgRespErrorNotify(xhr, error); Notify.pgRespErrorNotify(xhr, error);

View File

@@ -15,7 +15,7 @@ import Notify, {initializeModalProvider, initializeNotifier} from '../../../stat
import { checkMasterPassword } from '../../../static/js/Dialogs/index'; import { checkMasterPassword } from '../../../static/js/Dialogs/index';
import { pgHandleItemError } from '../../../static/js/utils'; import { pgHandleItemError } from '../../../static/js/utils';
import { Search } from './quick_search/trigger_search'; import { Search } from './quick_search/trigger_search';
import { send_heartbeat } from './heartbeat'; import { send_heartbeat, stop_heartbeat } from './heartbeat';
define('pgadmin.browser', [ define('pgadmin.browser', [
'sources/gettext', 'sources/url_for', 'require', 'jquery', 'sources/gettext', 'sources/url_for', 'require', 'jquery',
@@ -586,6 +586,10 @@ define('pgadmin.browser', [
'pgadmin:server:connected', send_heartbeat.bind(obj) 'pgadmin:server:connected', send_heartbeat.bind(obj)
); );
obj.Events.on(
'pgadmin:server:disconnect', stop_heartbeat.bind(obj)
);
obj.set_master_password(''); obj.set_master_password('');
obj.check_corrupted_db_file(); obj.check_corrupted_db_file();
obj.Events.on('pgadmin:browser:tree:add', obj.onAddTreeNode.bind(obj)); obj.Events.on('pgadmin:browser:tree:add', obj.onAddTreeNode.bind(obj));

View File

@@ -16,16 +16,32 @@ import pgAdmin from 'sources/pgadmin';
const axiosApi = getApiInstance(); const axiosApi = getApiInstance();
let HEARTBEAT_TIMEOUT = pgAdmin.heartbeat_timeout * 1000; let HEARTBEAT_TIMEOUT = pgAdmin.heartbeat_timeout * 1000;
export function send_heartbeat(_server_id) { export function send_heartbeat(_server_id, _item) {
// Send heartbeat to the server every 30 seconds // Send heartbeat to the server every 30 seconds
setInterval(function() { _item.heartbeat = setInterval(function() {
axiosApi.post(url_for('misc.heartbeat'), {'sid': _server_id}) axiosApi.post(url_for('misc.log_heartbeat'), {'sid': _server_id})
.then(() => { .then((data) => {
// pass if (data.status !== 200) {
stop_heartbeat(_item);
}
}) })
.catch((error) => { .catch((error) => {
if (error && error.message == 'Network Error') {
Notifier.error(gettext(`pgAdmin server not responding, try to login again: ${error.message || error.response.data.errormsg}`)); Notifier.error(gettext(`pgAdmin server not responding, try to login again: ${error.message || error.response.data.errormsg}`));
} else {
Notifier.error(gettext(`Server heartbeat logging error: ${error.message || error.response.data.errormsg}`));
}
stop_heartbeat(_item);
}); });
}, HEARTBEAT_TIMEOUT); }, HEARTBEAT_TIMEOUT);
} }
export function stop_heartbeat(_obj) {
let _item = _obj.item || _obj,
_id = _item.getMetadata('data')._id;
clearInterval(_item.heartbeat);
axiosApi.post(url_for('misc.stop_heartbeat'), {'sid': _id});
}

View File

@@ -19,7 +19,8 @@ from pgadmin.utils.session import cleanup_session_files
from pgadmin.misc.themes import get_all_themes from pgadmin.misc.themes import get_all_themes
from pgadmin.utils.constants import MIMETYPE_APP_JS, UTILITIES_ARRAY from pgadmin.utils.constants import MIMETYPE_APP_JS, UTILITIES_ARRAY
from pgadmin.utils.ajax import precondition_required, make_json_response from pgadmin.utils.ajax import precondition_required, make_json_response
from pgadmin.utils.heartbeat import log_server_heartbeat, get_server_heartbeat from pgadmin.utils.heartbeat import log_server_heartbeat,\
get_server_heartbeat, stop_server_heartbeat
import config import config
import subprocess import subprocess
import os import os
@@ -94,8 +95,8 @@ class MiscModule(PgAdminModule):
list: a list of url endpoints exposed to the client. list: a list of url endpoints exposed to the client.
""" """
return ['misc.ping', 'misc.index', 'misc.cleanup', return ['misc.ping', 'misc.index', 'misc.cleanup',
'misc.validate_binary_path', 'misc.heartbeat', 'misc.validate_binary_path', 'misc.log_heartbeat',
'misc.get_heartbeat'] 'misc.stop_heartbeat', 'misc.get_heartbeat']
def register(self, app, options): def register(self, app, options):
""" """
@@ -158,9 +159,9 @@ def cleanup():
return "" return ""
@blueprint.route("/heartbeat", methods=['POST']) @blueprint.route("/heartbeat/log", methods=['POST'])
@pgCSRFProtect.exempt @pgCSRFProtect.exempt
def heartbeat(): def log_heartbeat():
data = None data = None
if hasattr(request.data, 'decode'): if hasattr(request.data, 'decode'):
data = request.data.decode('utf-8') data = request.data.decode('utf-8')
@@ -168,8 +169,25 @@ def heartbeat():
if data != '': if data != '':
data = json.loads(data) data = json.loads(data)
log_server_heartbeat(data) status, msg = log_server_heartbeat(data)
return make_json_response(data=gettext('Heartbeat logged successfully.'), if status:
return make_json_response(data=msg, status=200)
else:
return make_json_response(data=msg, status=404)
@blueprint.route("/heartbeat/stop", methods=['POST'])
@pgCSRFProtect.exempt
def stop_heartbeat():
data = None
if hasattr(request.data, 'decode'):
data = request.data.decode('utf-8')
if data != '':
data = json.loads(data)
status, msg = stop_server_heartbeat(data)
return make_json_response(data=msg,
status=200) status=200)

View File

@@ -14,6 +14,7 @@ import threading
import datetime import datetime
import config import config
from flask import session, current_app from flask import session, current_app
from flask_babel import gettext
def log_server_heartbeat(data): def log_server_heartbeat(data):
@@ -28,17 +29,38 @@ def log_server_heartbeat(data):
if session.sid not in _server_heartbeat: if session.sid not in _server_heartbeat:
_server_heartbeat[session.sid] = {} _server_heartbeat[session.sid] = {}
if not manager:
stop_server_heartbeat(data)
return False, gettext("Manager not found. Stopped Heartbeat logging.")
else:
_server_heartbeat[session.sid][data['sid']] = { _server_heartbeat[session.sid][data['sid']] = {
'timestamp': datetime.datetime.now(), 'timestamp': datetime.datetime.now(),
'conn': manager.connections 'conn': manager.connections
} }
setattr(current_app, '_pgadmin_server_heartbeat', _server_heartbeat)
current_app.logger.debug( current_app.logger.debug(
"Heartbeat logged for the session id##server id: {0}##{1}".format( "Heartbeat logged for the session id##server id: {0}##{1}".format(
session.sid, data['sid'])) session.sid, data['sid']))
setattr(current_app, '_pgadmin_server_heartbeat', _server_heartbeat)
return True, gettext("Heartbeat logged successfully.")
def stop_server_heartbeat(data):
"""Stop logging server heartbeat."""
_server_heartbeat = getattr(current_app, '_pgadmin_server_heartbeat', {})
if session.sid in _server_heartbeat and \
data['sid'] in _server_heartbeat[session.sid]:
_server_heartbeat[session.sid].pop(data['sid'])
current_app.logger.debug(
"Heartbeat logging stopped for the session"
" id##server id: {0}##{1}".format(session.sid, data['sid']))
setattr(current_app, '_pgadmin_server_heartbeat', _server_heartbeat)
return True, gettext("Stopped Heartbeat logging.")
def get_server_heartbeat(server_id): def get_server_heartbeat(server_id):
_server_heartbeat = getattr(current_app, '_pgadmin_server_heartbeat', {}) _server_heartbeat = getattr(current_app, '_pgadmin_server_heartbeat', {})