From 93ce6c03413fbf84ba6e79f6cf9c4527f4bad5e0 Mon Sep 17 00:00:00 2001 From: "Hyuk-Beom, Yoon" Date: Mon, 18 Mar 2013 14:30:02 +0900 Subject: [PATCH] 0.0.31 --- README.md | 247 ++++++++++++++++++++-------------------- lib/chain.js | 2 - lib/query.js | 249 +++++++++++++++++++++-------------------- lib/queue.js | 17 ++- lib/queueConnection.js | 31 +++-- package.json | 2 +- test/test.js | 20 ++-- 7 files changed, 289 insertions(+), 279 deletions(-) diff --git a/README.md b/README.md index 5ab1228..e3072c6 100644 --- a/README.md +++ b/README.md @@ -20,24 +20,25 @@ var mysql = require('mysql'); var transaction = require('node-mysql-transaction'); var trCon = transaction({ - // mysql driver set - connection: [mysql.createConnection,{ - user: ..., - password: ..., - database: ..., - ... - }], - - // number of static parallel connection - // you can chose it 0, if you want to use only dynamic connection. - staticConnection:3, - - // when queue length is more than 0, - // make temporary connection for increased volume of async work. - dynamicConnection:3, - - // auto time out rollback in ms - timeOut:600 + // mysql driver set + connection: [mysql.createConnection,{ + user: ..., + password: ..., + database: ..., + ... + }], + + // number of static parallel connection + // you can chose it 0, if you want to use only dynamic connection. + staticConnection:3, + + // when queue length is more than 0, + // make temporary connection for increased volume of async work. + dynamicConnection:3, + + // auto time out rollback in ms + // turn off is 0 + timeOut:600 }); ``` @@ -57,10 +58,10 @@ var chain = trCon.chain(); chain. on('commit', function(){ - console.log('number commit'); + console.log('number commit'); }). on('rollback', function(err){ - console.log(err); + console.log(err); }); chain. @@ -78,10 +79,10 @@ var chain = trCon.chain(); chain. on('commit', function(){ - console.log('number commit'); + console.log('number commit'); }). on('rollback', function(err){ - console.log(err); + console.log(err); }); chain. @@ -90,7 +91,7 @@ query('insert ...'). query('insert ...'). query('insert ...'). on('result', function(result){ - chain.commit(); + chain.commit(); }). autoCommit(false); @@ -103,30 +104,30 @@ var chain = trCon.chain(); chain. on('commit', function(){ - console.log('number commit'); + console.log('number commit'); }). on('rollback', function(err){ - console.log(err); + console.log(err); }); chain. query('insert ...'). on('result', function(result){ - chain. - query('insert ...'). - on('result', function(result){ - console.log('lol'); - }). - query('insert ...'). - on('result',function(result){ - chain. - query('insert ...',[result.insertId]). - query('insert ...'). - query('insert ...'). - query('insert ...') - // auto commit run - // all of this is a single transaction - }).autoCommit(false); + chain. + query('insert ...'). + on('result', function(result){ + console.log('lol'); + }). + query('insert ...'). + on('result',function(result){ + chain. + query('insert ...',[result.insertId]). + query('insert ...'). + query('insert ...'). + query('insert ...') + // auto commit run + // all of this is a single transaction + }).autoCommit(false); }).autoCommit(false); ``` @@ -137,34 +138,26 @@ var chain = trCon.chain(); chain. on('commit', function(){ - console.log('number commit'); + console.log('number commit'); }). on('rollback', function(err){ - console.log(err); + console.log(err); }); chain. query('insert ...'). on('result', function(result){ - console.log(result.insertId); + console.log(result.insertId); }). query('insert ...'). on('result', function(result){ - console.log(result.insertId); -}). -query('insert ...'). -on('result', function(result){ - console.log(result.insertId); -}). -query('insert ...'). -on('result', function(result){ - chain.commit(); + chain.commit(); }). autoCommit(false); ``` -Unlike auto commit, auto rollback is always working. But if you attach error event listener to the query, auto commit is turn off in that query. +Unlike autocommit, auto rollback is always running. But if you attach error event listener to the query, auto rollback is turn off in that query. ``` var chain = trCon.chain(); @@ -174,10 +167,10 @@ var chain = trCon.chain(); chain. query('insert ...'). on('error', function(err){ - console.log(err); - // now auto rollback turn off + console.log(err); + // now auto rollback is turned off }). -// other query's auto rollback is still works +// other queries auto rollback is still works query('insert ...'). ... ``` @@ -188,84 +181,102 @@ chain can make a loop. var chain = trCon.chain(); chain. on('commit', function(){ - console.log('chain commit'); + console.log('chain commit'); }). on('rollback', function(err){ - console.log(err); + console.log(err); }); for(var i = 0; i < 10; i+=1) { - // loop in transaction - chain.query('insert ...',[...]); + // loop in transaction + chain.query('insert ...',[...]); } ``` +###Terminating + +Call end method. Method sending error to all callback function in the queue and connection terminating after current transaction finished. + +``` +trCon.end() +``` + ###transaction query query is not recommended method. The query method can be removal in a next version. -.query style transaction can usable. But you will be changed some error handling way. +.query style transaction can usable. But, in some case, the method is slower than chain. And you will make a lot of indent. ``` // With old style error handling +// if you choose this way, auto rollback and timeout rollback is turn off trCon.query('insert ...',[...],function(err,result){ - if (err) { - result.rollback(); - } - trCon.query('insert ...',['err'],function(err,otherResult){ - if (err) { - otherResult.rollback(); - } - trCon.query('insert ...',[...],function(err,theOtherResult){ - if (err) { - theOtherResult.rollback(); - } - // It's bad idea because you cannot take any message when time out rollback occur. - }); - }); + if (err) { + return result.rollback(); + } + trCon.query('insert ...',[...],function(err,otherResult){ + if (err) { + return otherResult.rollback(); + } + trCon.query('insert ...',[...],function(err,theOtherResult){ + if (err) { + return theOtherResult.rollback(); + } + theOtherResult.commit(function(err){ + if (!err) { + console.log('complete') + } + }); + }); + }); }) ``` -Use rollback event for error handling. +You can choose rollback event for an error handling. In this way, you can turn on auto rollback and timeout rollback. ``` +// now auto rollback and timeout rollback is working. +// you don't need any error handling in the middle of transaction +// If you call the query method after call end method, error occurred to callback function + trCon.query('insert ...',[...],function(err,result){ - trCon.query('insert ...',['err'],function(err,otherResult){ - - trCon.query('insert ...',[...],function(err,theOtherResult){ - // now auto rollback is working - // you don't need any error handling in the middle of transaction - }); - }); + trCon.query('insert ...',['err'],function(err,otherResult){ + + trCon.query('insert ...',[...],function(err,theOtherResult){ + + }); + }); }). on('rollback', function(err){ - // error linked to here after rollback occur - console.log('trCon.query auto rollback'); + // normal error linked to here after rollback occur + console.log('trCon.query auto rollback'); }); ``` -Also auto commit can off. +auto commit can turn off. ``` +// result.rollback === otherResult.rollback === theOtherResult.rollback; + trCon.query('insert ...',[...],function(err,result){ - trCon.query('insert ...',[...],function(err,otherResult){ - trCon.query('insert ...',[...],function(err,theOtherResult){ - // auto commit off - theOtherResult.autoCommit(false); - - setTimeout(function(){ - theOtherResult.commit(); - // result.rollback === otherResult.rollback === theOtherResult.rollback; - },0); - }); - }); + trCon.query('insert ...',[...],function(err,otherResult){ + trCon.query('insert ...',[...],function(err,theOtherResult){ + // auto commit off + theOtherResult.autoCommit(false); + + setTimeout(function(){ + theOtherResult.commit(); + + },0); + }); + }); }). on('commit', function(){ - console.log('manual commit'); + console.log('manual commit'); }). on('rollback',function(err){ - console.log(err); + console.log(err); }); ``` @@ -273,33 +284,27 @@ Unlike chain method, .query method cannot linked to other event loop. even auto ``` trCon.query('insert ...',[...],function(err,result){ - trCon.query('insert ...',[...],function(err,theOtherResult){ - // auto commit off - theOtherResult.autoCommit(false); - - setTimeout(function(){ - trCon.query('insert ...',[...],function(err,otherTransactionResult){ - // This is new transaction!! - // Earlier 2 insert query now, just waiting time out rollback. - ... - }); - },0); - }); + trCon.query('insert ...',[...],function(err,theOtherResult){ + // auto commit off + theOtherResult.autoCommit(false); + + setTimeout(function(){ + trCon.query('insert ...',[...],function(err,otherTransactionResult){ + // This is new transaction!! + // Now, earlier 2 insert query just waiting timeout rollback. + ... + }); + },0); + }); }). on('commit', function(){ - console.log('manual commit'); + console.log('manual commit'); }). on('rollback',function(err){ - console.log(err); + console.log(err); }); ``` -###Terminating -Call end method. Method sending error to all callback function in the queue and connection terminating after current transaction finished. -``` -trCon.end() -``` - Update --- @@ -311,4 +316,6 @@ Update 0.0.23: fix process.nextTick recursive. now module fit to the node.js 0.10 -0.0.3: default chain method setMaxListeners is 0. code and internal API update. \ No newline at end of file +0.0.3: default chain method setMaxListeners is 0. code and internal API update. + +0.0.31: query method update. \ No newline at end of file diff --git a/lib/chain.js b/lib/chain.js index f6fcb25..914adc9 100644 --- a/lib/chain.js +++ b/lib/chain.js @@ -1,5 +1,3 @@ -// minimum safty timer for chain work commit -// safeCon._count is count of not finished query var events = require("events"); module.exports = chainFactory diff --git a/lib/query.js b/lib/query.js index a5c871d..4949c4e 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1,129 +1,132 @@ var events = require("events"); module.exports = quaryFactory +function quaryFactory (queueControl) { + var query = Object.create(queryObj); + + query.chainOn = false; + query.stateQuery = query.stateUp(); + + query.tool = {}; + query.tool.set = queueControl.set.bind(queueControl); + + return function(){ + return query.stateQuery.apply(query, arguments); + }; +}; -function quaryFactory (queue) { +var queryObj = { + callbackQuery: function(safeCon, arg, position, eventObj) { + var callback = arg[position]; + + arg[position] = function (err, result, raw) { + if (err) { + if (eventObj.listeners('rollback').length) { + return safeCon.rollback(err); + } + } + // if is not a array result + if (!Array.isArray(result)) { + result = resultObjectSet(result, safeCon) + } + // state query function change + // ready to link to the next transaction query + this.stateQuery = this.stateUp(safeCon, eventObj); + + this.chainOn = false; + + callback(err, result, raw); + + // state query function rollback + // ready to take new transaction queue + this.stateQuery = this.stateUp(); + + // auto commit + if (!this.chainOn && result._autoCommit) { + return safeCon.commit(); + } + this.chainOn = false; + }.bind(this); + safeCon.query.apply(null, arg); + return eventObj; + }, + + newCallbackQuery: function(arg, position) { + var eventObj = new events.EventEmitter(); + + // set point + this.tool.set(function(err, safeCon){ + if (err) { + if (eventObj.listeners('rollback').length) { + return eventObj.emit('rollback', err); + } + return arg[position](err); + } + + if (!eventObj.listeners('rollback').length) { + safeCon.timeOut = 0; + } + + safeCon.on('commit',function(){ + eventObj.emit('commit'); + }); + safeCon.on('rollback',function(err){ + eventObj.emit('rollback', err); + }); + + this.callbackQuery(safeCon, arg, position, eventObj); + }.bind(this)); + return eventObj; + }, + + stateUp: function(currentConnection, eventObj){ + var readyState = !!(currentConnection); + return function(){ + this.chainOn = readyState; + for (var position in arguments) { + if (typeof arguments[position] === 'function') { + if (readyState) { + return this.callbackQuery(currentConnection, arguments, position, eventObj); + } + return this.newCallbackQuery(arguments, position); + } + }; + if (readyState) { + return skipCallbackQuery(currentConnection, arguments, eventObj) + } + return null; + } + }, +}; - var chainOn = false; - var errDummy = { - rollback: function(){}, - commit: function(){}, - autoCommit: function(){}, - }; - - function resultObjectSet (result, safeCon) { - result = result || {}; - result.rollback = safeCon.rollback.bind(safeCon); - result.commit = safeCon.commit.bind(safeCon); - result._autoCommit = true; - result.autoCommit = function(select){ - this._autoCommit = select; - }; - return result; - }; - - function skipCallbackQuery (safeCon, arg, eventObj) { - if (!(eventObj.listeners('rollback').length) || !(eventObj.listeners('commit').length)) { - throw new Error('skip callback query must need rollback and commit event listener'); - } - - var query; - try { - query = safeCon.query.apply(null, arg); - } catch(e) { - return safeCon.rollback(e); - } - - query. - on('error', function(err){ - safeCon.rollback(err); - }). - on('end', function(result){ - safeCon.commit(); - }); - }; - - function callbackQuery (safeCon, arg, position, eventObj) { - var callback = arg[position]; - - arg[position] = function (err, result, raw) { - if (err) { - if (eventObj.listeners('rollback').length) { - return safeCon.rollback(err); - } - } - // if is not a array result - if (!Array.isArray(result)) { - result = resultObjectSet(result, safeCon) - } - // state query function change - // ready to link to the next transaction query - stateQuery = stateUp(safeCon, eventObj); - - chainOn = false; - - callback(err, result, raw); - - // state query function rollback - // ready to take new transaction queue - stateQuery = stateUp(); - - // auto commit - if (!chainOn && result._autoCommit) { - return safeCon.commit(); - } - chainOn = false; - }; - safeCon.query.apply(null, arg); - return eventObj; - }; - - function newCallbackQuery (arg, position) { - var eventObj = new events.EventEmitter(); - - // set point - queue.set(function(err, safeCon){ - if (err) { - if (eventObj.listeners('rollback').length) { - return eventObj.emit('rollback', err); - } - return arg[position](err, errDummy); - } - - safeCon.on('commit',function(){ - eventObj.emit('commit'); - }); - safeCon.on('rollback',function(err){ - eventObj.emit('rollback', err); - }); - - callbackQuery(safeCon, arg, position, eventObj); - }); - return eventObj; - }; - - var stateUp; - var stateQuery = (stateUp = function(currentConnection, eventObj){ - var readyState = !!(currentConnection); - - return function(){ - chainOn = readyState; - for (var position in arguments) { - if (typeof arguments[position] === 'function') { - if (readyState) { - return callbackQuery(currentConnection, arguments, position, eventObj); - } - return newCallbackQuery(arguments, position); - } - }; - if (readyState) { - return skipCallbackQuery(currentConnection, arguments, eventObj) - } - return null; - } - })(); - - return function(){ - return stateQuery.apply(null, arguments); - }; +function resultObjectSet (result, safeCon) { + result = result || {}; + result.rollback = safeCon.rollback.bind(safeCon); + result.commit = safeCon.commit.bind(safeCon); + result._autoCommit = true; + result.autoCommit = function(select){ + this._autoCommit = select; + }; + return result; }; + +function skipCallbackQuery (safeCon, arg, eventObj) { + if (!(eventObj.listeners('rollback').length) || !(eventObj.listeners('commit').length)) { + throw new Error('skip callback query must need rollback and commit event listener'); + } + + var query; + try { + query = safeCon.query.apply(null, arg); + } catch(e) { + return safeCon.rollback(e); + } + + query. + on('error', function(err){ + safeCon.rollback(err); + }). + on('end', function(result){ + safeCon.commit(); + }); +}; \ No newline at end of file diff --git a/lib/queue.js b/lib/queue.js index 3110946..b45828d 100644 --- a/lib/queue.js +++ b/lib/queue.js @@ -26,7 +26,7 @@ var queueObj = { this.dynamicConnection.loopOn(); } }, - + usableConnnection: function(){ var length = this.connections.length; while(length){ @@ -37,14 +37,14 @@ var queueObj = { }; return; }, - + decreaseConnection: function(){ var last = this.connections.pop(); if (last) { return last.connectionCut(); } }, - + increaseConnection: function(){ this.connections.push( queueConnection( @@ -52,11 +52,11 @@ var queueObj = { this.config, this.queue)); }, - + queueLength: function(){ return this.queue.length; }, - + end: function(){ this.set = dummySet; this.queueCleaner; @@ -67,7 +67,7 @@ var queueObj = { this.decreaseConnection(); }; }, - + queueCleaner: function(){ var err = new Error('transaction queue cleaner work') var inLoop; @@ -81,13 +81,12 @@ var queueObj = { }.bind(this)); }, }; - + function connectionFactory (opt) { - // connection = mysql.createConnection + // return mysql.createConnection(options) return opt.connection[0](opt.connection[1]); }; - function dummySet () { var err = new Error('transaction connection closed'); for (var i in arguments) { diff --git a/lib/queueConnection.js b/lib/queueConnection.js index db9c315..646655d 100644 --- a/lib/queueConnection.js +++ b/lib/queueConnection.js @@ -17,21 +17,16 @@ function queueConnection (connection, config, queue){ con.tool.connectionQuery = Object.getPrototypeOf(con.connection).query.bind(con.connection); return con; }; - - // return transaction connection(safeConnection) - // safeConnection has commit and rollback API for transaction finish + var queueObj = { safeConnectionFactory: function(target){ - // main query function var safeConnection = new events.EventEmitter(); safeConnection.timeOut = this.timeOut; safeConnection.timer = null; safeConnection.target = target; - safeConnection.usable = safeConMethod.usable.bind(safeConnection, this); - - + safeConnection.usable = safeConMethod.usable.bind(safeConnection, this); safeConnection.query = safeConMethod.query.bind(safeConnection); safeConnection.commit = safeConMethod.commit.bind(safeConnection); safeConnection.rollback = safeConMethod.rollback.bind(safeConnection); @@ -45,8 +40,8 @@ var queueObj = { return safeConnection; }, - - _nextQuery: function(){ + + _next: function(){ if (!this._queue.length || this.workCut) { this.lock = false; return; @@ -66,17 +61,17 @@ var queueObj = { this._currentTransaction(undefined, safeConnection); }.bind(this)); }, - - // internal commit and rollback request query sender + + // internal commit and rollback request query sender commitReq: function (callback){ this.tool.connectionQuery('COMMIT', function(err, result){ if(callback){ callback(err); } }); - this._nextQuery(); + this._next(); }, - + rollbackReq: function(reason, callback){ this.tool.connectionQuery('ROLLBACK', function(err, result){ if (callback) { @@ -86,14 +81,14 @@ var queueObj = { callback(reason); } }); - this._nextQuery(); + this._next(); }, nextQuery: function(){ if (this.lock) { return; } - this._nextQuery(); + this._next(); }, connectionCut: function(){ @@ -107,7 +102,7 @@ var queueObj = { return; }); }.bind(this))(); - } + }, }; var safeConMethod = { @@ -135,6 +130,7 @@ var safeConMethod = { } return this.tool.query.apply(this.tool.connection, arguments); }, + commit: function(callback){ if (!this.usable()) { return; @@ -144,6 +140,7 @@ var safeConMethod = { this.tool.nullCurrentState(); return this.tool.commitReq(callback); }, + rollback: function(reason, callback){ if (!this.usable()) { return; @@ -158,9 +155,11 @@ var safeConMethod = { this.tool.nullCurrentState(); return this.tool.rollbackReq(reason, callback); }, + usable: function(obj){ return (obj._currentTransaction === this.target); }, + nullCurrentState: function(obj){ obj._currentTransaction = null; }, diff --git a/package.json b/package.json index 6d21aaf..245c220 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-mysql-transaction", - "version": "0.0.3", + "version": "0.0.31", "description": "transactions wrapper for node-mysql 2.0 driver", "main": "index.js", "directories": { diff --git a/test/test.js b/test/test.js index 6b9c31e..45c6ab2 100644 --- a/test/test.js +++ b/test/test.js @@ -240,17 +240,21 @@ test.query('insert transaction_test set test=?',[3000],function(err,result){ // time out rollback test setTimeout(function(){ - theOtherResult.commit();// result.rollback === otherResult.rollback; + theOtherResult.commit(function(err){ + if(!err){ + console.log('time out rollback off'); + } + });// result.rollback === otherResult.rollback; },1000); }); }); -}). -on('commit', function(){ - console.log('time out test commit??'); -}). -on('rollback',function(err){ - console.log(err); -}); +})//. +// on('commit', function(){ + // console.log('time out test commit??'); +// }). +// on('rollback',function(err){ + // console.log(err); +// }); test.query('insert transaction_test set test=?',[4000],function(err,result){ test.query('insert transaction_test set test=?',[3999],function(err,otherResult){