Comparing version 2.3.5 to 2.4.0-alpha.0
@@ -71,3 +71,5 @@ const { Statement } = require('./Statement'); | ||
return this.odbcConnection.query(sql, parameters, callback); | ||
process.nextTick(() => { | ||
this.odbcConnection.query(sql, parameters, callback); | ||
}) | ||
} | ||
@@ -74,0 +76,0 @@ |
@@ -37,10 +37,5 @@ const binary = require('node-pre-gyp'); | ||
if (typeof callback !== 'function') { | ||
return new Promise((resolve, reject) => { | ||
poolObj.init((error) => { | ||
if (error) { | ||
reject(error); | ||
} else { | ||
resolve(poolObj); | ||
} | ||
}); | ||
return new Promise(async (resolve, reject) => { | ||
await poolObj.init(); | ||
resolve(poolObj); | ||
}); | ||
@@ -47,0 +42,0 @@ } |
247
lib/Pool.js
@@ -0,1 +1,2 @@ | ||
const EventEmitter = require('events'); | ||
const async = require('async'); | ||
@@ -11,2 +12,3 @@ const binary = require('node-pre-gyp'); | ||
const REUSE_CONNECTIONS_DEFAULT = true; | ||
const INITIAL_SIZE_DEFAULT = 10; | ||
@@ -20,5 +22,27 @@ const INCREMENT_SIZE_DEFAULT = 10; | ||
class Pool { | ||
constructor(connectionString) { | ||
this.connectionEmitter = new EventEmitter(); | ||
this.connectionEmitter.on('connected', (connection) => { | ||
if (this.connectionQueue.length > 0) | ||
{ | ||
let connectionWork = this.connectionQueue.pop(); | ||
if (typeof connectionWork == 'function') | ||
{ | ||
// callback function | ||
return connectionWork(null, connection); | ||
} else { | ||
// Promise (stored resolve function) | ||
return connectionWork.resolveFunction(connection); | ||
} | ||
} else { | ||
this.freeConnections.push(connection); | ||
} | ||
}); | ||
this.isOpen = false; | ||
this.freeConnections = []; | ||
this.connectingCount = 0; | ||
this.connectionQueue = []; | ||
@@ -28,2 +52,4 @@ // connectionString is a... | ||
this.connectionString = connectionString; | ||
this.reuseConnections = REUSE_CONNECTIONS_DEFAULT; | ||
this.initialSize = INITIAL_SIZE_DEFAULT; | ||
@@ -35,2 +61,3 @@ this.incrementSize = INCREMENT_SIZE_DEFAULT; | ||
this.loginTimeout = LOGIN_TIMEOUT_DEFAULT; | ||
} else if (typeof connectionString === 'object') { | ||
@@ -42,8 +69,23 @@ const configObject = connectionString; | ||
this.connectionString = configObject.connectionString; | ||
this.initialSize = configObject.initialSize || INITIAL_SIZE_DEFAULT; | ||
this.incrementSize = configObject.incrementSize || INCREMENT_SIZE_DEFAULT; | ||
this.maxSize = configObject.maxSize || MAX_SIZE_DEFAULT; | ||
this.shrink = configObject.shrink || SHRINK_DEFAULT; | ||
this.connectionTimeout = configObject.connectionTimeout || CONNECTION_TIMEOUT_DEFAULT; | ||
this.loginTimeout = configObject.loginTimeout || LOGIN_TIMEOUT_DEFAULT; | ||
// reuseConnections | ||
this.reuseConnections = configObject.reuseConnections !== undefined ? configObject.reuseConnections : REUSE_CONNECTIONS_DEFAULT; | ||
// initialSize | ||
this.initialSize = configObject.initialSize !== undefined ? configObject.initialSize : INITIAL_SIZE_DEFAULT; | ||
// incrementSize | ||
this.incrementSize = configObject.incrementSize !== undefined ? configObject.incrementSize : INCREMENT_SIZE_DEFAULT; | ||
// maxSize | ||
this.maxSize = configObject.incrementSize !== undefined ? configObject.incrementSize : INCREMENT_SIZE_DEFAULT; | ||
// shrink | ||
this.shrink = configObject.shrink !== undefined ? configObject.shrink : SHRINK_DEFAULT; | ||
// connectionTimeout | ||
this.connectionTimeout = configObject.connectionTimeout !== undefined ? configObject.connectionTimeout : CONNECTION_TIMEOUT_DEFAULT; | ||
// loginTimeout | ||
this.loginTimeout = configObject.loginTimeout !== undefined ? configObject.loginTimeout : LOGIN_TIMEOUT_DEFAULT; | ||
} else { | ||
@@ -54,2 +96,3 @@ throw TypeError('Pool constructor must passed a connection string or a configuration object'); | ||
// TODO: Documentation | ||
@@ -61,52 +104,44 @@ // TODO: Does this need to be async? | ||
async connect(callback = undefined) { | ||
if (this.freeConnections.length < 2) { | ||
await this.increasePoolSize(this.incrementSize); | ||
} | ||
let connection; | ||
if (this.freeConnections.length > 0) { | ||
connection = this.freeConnections.pop(); | ||
} else { | ||
await this.increasePoolSize(this.incrementSize); | ||
connection = this.freeConnections.pop(); | ||
} | ||
if (this.freeConnections.length == 0) { | ||
connection.nativeClose = connection.close; | ||
// If the number of connections waiting is more (shouldn't happen) or | ||
// equal to the number of connections connecting, then we will need to | ||
// create MORE connections. | ||
if (this.connectingCount <= this.connectionQueue.length) | ||
{ | ||
this.increasePoolSize(this.incrementSize); | ||
} | ||
connection.close = async (closeCallback = undefined) => { | ||
if (typeof closeCallback === 'undefined') { | ||
return new Promise((resolve, reject) => { | ||
connection.nativeClose((error, result) => { | ||
if (error) { | ||
reject(error); | ||
} else { | ||
resolve(result); | ||
} | ||
}); | ||
if (typeof callback == 'undefined') { | ||
let resolveConnectionPromise; | ||
this.increasePoolSize(1); | ||
const promise = new Promise((resolve, reject) => { | ||
resolveConnectionPromise = resolve; | ||
}); | ||
const promiseObj = { | ||
promise: promise, | ||
resolveFunction: resolveConnectionPromise | ||
} | ||
this.connectionQueue.unshift(promiseObj); | ||
return promise; | ||
} else { | ||
this.connectionQueue.unshift(callback) | ||
return undefined; | ||
} | ||
} else { | ||
connection = this.freeConnections.pop(); | ||
connection.nativeClose(closeCallback); | ||
this.increasePoolSize(1); | ||
return undefined; | ||
}; | ||
// promise... | ||
if (typeof callback === 'undefined') { | ||
return new Promise((resolve, reject) => { | ||
if (connection == null) { | ||
reject(); | ||
} else { | ||
resolve(connection); | ||
} | ||
}); | ||
// promise... | ||
if (typeof callback === 'undefined') { | ||
return Promise.resolve(connection); | ||
} else { | ||
// ...or callback | ||
return callback(null, connection); | ||
} | ||
} | ||
}; | ||
// ...or callback | ||
return callback(null, connection); | ||
} | ||
async query(sql, params, cb) { | ||
@@ -126,26 +161,17 @@ // determine the parameters passed | ||
let connection; | ||
if (this.freeConnections.length > 0) { | ||
connection = this.freeConnections.pop(); | ||
} else { | ||
await this.increasePoolSize(this.incrementSize); | ||
connection = this.freeConnections.pop(); | ||
} | ||
if (!connection) { | ||
return callback(Error('Could not get a connection from the pool.')); | ||
} | ||
// promise... | ||
if (typeof callback !== 'function') { | ||
return new Promise((resolve, reject) => { | ||
connection.query(sql, parameters, (error, result) => { | ||
// after running, close the connection whether error or not | ||
this.connect((error, connection) => { | ||
if (error) { | ||
reject(error); | ||
} else { | ||
resolve(result); | ||
} | ||
connection.close(); | ||
connection.query(sql, parameters, (error, result) => { | ||
if (error) { | ||
reject(error); | ||
} else { | ||
resolve(result); | ||
} | ||
connection.close(); | ||
}); | ||
}); | ||
@@ -155,9 +181,15 @@ }); | ||
// ...or callback | ||
return connection.query(sql, parameters, (error, result) => { | ||
// after running, close the connection whether error or not | ||
process.nextTick(() => { | ||
callback(error, result); | ||
this.connect((error, connection) => { | ||
if (error) { | ||
throw error; | ||
} | ||
// ...or callback | ||
return connection.query(sql, parameters, (error, result) => { | ||
// after running, close the connection whether error or not | ||
process.nextTick(() => { | ||
callback(error, result); | ||
}); | ||
connection.close(); | ||
}); | ||
connection.close(); | ||
}); | ||
@@ -175,3 +207,3 @@ } | ||
async.each(connections, (connection, cb) => { | ||
connection.close((error) => { | ||
connection.nativeClose((error) => { | ||
cb(error); | ||
@@ -190,3 +222,3 @@ }); | ||
async.each(this.freeConnections, (connection, cb) => { | ||
connection.close((error) => { | ||
connection.nativeClose((error) => { | ||
cb(error); | ||
@@ -205,3 +237,3 @@ }); | ||
await this.increasePoolSize(this.initialSize); | ||
resolve(null); | ||
resolve(); | ||
} catch (error) { | ||
@@ -221,4 +253,2 @@ reject(error); | ||
} | ||
console.log('.init() was called, but the Pool was already initialized.'); | ||
return undefined; | ||
@@ -229,2 +259,3 @@ } | ||
async increasePoolSize(count) { | ||
this.connectingCount += count; | ||
const connectionConfig = { | ||
@@ -235,23 +266,61 @@ connectionString: this.connectionString, | ||
}; | ||
return new Promise((resolve, reject) => { | ||
return new Promise(async (resolve, reject) => { | ||
const connectArray = []; | ||
for (let i = 0; i < count; i += 1) { | ||
connectArray.push((callback) => { | ||
odbc.connect(connectionConfig, (error, connection) => { | ||
if (!error) { | ||
if (this.isOpen) { | ||
this.freeConnections.push(new Connection(connection)); | ||
let promise = new Promise((resolve, reject) => { | ||
odbc.connect(connectionConfig, (error, nativeConnection) => { | ||
let connection = undefined; | ||
if (error) { | ||
reject(error); | ||
return; | ||
} | ||
connection = new Connection(nativeConnection); | ||
connection.nativeClose = connection.close; | ||
if (this.reuseConnections) { | ||
connection.close = async (closeCallback = undefined) => { | ||
this.connectionEmitter.emit('connected', connection); | ||
if (typeof closeCallback === 'undefined') { | ||
return new Promise((resolve, reject) => { | ||
resolve(); | ||
}) | ||
} | ||
return closeCallback(null); | ||
}; | ||
} else { | ||
connection.close = async (closeCallback = undefined) => { | ||
this.increasePoolSize(1); | ||
if (typeof closeCallback === 'undefined') { | ||
return new Promise((resolve, reject) => { | ||
connection.nativeClose((error, result) => { | ||
if (error) { | ||
reject(error); | ||
} else { | ||
resolve(result); | ||
} | ||
}); | ||
}); | ||
} | ||
connection.nativeClose(closeCallback); | ||
} | ||
} | ||
callback(error, connection); | ||
this.connectingCount--; | ||
this.connectionEmitter.emit('connected', connection); | ||
resolve(); | ||
}); | ||
}); | ||
connectArray.push(promise); | ||
} | ||
async.race(connectArray, (error) => { | ||
if (error) { | ||
reject(error); | ||
} else { | ||
resolve(); | ||
} | ||
}); | ||
if (connectArray.length > 0) | ||
{ | ||
await Promise.race(connectArray); | ||
resolve(); | ||
} else { | ||
resolve(); | ||
} | ||
}); | ||
@@ -258,0 +327,0 @@ } |
{ | ||
"name": "odbc", | ||
"description": "unixodbc bindings for node", | ||
"version": "2.3.5", | ||
"version": "2.4.0-alpha.0", | ||
"homepage": "http://github.com/markdirish/node-odbc/", | ||
@@ -34,12 +34,12 @@ "main": "lib/odbc.js", | ||
"engines": { | ||
"node": ">=8.16.0" | ||
"node": ">=10.19.0" | ||
}, | ||
"scripts": { | ||
"install": "node-pre-gyp install --fallback-to-build", | ||
"test": "mocha --slow 5000 --timeout 10000" | ||
"test": "mocha --slow 5000 --timeout 30000" | ||
}, | ||
"dependencies": { | ||
"async": "^3.0.1", | ||
"node-addon-api": "^1.7.1", | ||
"node-pre-gyp": "^0.14.0" | ||
"node-addon-api": "^3.0.2", | ||
"node-pre-gyp": "^0.15.0" | ||
}, | ||
@@ -49,3 +49,3 @@ "gypfile": true, | ||
"dotenv": "^6.2.0", | ||
"eslint": "^5.13.0", | ||
"eslint": "^7.11.0", | ||
"eslint-config-airbnb-base": "^13.1.0", | ||
@@ -61,5 +61,8 @@ "eslint-plugin-import": "^2.16.0", | ||
"napi_versions": [ | ||
3 | ||
3, | ||
4, | ||
5, | ||
6 | ||
] | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
283806
783
1
+ Addednode-addon-api@3.2.1(transitive)
+ Addednode-pre-gyp@0.15.0(transitive)
- Removednode-addon-api@1.7.2(transitive)
- Removednode-pre-gyp@0.14.0(transitive)
Updatednode-addon-api@^3.0.2
Updatednode-pre-gyp@^0.15.0