From a77cb9447d0ef7198674425879124cf1a14247b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Carlos=20de=20Lima=20Roscoe?= Date: Sun, 3 Mar 2024 03:21:34 -0300 Subject: [PATCH 1/5] Reset db connection on message reception, if needed (new config data) --- postgresql.js | 90 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 66 insertions(+), 24 deletions(-) diff --git a/postgresql.js b/postgresql.js index b428406..e157dac 100644 --- a/postgresql.js +++ b/postgresql.js @@ -51,6 +51,38 @@ module.exports = function (RED) { } } + function changed(cnfg, prevCnfg) { + if (cnfg === undefined) { + return undefined; + } + else if (prevCnfg === undefined) { + return true; + } + else { + // Perform actual comparison + let result = false; + const cnfgKeys = Object.keys(cnfg).sort(); + const prevCnfgKeys = Object.keys(prevCnfg).sort(); + // Check for different numbers of keys + if (cnfgKeys.length !== prevCnfgKeys.length) { + result = true; + } + else { + // Same nambers of keys - check for at least one changed key + if (!(cnfgKeys.every((key, index) => key === prevCnfgKeys[index]))) { + result = true + } + else { + // Same keys - check for at least one changed value + if (!(cnfgKeys.every((key) => cnfg[key] === prevCnfg[key]))) { + result = true; + } + } + } + return result; + } + } + function PostgreSQLConfigNode(n) { const node = this; RED.nodes.createNode(node, n); @@ -75,22 +107,6 @@ module.exports = function (RED) { node.passwordFieldType = n.passwordFieldType; node.connectionTimeout = n.connectionTimeout; node.connectionTimeoutFieldType = n.connectionTimeoutFieldType; - - this.pgPool = new Pool({ - user: getField(node, n.userFieldType, n.user), - password: getField(node, n.passwordFieldType, n.password), - host: getField(node, n.hostFieldType, n.host), - port: getField(node, n.portFieldType, n.port), - database: getField(node, n.databaseFieldType, n.database), - ssl: getField(node, n.sslFieldType, n.ssl), - application_name: getField(node, n.applicationNameType, n.applicationName), - max: getField(node, n.maxFieldType, n.max), - idleTimeoutMillis: getField(node, n.idleFieldType, n.idle), - connectionTimeoutMillis: getField(node, n.connectionTimeoutFieldType, n.connectionTimeout), - }); - this.pgPool.on('error', (err, _) => { - node.error(err.message); - }); } RED.nodes.registerType('postgreSQLConfig', PostgreSQLConfigNode); @@ -102,11 +118,8 @@ module.exports = function (RED) { node.query = config.query; node.split = config.split; node.rowsPerMsg = config.rowsPerMsg; - node.config = RED.nodes.getNode(config.postgreSQLConfig) || { - pgPool: { - totalCount: 0, - }, - }; + node.config = RED.nodes.getNode(config.postgreSQLConfig) || {}; + let pgPool = { totalCount: 0, end: null}; // Declare the ability of this node to provide ticks upstream for back-pressure node.tickProvider = true; @@ -137,14 +150,14 @@ module.exports = function (RED) { fill = 'red'; } else if (nbQueue <= 0) { fill = 'blue'; - } else if (nbQueue <= node.config.pgPool.totalCount) { + } else if (nbQueue <= pgPool.totalCount) { fill = 'green'; } else { fill = 'yellow'; } node.status({ fill, - shape: hasError || nbQueue > node.config.pgPool.totalCount ? 'ring' : 'dot', + shape: hasError || nbQueue > pgPool.totalCount ? 'ring' : 'dot', text: 'Queue: ' + nbQueue + (hasError ? ' Error!' : ''), }); hasError = false; @@ -155,6 +168,35 @@ module.exports = function (RED) { updateStatus(0, false); node.on('input', async (msg, send, done) => { + + // Get current db access configuration data + let dbAccessCfgData = {}; + dbAccessCfgData.user = getField(node, node.config.userFieldType, node.config.user); + dbAccessCfgData.password = getField(node, node.config.passwordFieldType, node.config.password); + dbAccessCfgData.host = getField(node, node.config.hostFieldType, node.config.host); + dbAccessCfgData.port = getField(node, node.config.portFieldType, node.config.port); + dbAccessCfgData.database = getField(node, node.config.databaseFieldType, node.config.database); + dbAccessCfgData.ssl = getField(node, node.config.sslFieldType, node.config.ssl); + dbAccessCfgData.application_name = getField(node, node.config.applicationNameType, node.config.applicationName); + dbAccessCfgData.max = getField(node, node.config.maxFieldType, node.config.max); + dbAccessCfgData.idleTimeoutMillis = getField(node, node.config.idleFieldType, node.config.idle); + dbAccessCfgData.connectionTimeoutMillis = getField(node, node.config.connectionTimeoutFieldType, node.config.connectionTimeout); + + // Get previous db access configuration data + const nodeContext = node.context(); + const previousDbAccessCfgData = nodeContext.get('previousDbAccessCfgData') + + if (changed(dbAccessCfgData, previousDbAccessCfgData)) + { + // Reset connections pool + if (pgPool.end !== null) { + pgPool.end(); + } + pgPool = new Pool(dbAccessCfgData); + // Update previous db access configuration datain context + nodeContext.set('previousDbAccessCfgData',dbAccessCfgData) + } + // 'send' and 'done' require Node-RED 1.0+ send = send || function () { node.send.apply(node, arguments); }; @@ -223,7 +265,7 @@ module.exports = function (RED) { client = new Client(msg.pgConfig); await client.connect(); } else { - client = await node.config.pgPool.connect(); + client = await pgPool.connect(); } let params = []; From 4330fcd9ec0cae7b3c49c311b97bdcf65fb9bfe3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Carlos=20de=20Lima=20Roscoe?= Date: Sun, 3 Mar 2024 12:02:51 -0300 Subject: [PATCH 2/5] Move back connection pool object into configuration node --- postgresql.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/postgresql.js b/postgresql.js index e157dac..c49da67 100644 --- a/postgresql.js +++ b/postgresql.js @@ -119,7 +119,7 @@ module.exports = function (RED) { node.split = config.split; node.rowsPerMsg = config.rowsPerMsg; node.config = RED.nodes.getNode(config.postgreSQLConfig) || {}; - let pgPool = { totalCount: 0, end: null}; + node.config.pgPool = { totalCount: 0, end: null}; // Declare the ability of this node to provide ticks upstream for back-pressure node.tickProvider = true; @@ -150,14 +150,14 @@ module.exports = function (RED) { fill = 'red'; } else if (nbQueue <= 0) { fill = 'blue'; - } else if (nbQueue <= pgPool.totalCount) { + } else if (nbQueue <= node.config.pgPool.totalCount) { fill = 'green'; } else { fill = 'yellow'; } node.status({ fill, - shape: hasError || nbQueue > pgPool.totalCount ? 'ring' : 'dot', + shape: hasError || nbQueue > node.config.pgPool.totalCount ? 'ring' : 'dot', text: 'Queue: ' + nbQueue + (hasError ? ' Error!' : ''), }); hasError = false; @@ -189,10 +189,10 @@ module.exports = function (RED) { if (changed(dbAccessCfgData, previousDbAccessCfgData)) { // Reset connections pool - if (pgPool.end !== null) { - pgPool.end(); + if (node.config.pgPool.end !== null) { + node.config.pgPool.end(); } - pgPool = new Pool(dbAccessCfgData); + node.config.pgPool = new Pool(dbAccessCfgData); // Update previous db access configuration datain context nodeContext.set('previousDbAccessCfgData',dbAccessCfgData) } @@ -265,7 +265,7 @@ module.exports = function (RED) { client = new Client(msg.pgConfig); await client.connect(); } else { - client = await pgPool.connect(); + client = await node.config.pgPool.connect(); } let params = []; From c1d192fd7a809c092b3e82a8d00cac78800f907b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Carlos=20de=20Lima=20Roscoe?= Date: Mon, 4 Mar 2024 09:30:15 -0300 Subject: [PATCH 3/5] Fix linter findings --- postgresql.js | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/postgresql.js b/postgresql.js index c49da67..b95c5c6 100644 --- a/postgresql.js +++ b/postgresql.js @@ -54,11 +54,9 @@ module.exports = function (RED) { function changed(cnfg, prevCnfg) { if (cnfg === undefined) { return undefined; - } - else if (prevCnfg === undefined) { + } else if (prevCnfg === undefined) { return true; - } - else { + } else { // Perform actual comparison let result = false; const cnfgKeys = Object.keys(cnfg).sort(); @@ -66,13 +64,11 @@ module.exports = function (RED) { // Check for different numbers of keys if (cnfgKeys.length !== prevCnfgKeys.length) { result = true; - } - else { + } else { // Same nambers of keys - check for at least one changed key if (!(cnfgKeys.every((key, index) => key === prevCnfgKeys[index]))) { - result = true - } - else { + result = true; + } else { // Same keys - check for at least one changed value if (!(cnfgKeys.every((key) => cnfg[key] === prevCnfg[key]))) { result = true; @@ -119,7 +115,7 @@ module.exports = function (RED) { node.split = config.split; node.rowsPerMsg = config.rowsPerMsg; node.config = RED.nodes.getNode(config.postgreSQLConfig) || {}; - node.config.pgPool = { totalCount: 0, end: null}; + node.config.pgPool = { totalCount: 0, end: null }; // Declare the ability of this node to provide ticks upstream for back-pressure node.tickProvider = true; @@ -168,9 +164,8 @@ module.exports = function (RED) { updateStatus(0, false); node.on('input', async (msg, send, done) => { - // Get current db access configuration data - let dbAccessCfgData = {}; + const dbAccessCfgData = {}; dbAccessCfgData.user = getField(node, node.config.userFieldType, node.config.user); dbAccessCfgData.password = getField(node, node.config.passwordFieldType, node.config.password); dbAccessCfgData.host = getField(node, node.config.hostFieldType, node.config.host); @@ -184,17 +179,16 @@ module.exports = function (RED) { // Get previous db access configuration data const nodeContext = node.context(); - const previousDbAccessCfgData = nodeContext.get('previousDbAccessCfgData') + const previousDbAccessCfgData = nodeContext.get('previousDbAccessCfgData'); - if (changed(dbAccessCfgData, previousDbAccessCfgData)) - { + if (changed(dbAccessCfgData, previousDbAccessCfgData)) { // Reset connections pool if (node.config.pgPool.end !== null) { node.config.pgPool.end(); } node.config.pgPool = new Pool(dbAccessCfgData); // Update previous db access configuration datain context - nodeContext.set('previousDbAccessCfgData',dbAccessCfgData) + nodeContext.set('previousDbAccessCfgData', dbAccessCfgData); } // 'send' and 'done' require Node-RED 1.0+ From 31250357ed5bbfaf17336bab99465cd7a3a1bafb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Carlos=20de=20Lima=20Roscoe?= Date: Mon, 4 Mar 2024 09:44:12 -0300 Subject: [PATCH 4/5] Simplify changes check (don't need full objects comparison) --- postgresql.js | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/postgresql.js b/postgresql.js index b95c5c6..04905f5 100644 --- a/postgresql.js +++ b/postgresql.js @@ -58,24 +58,12 @@ module.exports = function (RED) { return true; } else { // Perform actual comparison - let result = false; const cnfgKeys = Object.keys(cnfg).sort(); - const prevCnfgKeys = Object.keys(prevCnfg).sort(); - // Check for different numbers of keys - if (cnfgKeys.length !== prevCnfgKeys.length) { - result = true; - } else { - // Same nambers of keys - check for at least one changed key - if (!(cnfgKeys.every((key, index) => key === prevCnfgKeys[index]))) { - result = true; - } else { - // Same keys - check for at least one changed value - if (!(cnfgKeys.every((key) => cnfg[key] === prevCnfg[key]))) { - result = true; - } - } + // Check for at least one changed value + if (!(cnfgKeys.every((key) => cnfg[key] === prevCnfg[key]))) { + return true; } - return result; + return false; } } From f817ebe608a98409436523b06f9d8713ddc79aa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Carlos=20de=20Lima=20Roscoe?= Date: Thu, 7 Mar 2024 19:13:14 -0300 Subject: [PATCH 5/5] Monitor changes to flagged parameters, only; support "reconnect in msg --- locales/en-US/postgresql.json | 6 ++ postgresql.html | 88 ++++++++++++++++++++++--- postgresql.js | 119 +++++++++++++++++++++++----------- 3 files changed, 168 insertions(+), 45 deletions(-) diff --git a/locales/en-US/postgresql.json b/locales/en-US/postgresql.json index 5b197d2..8db8292 100644 --- a/locales/en-US/postgresql.json +++ b/locales/en-US/postgresql.json @@ -3,11 +3,17 @@ "label": { "name": "Name", "host": "Host", + "hostWatch": "Watch host changes", "port": "Port", + "portWatch": "Watch port changes", "database": "Database", + "databaseWatch": "Watch database changes", "ssl": "SSL", + "sslWatch": "Watch SSL changes", "user": "User", + "userWatch": "Watch user changes", "password": "Password", + "passwordWatch": "Watch password changes", "applicationName": "Application name", "max": "Maximum size", "idle": "Idle Timeout", diff --git a/postgresql.html b/postgresql.html index 39ce99e..be6d324 100644 --- a/postgresql.html +++ b/postgresql.html @@ -20,12 +20,30 @@
- - - -
+ + + + +
+ + + +
+
+ + + +
-
+
+ - +
+
+ + + +