UNPKG

@worker-tools/deno-kv-storage

Version:

An implementation of the StorageArea (1,2,3) interface for Deno with an extensible system for supporting various database backends.

197 lines 8.86 kB
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { if (kind === "m") throw new TypeError("Private method is not writable"); if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; }; var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); }; var _Pool_instances, _Pool_available_connections, _Pool_connection_params, _Pool_ended, _Pool_lazy, _Pool_ready, _Pool_size, _Pool_initialize; import { PoolClient } from "./client.js"; import { createParams, } from "./connection/connection_params.js"; import { DeferredAccessStack } from "./utils/deferred.js"; /** * Connection pools are a powerful resource to execute parallel queries and * save up time in connection initialization. It is highly recommended that all * applications that require concurrent access use a pool to communicate * with their PostgreSQL database * * ```ts * import { Pool } from "./pool.ts"; * * const pool = new Pool({ * database: "database", * hostname: "hostname", * password: "password", * port: 5432, * user: "user", * }, 10); // Creates a pool with 10 available connections * * const client = await pool.connect(); * await client.queryArray`SELECT 1`; * client.release(); * ``` * * You can also opt to not initialize all your connections at once by passing the `lazy` * option when instantiating your pool, this is useful to reduce startup time. In * addition to this, the pool won't start the connection unless there isn't any already * available connections in the pool * * ```ts * import { Pool } from "./pool.ts"; * * // Creates a pool with 10 max available connections * // Connection with the database won't be established until the user requires it * const pool = new Pool({}, 10, true); * * // Connection is created here, will be available from now on * const client_1 = await pool.connect(); * await client_1.queryArray`SELECT 1`; * await client_1.release(); * * // Same connection as before, will be reused instead of starting a new one * const client_2 = await pool.connect(); * await client_2.queryArray`SELECT 1`; * * // New connection, since previous one is still in use * // There will be two open connections available from now on * const client_3 = await pool.connect(); * await client_2.release(); * await client_3.release(); * ``` */ export class Pool { constructor(connection_params, size, lazy = false) { _Pool_instances.add(this); _Pool_available_connections.set(this, void 0); _Pool_connection_params.set(this, void 0); _Pool_ended.set(this, false); _Pool_lazy.set(this, void 0); // TODO // Initialization should probably have a timeout _Pool_ready.set(this, void 0); _Pool_size.set(this, void 0); __classPrivateFieldSet(this, _Pool_connection_params, createParams(connection_params), "f"); __classPrivateFieldSet(this, _Pool_lazy, lazy, "f"); __classPrivateFieldSet(this, _Pool_size, size, "f"); // This must ALWAYS be called the last __classPrivateFieldSet(this, _Pool_ready, __classPrivateFieldGet(this, _Pool_instances, "m", _Pool_initialize).call(this), "f"); } /** * The number of open connections available for use * * Lazily initialized pools won't have any open connections by default */ get available() { if (!__classPrivateFieldGet(this, _Pool_available_connections, "f")) { return 0; } return __classPrivateFieldGet(this, _Pool_available_connections, "f").available; } /** * The number of total connections open in the pool * * Both available and in use connections will be counted */ get size() { if (!__classPrivateFieldGet(this, _Pool_available_connections, "f")) { return 0; } return __classPrivateFieldGet(this, _Pool_available_connections, "f").size; } // TODO // Rename to getClient or similar // The connect method should initialize the connections instead of doing it // in the constructor /** * This will return a new client from the available connections in * the pool * * In the case of lazy initialized pools, a new connection will be established * with the database if no other connections are available * * ```ts * import { Pool } from "./pool.ts"; * * const pool = new Pool({}, 10); * const client = await pool.connect(); * await client.queryArray`UPDATE MY_TABLE SET X = 1`; * client.release(); * ``` */ async connect() { // Reinitialize pool if it has been terminated if (__classPrivateFieldGet(this, _Pool_ended, "f")) { __classPrivateFieldSet(this, _Pool_ready, __classPrivateFieldGet(this, _Pool_instances, "m", _Pool_initialize).call(this), "f"); } await __classPrivateFieldGet(this, _Pool_ready, "f"); return __classPrivateFieldGet(this, _Pool_available_connections, "f").pop(); } /** * This will close all open connections and set a terminated status in the pool * * ```ts * import { Pool } from "./pool.ts"; * * const pool = new Pool({}, 10); * * await pool.end(); * console.assert(pool.available === 0, "There are connections available after ending the pool"); * await pool.end(); // An exception will be thrown, pool doesn't have any connections to close * ``` * * However, a terminated pool can be reused by using the "connect" method, which * will reinitialize the connections according to the original configuration of the pool * * ```ts * import { Pool } from "./pool.ts"; * * const pool = new Pool({}, 10); * await pool.end(); * const client = await pool.connect(); * await client.queryArray`SELECT 1`; // Works! * await client.release(); * ``` */ async end() { if (__classPrivateFieldGet(this, _Pool_ended, "f")) { throw new Error("Pool connections have already been terminated"); } await __classPrivateFieldGet(this, _Pool_ready, "f"); while (this.available > 0) { const client = await __classPrivateFieldGet(this, _Pool_available_connections, "f").pop(); await client.end(); } __classPrivateFieldSet(this, _Pool_available_connections, undefined, "f"); __classPrivateFieldSet(this, _Pool_ended, true, "f"); } async initialized() { if (!__classPrivateFieldGet(this, _Pool_available_connections, "f")) { return 0; } return await __classPrivateFieldGet(this, _Pool_available_connections, "f").initialized(); } } _Pool_available_connections = new WeakMap(), _Pool_connection_params = new WeakMap(), _Pool_ended = new WeakMap(), _Pool_lazy = new WeakMap(), _Pool_ready = new WeakMap(), _Pool_size = new WeakMap(), _Pool_instances = new WeakSet(), _Pool_initialize = /** * Initialization will create all pool clients instances by default * * If the pool is lazily initialized, the clients will connect when they * are requested by the user, otherwise they will all connect on initialization */ async function _Pool_initialize() { const initialized = __classPrivateFieldGet(this, _Pool_lazy, "f") ? 0 : __classPrivateFieldGet(this, _Pool_size, "f"); const clients = Array.from({ length: __classPrivateFieldGet(this, _Pool_size, "f") }, async (_e, index) => { const client = new PoolClient(__classPrivateFieldGet(this, _Pool_connection_params, "f"), () => __classPrivateFieldGet(this, _Pool_available_connections, "f").push(client)); if (index < initialized) { await client.connect(); } return client; }); __classPrivateFieldSet(this, _Pool_available_connections, new DeferredAccessStack(await Promise.all(clients), (client) => client.connect(), (client) => client.connected), "f"); __classPrivateFieldSet(this, _Pool_ended, false, "f"); }; //# sourceMappingURL=pool.js.map