From b4cee6c669fa49b505cad162d4dcc88921aa78a2 Mon Sep 17 00:00:00 2001 From: uPaymeiFixit Date: Tue, 4 Mar 2025 11:36:03 -0800 Subject: [PATCH 1/4] add regex support to PoolCluster --- lib/pool_cluster.js | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/lib/pool_cluster.js b/lib/pool_cluster.js index 9edda501a2..d15685137c 100644 --- a/lib/pool_cluster.js +++ b/lib/pool_cluster.js @@ -37,6 +37,23 @@ const getMonotonicMilliseconds = function () { return Math.floor(ms); }; +const isRegExp = function (val) { + return typeof val === 'object' + && Object.prototype.toString.call(val) === '[object RegExp]'; +} + +const patternRegExp = function (pattern) { + if (isRegExp(pattern)) { + return pattern; + } + + var source = pattern + .replace(/([.+?^=!:${}()|\[\]\/\\])/g, '\\$1') + .replace(/\*/g, '.*'); + + return new RegExp('^' + source + '$'); +} + class PoolNamespace { constructor(cluster, pattern, selector) { this._cluster = cluster; @@ -256,20 +273,12 @@ class PoolCluster extends EventEmitter { let currentTime = 0; let foundNodeIds = this._findCaches[pattern]; - if (typeof this._findCaches[pattern] === 'undefined') { - if (pattern === '*') { - // all - foundNodeIds = this._serviceableNodeIds; - } else if (this._serviceableNodeIds.indexOf(pattern) !== -1) { - // one - foundNodeIds = [pattern]; - } else { - // wild matching - const keyword = pattern.substring(pattern.length - 1, 0); - foundNodeIds = this._serviceableNodeIds.filter((id) => - id.startsWith(keyword) - ); - } + if (foundNodeIds === undefined) { + let expression = patternRegExp(pattern); + + foundNodeIds = this._serviceableNodeIds.filter((id) => + id.match(expression) + ); } this._findCaches[pattern] = foundNodeIds; From 6e4ba12ecd8a924b2709147be6b8bee0b9d53476 Mon Sep 17 00:00:00 2001 From: Josh Gibbs Date: Tue, 4 Mar 2025 14:06:39 -0800 Subject: [PATCH 2/4] Update lib/pool_cluster.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Weslley Araújo <46850407+wellwelwel@users.noreply.github.com> --- lib/pool_cluster.js | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/lib/pool_cluster.js b/lib/pool_cluster.js index d15685137c..d71cb4d732 100644 --- a/lib/pool_cluster.js +++ b/lib/pool_cluster.js @@ -37,13 +37,8 @@ const getMonotonicMilliseconds = function () { return Math.floor(ms); }; -const isRegExp = function (val) { - return typeof val === 'object' - && Object.prototype.toString.call(val) === '[object RegExp]'; -} - const patternRegExp = function (pattern) { - if (isRegExp(pattern)) { + if (pattern instanceof RegExp) { return pattern; } From 297aaa1bcdab927144dcb72c34d2f50219f65955 Mon Sep 17 00:00:00 2001 From: uPaymeiFixit Date: Tue, 4 Mar 2025 21:12:43 -0800 Subject: [PATCH 3/4] fix linting issues --- lib/pool_cluster.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/pool_cluster.js b/lib/pool_cluster.js index d71cb4d732..958f938e3b 100644 --- a/lib/pool_cluster.js +++ b/lib/pool_cluster.js @@ -42,12 +42,12 @@ const patternRegExp = function (pattern) { return pattern; } - var source = pattern - .replace(/([.+?^=!:${}()|\[\]\/\\])/g, '\\$1') + const source = pattern + .replace(/([.+?^=!:${}()|[\]/\\])/g, '\\$1') .replace(/\*/g, '.*'); - return new RegExp('^' + source + '$'); -} + return new RegExp(`^${source}$`); +}; class PoolNamespace { constructor(cluster, pattern, selector) { @@ -269,7 +269,7 @@ class PoolCluster extends EventEmitter { let foundNodeIds = this._findCaches[pattern]; if (foundNodeIds === undefined) { - let expression = patternRegExp(pattern); + const expression = patternRegExp(pattern); foundNodeIds = this._serviceableNodeIds.filter((id) => id.match(expression) From 140228a082afe9bcf31791b789c8e5e8ee0f4e6c Mon Sep 17 00:00:00 2001 From: uPaymeiFixit Date: Thu, 6 Mar 2025 07:21:35 -0800 Subject: [PATCH 4/4] chore: add tests for regex pattern --- .../test-promise-wrapper.test.mjs | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/test/esm/integration/pool-cluster/test-promise-wrapper.test.mjs b/test/esm/integration/pool-cluster/test-promise-wrapper.test.mjs index 09706f59db..1b407fdbac 100644 --- a/test/esm/integration/pool-cluster/test-promise-wrapper.test.mjs +++ b/test/esm/integration/pool-cluster/test-promise-wrapper.test.mjs @@ -110,4 +110,40 @@ const { createPoolCluster } = require('../../../../promise.js'); poolCluster.end(); }); + + await test(async () => { + const poolCluster = createPoolCluster(); + poolCluster.add('SLAVE', common.config); + + try { + await poolCluster.getConnection('SLAVE1'); + assert.fail('An error was expected'); + } catch (error) { + assert.equal( + error.code, + 'POOL_NOEXIST', + 'should throw when PoolNamespace does not exist' + ); + } finally { + poolCluster.end(); + } + }); + + await test(async () => { + const poolCluster = createPoolCluster(); + poolCluster.add('SLAVE1', common.config); + + try { + const connection = await poolCluster.getConnection(/SLAVE[12]/); + assert.equal( + connection.connection._clusterId, + 'SLAVE1', + 'should match regex pattern' + ); + } catch (error) { + assert.fail('should not throw'); + } finally { + poolCluster.end(); + } + }); })();