UNPKG

ngn-data

Version:

Data modeling, stores, proxies, and utilities for NGN

184 lines (147 loc) 4.26 kB
/** * v0.1.11 generated on: Sat Jun 24 2017 01:20:07 GMT+0000 (UTC) * Copyright (c) 2014-2017, Ecor Ventures LLC. All Rights Reserved. See LICENSE (BSD3). */ 'use strict' class ConnectionPool extends NGN.EventEmitter { constructor () { super() Object.defineProperties(this, { clients: NGN.private({}), destroyOnDrain: NGN.private(true), drainMethod: NGN.private({}) }) NGN.createException({ name: 'DatabaseConnectionError', type: 'DatabaseConnectionError', message: 'An error occured with a pooled connection.' }) this.on('pool.drained', (id) => { if (this.destroyOnDrain) { if (this.drainMethod.hasOwnProperty(id)) { if (this.drainMethod[id].length > 1) { this.drainMethod[id](this[id], () => this.remove(id)) } else { this.drainMethod[id](this[id]) this.remove(id) } } } }) } get connections () { return this.clients } get deleteOnEmpty () { return this.destroyOnDrain } set deleteOnEmpty (value) { this.destroyOnDrain = value } add (key, value, drainFn, overwrite = false) { let triggerEvent = true if (typeof drainFn === 'boolen') { overwrite = drainFn drainFn = null } else if (!NGN.isFn(drainFn)) { drainFn = null } if (this.hasOwnProperty(key)) { if (value === this[key]) { return } else if (!overwrite) { throw new DatabaseConnectionError(`A different connection for ${key} already exists.`) } else { triggerEvent = false } } Object.defineProperty(this, key, { enumerable: true, configurable: true, get: () => { this.emit('pool.used', key) return value } }) if (typeof value === 'object' && value.hasOwnProperty('on')) { value.on('disconnect', () => this.remove(key)) value.on('disconnected', () => this.remove(key)) } if (NGN.isFn(drainFn)) { this.drainMethod[key] = drainFn } if (triggerEvent) { this.emit('pool.created', { id: key, connection: value }) } } remove (key) { if (!this.hasOwnProperty(key)) { return NGN.BUS.emit('NGN.ADVISORY.WARN', `NGN.DATA.ConnectionPool cannot remove '${key}' because it cannot be found.`) } let old = { id: key, connection: this[key] } Object.defineProperty(this, key, { get: undefined }) delete this[key] if (this.clients.hasOwnProperty(key)) { delete this.clients[key] } this.emit('pool.deleted', old) old = null } registerClient (key, name = null) { this.clients[key] = NGN.coalesce(this.clients[key], {}) let id = NGN.coalesce(name, NGN.DATA.util.GUID()) this.clients[key][id] = NGN.coalesce(this.clients[key][id], 0) this.clients[key][id]++ return id } unregisterClient (key, name) { if (!this.clients.hasOwnProperty(key)) { NGN.BUS.emit('NGN.ADVISORY.WARN', `Cannot unregister non-existant client: "${key}"`) return } if (!this.clients[key].hasOwnProperty(name)) { NGN.BUS.emit('NGN.ADVISORY.WARN', `Cannot unregister unrecognized client (${name}) from connection ID: ${key}`) return } this.clients[key][name] = this.clients[key][name] - 1 if (this.clients[key][name] === 0) { delete this.clients[key][name] this.emit('client.disconnected', { connection: this[key], connectionId: key, id: name }) } if (Object.keys(this.clients[key]).length === 0) { delete this.clients[key] this.emit('pool.drained', key) } } activeConnections (id = null) { let count = 0 if (id !== null) { if (!this.clients.hasOwnProperty(id)) { return 0 } Object.keys(this.clients[id]).forEach((client) => { count += this.clients[id][client] }) } else { Object.keys(this.clients).forEach((connection) => { Object.keys(this.clients[connection]).forEach((client) => { count += this.clients[connection][client] }) }) } return count } } NGN.DATA.ConnectionPool = new ConnectionPool()