v134 · javascript
Connection pool
A connection pool hands out limited resources and reclaims them on scope exit. With using, the checkout returns a Disposable: Symbol.dispose automatically returns the connection when the block exits — even if an exception is thrown.
Feature detection: checking…
Without using — manual release required
function runQuery(query) {
const conn = pool.checkout(); // must remember to release
try {
return conn.query(query);
} finally {
pool.release(conn); // easy to forget
}
}
// If the dev forgets the try/finally:
function badQuery(query) {
const conn = pool.checkout();
return conn.query(query); // leaks on throw!
}
With using — automatic on scope exit
function runQuery(query) {
using conn = pool.checkout();
// conn[Symbol.dispose]() called
// when block exits — throw or not
return conn.query(query);
}
// Works even if query throws:
function riskyQuery(query) {
using conn = pool.checkout();
if (Math.random() < 0.4) {
throw new Error('simulated failure');
}
return conn.query(query);
// conn is always released
}
Connection pool — 6 slots
idle
checked out: 0
available: 6
queries run: 0
leaks prevented: 0
Activity log:
Run a query to see checkout/release lifecycle.
// Disposable connection — Symbol.dispose auto-releases to pool
class PooledConnection {
constructor(id, pool, log) {
this.id = id;
this._pool = pool;
this._log = log;
}
query(sql) {
this._log(`conn#${this.id} executing: ${sql}`);
return { rows: [], conn: this.id };
}
// Called by `using` on scope exit
[Symbol.dispose]() {
this._pool.release(this);
this._log(`conn#${this.id} auto-released to pool`);
}
}
// Pool.checkout returns a PooledConnection
// `using conn = pool.checkout()` guarantees release
function processRequest(sql) {
using conn = pool.checkout();
return conn.query(sql); // conn released here, always
}