Generic resource pooling for fibjs
Install
npm install fib-pool [--save]
Test
npm test # fibjs test
npm run typecheck # fibjs --check, including test/types.ts
Creating a pool
Simple example.
var db = require("db");
var Pool = require("fib-pool");
var p = Pool(() => {
return db.open("sqlite:test.db");
});
Specify maxsize and timeout.
var db = require("db");
var Pool = require("fib-pool");
var p = Pool(() => {
return db.open("sqlite:test.db");
}, 10, 30 * 1000);
Specify custom destroy function.
var db = require("db");
var Pool = require("fib-pool");
var p = Pool({
create: () => {
return db.open("sqlite:test.db");
},
destroy: (o) => {
o.close()
},
timeout: 30 * 1000,
retry: 3
});
Using the pool
var db = require("db");
var Pool = require("fib-pool");
var p = Pool({
create: () => {
return db.open("sqlite:test.db");
},
destroy: (o) => {
o.close()
},
timeout: 30 * 1000,
retry: 3
});
var res = p((conn) => {
conn.execute("select * from test");
});
Using the pool with name
var db = require("db");
var Pool = require("fib-pool");
var p = Pool({
create: (name) => {
return db.open("sqlite:" + name + ".db");
},
destroy: (o) => {
o.close()
},
timeout: 30 * 1000
});
var res = p("test", (conn) => {
conn.execute("select * from test");
});
Options
| option | type | default | notes |
|---|---|---|---|
create |
(name) => item |
— | required; throwing is a failure, retried up to retry times |
destroy |
(item) => void |
close/destroy/dispose | defaults to calling whichever of those three the item provides |
maxsize |
positive integer | 10 |
caps both concurrency and the number of idle items |
timeout |
positive number (ms) | 60000 |
how long an idle item is kept |
retry |
positive integer | 1 |
how many times create is attempted before giving up |
strict |
boolean | true |
see below |
The pooled item is unconstrained: create may return an object, a class
instance, a function, or a primitive. The default destroy calls whichever of
close / destroy / dispose the item provides and ignores items that have
none of them.
var p = Pool(() => 10); // a primitive item
p((v) => v + 1);
var q = Pool(() => ({ value: 1 })); // a plain object, nothing to destroy
q((o) => o.value);
Invalid maxsize, timeout and retry values throw a TypeError when the
pool is created rather than being silently coerced:
Pool({ create: () => ({}), maxsize: 0 }); // TypeError: maxsize must be a positive integer, received 0
Pool({ create: () => ({}), timeout: -5 }); // TypeError: timeout must be a positive number, received -5
Pool({ create: () => ({}), retry: true }); // TypeError: retry must be a positive integer, received true
The idle list is capped by maxsize as well: a pool used with more names than
that evicts the least recently used item (and destroys it) instead of keeping
one idle item per name.
Reentrancy
A pool cannot be acquired twice from the same fiber. The inner call would wait for a permit that the outer call is holding, which never arrives, so it is rejected instead of deadlocking:
var p = Pool({ create: () => ({}), maxsize: 1 });
p(() => {
p(() => {}); // Error: Cannot pool again from the same fiber
});
Nesting different pools, or acquiring the same pool from another fiber, works as expected.
Strict mode (default: enabled)
By default, the pool uses strict mode to prevent accessing pooled objects outside of the callback function. This helps prevent resource leaks and ensures proper resource management.
var Pool = require("fib-pool");
var p = Pool({
create: () => {
return { value: 1, getValue: function() { return this.value; } };
}
});
var leaked;
p((obj) => {
leaked = obj;
// This works inside the pool callback
console.log(obj.getValue()); // OK
});
// This will throw an error: "access object outside of pool scope"
leaked.getValue(); // Error!
The guarded object behaves like the item for reading and inspection —
key in obj, Object.keys(obj), for...in, JSON.stringify(obj) and
util.inspect(obj) all report the item's own members — while the guards remain:
- Setting properties on pooled objects
- Calling
close(),destroy(), ordispose()methods directly - Extracting a method and calling it after the callback returned
To disable strict mode:
var p = Pool({
create: () => {
return { value: 1 };
},
strict: false
});
Clear a pool
Simple example.
var db = require("db");
var Pool = require("fib-pool");
var p = Pool(() => {
return db.open("sqlite:test.db");
});
p.clear();