1 背景
当我们使用generic-pool在释放资源时,有可能会出现 Error: Resource not currently part of this pool异常。通过下面的代码创建一个资源池,来演示出现该异常的情况。
const pool = require('generic-pool');
const factory = {
create: function() {
return Math.random();
},
destroy: function(rs) {
console.log(rs)
}
};
const opts = {
max: 10, // maximum size of the pool
min: 4 // minimum size of the pool
};
let gpool = pool.createPool(factory,opts);
2 资源释放分析
根据传入release接口的参数在_resourceLoans中去查找是否有该资源,如果
没找到,那么会产生Resource not currently part of this pool错误。
release(resource) {
// check for an outstanding loan
const loan = this._resourceLoans.get(resource);
if (loan === undefined) {
return this._Promise.reject(
new Error("Resource not currently part of this pool")
);
}
_resourceLoans定义为一个Map。
/**
* Loans keyed by the borrowed resource
* @type {Map}
*/
this._resourceLoans = new Map();
3 归还不属于该池的资源产生错误
很显然,根据2的分析归还一个不属于该池的资源会产生错误。
gpool.acquire().then(e => {
console.log(e);
gpool.release("test");
}).catch(err => {
console.log(err)
});
4 资源不唯一归还时候产生错误
resourceLoans是一个Map,ES6 引入了Map,key的范围不限于字符串,
各种类型的value(包括对象)都可以当作key。而在Map中key不能重复。
mapt = new Map();
Map(0) {}
mapt.set("1","3");
Map(1) {"1" => "3"}
mapt.set("1","4");
Map(1) {"1" => "4"}
因此当我们使用generic-pool,key是我们创建的资源。如果资源发生重复,那么在进行release操作时,可能会产生异常。
const factory = {
create: function() {
return 1;
},
destroy: function(rs) {
console.log(rs)
}
};
for(let i = 0; i < 10; i++) {
gpool.acquire().then(e => {
console.log(e);
gpool.release(e);
}).catch(err => {
console.log(err)
});
}
多次执行acquire获取资源,_resourceLoans最多只会存放一个借出资源。因此当执行多次release后就会出现resourceLoans为空的情况,导致产生Error: Resource not currently part of this pool异常。
所以使用pool时,资源对象作为Map的key不重复即可避免这种情况。
5 参考
[1] generic-pool@3.7.1 源码