我最近将我的通用池包升级到版本3,它使用了承诺 - 这个概念我可能不太了解。尽管在操作上有一些意想不到的差异,但我已设法使其正常工作。
我遇到的问题是我开始测试错误情况。我故意将密码设置错误,并且在测试时,我得到一个无限循环的"连接失败"错误 - 表示尽管出现错误,仍会触发创建函数。我假设我已经错误地配置了池,或者我收集不正确。
通用池工厂:
const poolFactory = {
create: function() {
return new Promise(function(resolve, reject) {
var client = mysql.createConnection({
host: config.host,
user: config.user,
password: config.pass,
});
client.connect(function(err) {
if (err != null) {
log.write('ERROR', "Connection Error: MySQL: " + err.message);
reject(err);
} else {
log.write('INFO', "MySQL Connection created.");
resolve(client);
}
});
})
},
destroy: function(client) {
return new Promise(function(resolve) {
client.end(function(err) {
if (err != null) {
log.write('ERROR', "DB Error: MySQL: " + err.message);
} else {
log.write('INFO', "Database connection closed.");
resolve();
}
});
})
}
}
const cp = genericPool.createPool(poolFactory);
触发连接错误的测试查询:
cp.acquire().then(
function(client) {
client.query('USE ' + config.db, function(err, results, fields) {
if (err != null) {
log.write('ERROR', "DB test error: MySQL: " + err.message);
} else {
log.write('INFO', "MySQL connection tested successfully.");
cp.release(client)
}
});
}).catch(function(err) {
cp.release(client);
log.write('ERROR', "Pool Error: " + err.message);
});
我的错误日志填满了一百万行:
Connection Error: MySQL: ER_ACCESS_DENIED_ERROR: Access denied for user 'user'@'localhost' (using password: YES)
我期待一个错误,因为我正在测试错误条件。得到无限循环我做错了什么?我认为拒绝(错误)应该将承诺置于一个不再回答任何问题的状态?
有人能指出我正确的方向吗?
一如既往 - 非常感谢你!
编辑:这是一个完整的脚本,可以说明问题,如果有人关心第一手问题!控制台填满" ERROR MySQL连接错误:ER_ACCESS_DENIED_ERROR:拒绝访问用户' devUser' @' localhost' (使用密码:是)"。再次感谢。
// Test App to show logging issue
var pool = require('generic-pool'),
mysql = require('mysql')
var config = {
port: 8880,
host: 'localhost',
user: 'devUser',
pass: 'wrong-pass',
db: 'node-app-db'
}
const poolConfig = {
max: 3
};
const poolFactory = {
create: function() {
return new Promise(function(resolve, reject) {
var client = mysql.createConnection({
host: config.host,
user: config.user,
password: config.pass,
});
client.connect(function(err) {
if (err != null) {
console.log('ERROR', "MySQL Connection Error: " + err.message);
reject(err);
} else {
console.log('USAGE', "MySQL Connection created. " + cp.size + " of " + config.poolSize + " connections to DB in use.");
resolve(client);
}
});
})
},
destroy: function(client) {
return new Promise(function(resolve) {
client.end(function(err) {
if (err != null) {
console.log('ERROR', "DB Error: MySQL: " + err.message);
} else {
console.log('USAGE', "Database connection closed. Pool contains ' + cp.size + ' more connections.");
resolve();
}
});
})
}
}
const cp = pool.createPool(poolFactory, poolConfig);
cp.acquire().then(
function(client) {
client.query('USE ' + config.db, function(err, results, fields) {
if (err != null) {
console.log('ERROR', "DB test error: MySQL: " + err.message);
} else {
console.log('READY', "MySQL connection tested successfully. DataServer ready for connections.");
cp.release(client)
}
});
}).catch(function(err) {
cp.release(client);
console.log('ERROR', "Pool Error: " + err.message);
});
答案 0 :(得分:0)
在github问题上从我原来的回复中交叉发布
嘿@whiteatom - 是的,你已经打到了“已知问题”的土地......对于某些历史......
在v2中,对pool.acquire
的特定调用与factory.create
的单个调用直接相关,而factory.create
中的错误将导致pool.acquire
。 (这通常是坏的️)
在v3中,对pool.acquire
的调用与factory.create
的调用没有任何关系,因此factory.create
中的任何错误都无法冒充pool.acquire
次调用,因为它没有任何语义感。相反,factory
错误现在通过event emitters
Pool
本身公开
总而言之:promise
返回的pool.acquire
只会因与acquire
调用特别相关的错误(例如超时)而拒绝,而不是因为任何其他错误池中的错误。要捕获池中的常规错误,您需要将一些事件侦听器附加到您拥有的Pool
实例。
如果你的factory.create
返回只能拒绝的承诺,那么仍然存在这样的问题:池可能会以某种无限循环结束。为了解决这个问题,你可以在你的factory.create
函数中构建退避功能(虽然这有点像黑客,但我真的需要找到一些方法来退回池本身。)