sequelize
Advanced tools
Comparing version 1.1.0 to 1.1.1
@@ -95,2 +95,6 @@ # v0.1.0 # | ||
- REVERTED mysql-pool usage (will give it a new try later) | ||
- updated node-mysql to 0.9.4 | ||
- updated node-mysql to 0.9.4 | ||
# v1.1.1 # | ||
- fixed memory leaks | ||
- added query queueing (adjustable via maxConcurrentQueries in config; default: 50) |
@@ -5,2 +5,3 @@ var Sequelize = require(__dirname + "/../../index") | ||
, QueryChainer = Sequelize.Utils.QueryChainer | ||
, sys = require("sys") | ||
@@ -10,22 +11,20 @@ var Person = sequelize.define('person', { name: Sequelize.STRING }) | ||
Person.sync({force: true}).on('success', function() { | ||
var start = Date.now() | ||
, count = 10000 | ||
, offset = 0 | ||
, stepWidth = 50 | ||
, queries = [] | ||
, chainer = new QueryChainer | ||
var start = Date.now() | ||
, count = 10000 | ||
, done = 0 | ||
var perform = function(cb) { | ||
console.log("Begin to create " + offset + " - " + (offset+stepWidth) + " items!") | ||
for(var i = offset; i < (offset + stepWidth); i++) | ||
chainer.add(Person.create({name: 'someone'})) | ||
chainer.run().on('success', function() { | ||
if(count - offset > 0) { | ||
offset += stepWidth | ||
perform(cb) | ||
var createPerson = function() { | ||
Person.create({name: 'someone'}).on('success', function() { | ||
if(++done == count) { | ||
var duration = (Date.now() - start) | ||
console.log("\nFinished creation of " + count + " people. Took: " + duration + "ms (avg: " + (duration/count) + "ms)") | ||
start = Date.now() | ||
console.log("Will now read them from the database:") | ||
Person.findAll().on('success', function(people) { | ||
console.log("Reading " + people.length + " items took: " + (Date.now() - start) + "ms") | ||
}) | ||
} else { | ||
console.log("Saving " + count + " items took: " + (Date.now() - start) + "ms") | ||
cb && cb.call() | ||
(done % 100 == 0) && sys.print('.') | ||
} | ||
@@ -36,13 +35,10 @@ }).on('failure', function(err) { | ||
} | ||
perform(function() { | ||
start = Date.now() | ||
console.log("Will now read them from the database:") | ||
Person.findAll().on('success', function(people) { | ||
console.log("Reading " + people.length + " items took: " + (Date.now() - start) + "ms") | ||
}) | ||
}) | ||
console.log('Creating people :)') | ||
for(var i = 0; i < count; i++) { | ||
createPerson() | ||
} | ||
}).on('failure', function(err) { | ||
console.log(err) | ||
}) |
@@ -0,5 +1,11 @@ | ||
var Query = require("./query") | ||
, without = function(arr, elem) { return arr.filter(function(e) { return e != elem }) } | ||
var ConnectorManager = module.exports = function(config) { | ||
this.connectorCheckTimeoutId = null | ||
this.client = null | ||
this.config = config | ||
this.disconnectTimeoutId = null | ||
this.queue = [] | ||
this.activeQueue = [] | ||
this.maxConcurrentQueries = (this.config.maxConcurrentQueries || 50) | ||
} | ||
@@ -17,25 +23,87 @@ | ||
}) | ||
this.client.setMaxListeners(999999) | ||
this.client.setMaxListeners(this.maxConcurrentQueries) | ||
} | ||
ConnectorManager.prototype.query = function(sql, callee, options) { | ||
if(!this.isConnected) this.connect() | ||
var queueItem = { | ||
query: new Query(this.client, callee, options || {}), | ||
sql: sql | ||
} | ||
this._enqueue(queueItem) | ||
return queueItem.query | ||
} | ||
ConnectorManager.prototype.disconnect = function() { | ||
this.client.end(function() {}) | ||
} | ||
ConnectorManager.prototype.reconnect = function() { | ||
this.disconnect() | ||
this.connect() | ||
} | ||
// private | ||
ConnectorManager.prototype._enqueue = function(queueItem) { | ||
if(this.activeQueue.length < this.maxConcurrentQueries) { | ||
this.activeQueue.push(queueItem) | ||
this._execQueueItem(queueItem) | ||
} else { | ||
this.queue.push(queueItem) | ||
} | ||
} | ||
ConnectorManager.prototype._dequeue = function(queueItem) { | ||
this.activeQueue = without(this.activeQueue, queueItem) | ||
} | ||
ConnectorManager.prototype._transferQueuedItems = function(count) { | ||
for(var i = 0; i < count; i++) { | ||
var queueItem = this.queue[0] | ||
if(queueItem) { | ||
this._enqueue(queueItem) | ||
this.queue = without(this.queue, queueItem) | ||
} | ||
} | ||
} | ||
ConnectorManager.prototype._afterQuery = function(queueItem) { | ||
var self = this | ||
this.client.end(function() { | ||
self.client = null | ||
self.connectorCheckTimeoutId = null | ||
}) | ||
this._dequeue(queueItem) | ||
this._transferQueuedItems(this.maxConcurrentQueries - this.activeQueue.length) | ||
this._disconnectIfNoConnections() | ||
} | ||
ConnectorManager.prototype.check = function() { | ||
ConnectorManager.prototype._execQueueItem = function(queueItem) { | ||
var self = this | ||
this.connectorCheckTimeoutId && clearTimeout(this.connectorCheckTimeoutId) | ||
this.connectorCheckTimeoutId = setTimeout(function() { | ||
if(self.client && self.client._queue && (self.client._queue.length === 0)) | ||
self.disconnect() | ||
}, 100) | ||
queueItem.query | ||
.on('success', function(){ self._afterQuery(queueItem) }) | ||
.on('failure', function(){ self._afterQuery(queueItem) }) | ||
queueItem.query.run(queueItem.sql) | ||
} | ||
ConnectorManager.prototype.__defineGetter__('hasNoConnections', function() { | ||
return (this.queue.length == 0) && (this.activeQueue.length == 0) && this.client._queue && (this.client._queue.length == 0) | ||
}) | ||
ConnectorManager.prototype.__defineGetter__('isConnected', function() { | ||
return (this.client !== null) | ||
}) | ||
return this.client != null | ||
}) | ||
ConnectorManager.prototype._disconnectIfNoConnections = function() { | ||
var self = this | ||
this.disconnectTimeoutId && clearTimeout(this.disconnectTimeoutId) | ||
this.disconnectTimeoutId = setTimeout(function() { | ||
self.isConnected && self.hasNoConnections && self.disconnect() | ||
}, 100) | ||
} |
@@ -8,4 +8,3 @@ var Utils = require("./utils") | ||
this.options = options || {} | ||
this.client.on('error', function(err) { self.onFailure(err) }) | ||
this.bindClientFunction = function(err) { self.onFailure(err) } | ||
} | ||
@@ -18,2 +17,4 @@ Utils.addEventEmitter(Query) | ||
this.bindClient() | ||
if(this.options.logging) | ||
@@ -29,6 +30,14 @@ console.log('Executing: ' + this.sql) | ||
Query.prototype.bindClient = function() { | ||
this.client.on('error', this.bindClientFunction) | ||
} | ||
Query.prototype.unbindClient = function() { | ||
this.client.removeListener('error', this.bindClientFunction) | ||
} | ||
Query.prototype.onSuccess = function(query, results, fields) { | ||
var result = this.callee | ||
, self = this | ||
// add the inserted row id to the instance | ||
@@ -47,2 +56,3 @@ if (this.callee && (query.indexOf('INSERT INTO') == 0) && (results.hasOwnProperty('insertId'))) | ||
this.unbindClient() | ||
this.emit('success', result) | ||
@@ -52,3 +62,4 @@ } | ||
Query.prototype.onFailure = function(err) { | ||
this.unbindClient() | ||
this.emit('failure', err, this.callee) | ||
} |
var Utils = require("./utils") | ||
, ModelDefinition = require("./model-definition") | ||
, Query = require("./query") | ||
, DataTypes = require('./data-types') | ||
@@ -9,5 +8,2 @@ | ||
var ModelManager = require("./model-manager") | ||
this.modelManager = new ModelManager(this) | ||
Utils._.reject(options, function(_, key) { return ["host", "port", "disableTableNameModification"].indexOf(key) > -1 }) | ||
@@ -23,2 +19,4 @@ | ||
} | ||
this.modelManager = new (require("./model-manager"))(this) | ||
this.connectorManager = new (require('./connector-manager'))(this.config) | ||
@@ -45,17 +43,9 @@ } | ||
query: function(sql, callee, options) { | ||
options = options || {} | ||
options = options || {} | ||
if(this.options.queryOptions) options = Sequelize.Utils.merge(options, this.options.queryOptions) | ||
if(!this.connectorManager.isConnected) this.connectorManager.connect() | ||
options.logging = this.options.hasOwnProperty('logging') ? this.options.logging : true | ||
var self = this | ||
, query = new Query(this.connectorManager.client, callee, options).run(sql) | ||
query | ||
.on('success', function(){ self.connectorManager.check() }) | ||
.on('failure', function(){ self.connectorManager.check() }) | ||
return query | ||
return this.connectorManager.query(sql, callee, options) | ||
}, | ||
@@ -75,5 +65,5 @@ | ||
chainer | ||
.run() | ||
.on('success', function() { eventEmitter.emit('success', null) }) | ||
.on('failure', function(err) { eventEmitter.emit('failure', err) }) | ||
.run() | ||
.on('success', function() { eventEmitter.emit('success', null) }) | ||
.on('failure', function(err) { eventEmitter.emit('failure', err) }) | ||
}) | ||
@@ -80,0 +70,0 @@ return eventEmitter.run() |
var client = new (require("mysql").Client)() | ||
var Utils = module.exports = { | ||
_: (function() { | ||
var _ = require("underscore"); | ||
_.mixin(require('underscore.string')); | ||
var _ = require("underscore") | ||
_.mixin(require('underscore.string')) | ||
_.mixin({ | ||
@@ -18,2 +19,3 @@ camelizeIf: function(string, condition) { | ||
}) | ||
return _ | ||
@@ -20,0 +22,0 @@ })(), |
{ | ||
"name": "sequelize", | ||
"description": "MySQL ORM for Node.JS", | ||
"version": "1.1.0", | ||
"version": "1.1.1", | ||
"author": "Sascha Depold <sascha@depold.com>", | ||
@@ -6,0 +6,0 @@ "contributors": [ |
@@ -40,6 +40,6 @@ var assert = require("assert") | ||
}) | ||
}, 100) | ||
}, 100) | ||
}, 10) | ||
}, 10) | ||
}) | ||
} | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
380610
2895