ngn-data
Version:
Data modeling, stores, proxies, and utilities for NGN
184 lines (147 loc) • 4.26 kB
JavaScript
/**
* 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()