Skip to content

Commit 3cfcb13

Browse files
committed
Test suite beginning
* Readme reflects subtree zongji * Example updated
1 parent 2e71400 commit 3cfcb13

10 files changed

+194
-38
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@
33
*.swo
44
.npm
55
node_modules/mysql
6+
node_modules/.bin
7+
node_modules/nodeunit

README.md

+8-16
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,12 @@ Built using the [`zongji` Binlog Tailer](https://github.com/nevill/zongji) and [
66

77
## *Under Construction*
88

9-
This package is yet completed. In order to test it, please use the following command sequence as a guide:
9+
This package is not yet completed. In order to test it, you must clone the repo. Please use the following command sequence as a guide:
1010

1111
```bash
1212
$ git clone https://github.com/numtel/mysql-live-select.git
1313
$ cd mysql-live-select
1414
$ npm install
15-
$ cd node_modules
16-
# Updated ZongJi module not yet available on NPM, clone repo instead:
17-
$ git clone https://github.com/nevill/zongji.git
18-
$ cd ..
1915
# To use example as-is, copy example data into MySQL
2016
$ mysql < example.sql
2117
# Configure example to match your MySQL settings
@@ -25,24 +21,18 @@ $ vim example.js
2521
$ node example.js
2622
```
2723

28-
Coming soon:
29-
30-
* Automated tests
31-
3224
## Installation
3325

3426
* Enable MySQL binlog in `my.cnf`, restart MySQL server after making the changes.
3527

3628
```
3729
# binlog config
3830
server-id = 1
31+
binlog_format = row
3932
log_bin = /usr/local/var/log/mysql/mysql-bin.log
4033
binlog_do_db = employees # optional
4134
expire_logs_days = 10 # optional
4235
max_binlog_size = 100M # optional
43-
44-
# Very important if you want to receive write, update and delete row events
45-
binlog_format = row
4636
```
4737
* Create an account with replication privileges:
4838

@@ -67,21 +57,23 @@ Setting | Type | Description
6757

6858
```javascript
6959
// Example:
70-
var table = 'my_table';
60+
var liveConnection = new LiveMysql(settings);
61+
var table = 'players';
7162
var id = 11;
7263

73-
liveMysqlInstance.select(function(esc, escId){
64+
liveConnection.select(function(esc, escId){
7465
return (
7566
'select * from ' + escId(table) +
7667
'where `id`=' + esc(id)
7768
);
78-
}, [
69+
}, [ {
7970
table: table,
8071
condition: function(row, newRow){ return row.id === id; }
81-
]).on('update', function(data){
72+
} ]).on('update', function(data){
8273
console.log(data);
8374
});
8475
```
76+
See [`example.js`](example.js) for full source...
8577

8678

8779
### LiveMysql.prototype.select(query, triggers)

example.js

+13-18
Original file line numberDiff line numberDiff line change
@@ -7,26 +7,21 @@ var settings = {
77
database : 'leaderboard',
88
serverId : 34,
99
minInterval : 200
10-
// debug: true
1110
};
1211

1312
var liveConnection = new LiveMysql(settings);
14-
// var result = liveConnection.select(
15-
// 'select * from players',
16-
// [
17-
// { table: 'players' }
18-
// ]
19-
// );
20-
// result.on('update', function(event){
21-
// // do something to update the client
22-
// console.log(event);
23-
// });
13+
var table = 'players';
14+
var id = 11;
2415

25-
liveConnection.select('select score from players where id=11', [
26-
{
27-
table: 'players',
28-
condition: function(row, newRow){ return row.id === 11; }
29-
}
30-
]).on('update', function(event){
31-
console.log(event);
16+
liveConnection.select(function(esc, escId){
17+
return (
18+
'select * from ' + escId(table) +
19+
'where `id`=' + esc(id)
20+
);
21+
}, [ {
22+
table: table,
23+
condition: function(row, newRow){ return row.id === id; }
24+
} ]).on('update', function(data){
25+
console.log(data);
3226
});
27+

lib/LiveMysql.js

+8-1
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@ function LiveMysql(settings){
2020
if(event.getEventName() === 'tablemap') return;
2121

2222
self._select.forEach(function(select){
23-
if(select.matchRowEvent(event))
23+
if(select.matchRowEvent(event)){
2424
select.update();
25+
}
2526
});
2627
});
2728

@@ -39,5 +40,11 @@ LiveMysql.prototype.select = function(query, triggers){
3940
return newSelect;
4041
};
4142

43+
LiveMysql.prototype.end = function(){
44+
var self = this;
45+
self.zongji.stop();
46+
self.db.destroy();
47+
};
48+
4249

4350
module.exports = LiveMysql;

lib/LiveMysqlSelect.js

+22-3
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@ function LiveMysqlSelect(query, triggers, base){
1313

1414
var self = this;
1515
EventEmitter.call(self);
16-
self.query = self._escapeQueryFun(query);
1716
self.triggers = triggers;
1817
self.base = base;
1918
self.lastUpdate = 0;
19+
self.query = self._escapeQueryFun(query);
2020

2121
self.update();
2222
}
@@ -42,6 +42,12 @@ LiveMysqlSelect.prototype.matchRowEvent = function(event){
4242
trigger = self.triggers[i];
4343
triggerDatabase = trigger.database ||
4444
self.base.settings.database;
45+
46+
if(triggerDatabase === undefined){
47+
self.emit('error', new Error('no database selected'));
48+
return false;
49+
}
50+
4551
if(triggerDatabase === tableMap.parentSchema &&
4652
trigger.table === tableMap.tableName){
4753
if(trigger.condition === undefined){
@@ -64,8 +70,8 @@ LiveMysqlSelect.prototype.matchRowEvent = function(event){
6470

6571
LiveMysqlSelect.prototype.update = function(){
6672
var self = this;
67-
if(self.base.settings.minInterval === undefined ||
68-
self.lastUpdate + self.base.settings.minInterval < Date.now()){
73+
74+
function _update(){
6975
self.base.db.query(self.query, function(error, rows){
7076
if(error){
7177
self.emit('error', error);
@@ -75,6 +81,19 @@ LiveMysqlSelect.prototype.update = function(){
7581
}
7682
});
7783
}
84+
85+
if(self.base.settings.minInterval === undefined){
86+
_update();
87+
}else if(self.lastUpdate + self.base.settings.minInterval < Date.now()){
88+
_update();
89+
}else{ // Before minInterval
90+
if(!self._updateTimeout){
91+
self._updateTimeout = setTimeout(function(){
92+
delete self._updateTimeout;
93+
_update();
94+
}, self.lastUpdate + self.base.settings.minInterval - Date.now());
95+
}
96+
}
7897
};
7998

8099
module.exports = LiveMysqlSelect;

package.json

+3
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,8 @@
1818
"license": "MIT",
1919
"dependencies": {
2020
"mysql": "^2.5.4"
21+
},
22+
"devDependencies": {
23+
"nodeunit": "^0.9.0"
2124
}
2225
}

test/helpers/connector.js

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/* mysql-live-select, MIT License [email protected]
2+
test/helpers/connector.js - Connect to database */
3+
var EventEmitter = require('events').EventEmitter;
4+
var util = require('util');
5+
var LiveMysql = require('../../');
6+
var querySequence = require('./querySequence');
7+
8+
function Connector(settings){
9+
var self = this;
10+
EventEmitter.call(self);
11+
self.database = settings.database;
12+
delete settings.database;
13+
self.conn = new LiveMysql(settings);
14+
self.ready = false;
15+
var escId = self.conn.db.escapeId;
16+
var esc = self.conn.db.escape.bind(self.conn.db);
17+
18+
querySequence(self.conn.db, [
19+
'DROP DATABASE IF EXISTS ' + escId(self.database),
20+
'CREATE DATABASE ' + escId(self.database),
21+
'USE ' + escId(self.database),
22+
], function(results){
23+
self.ready = true;
24+
self.emit('ready', self.conn, esc, escId);
25+
});
26+
27+
setTimeout(function(){
28+
self.on('newListener', function(event, listener){
29+
if(event === 'ready'){
30+
if(self.ready) listener(self.conn, esc, escId);
31+
}
32+
});
33+
}, 1);
34+
35+
};
36+
37+
util.inherits(Connector, EventEmitter);
38+
39+
module.exports = Connector;

test/helpers/querySequence.js

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Execute a sequence of queries on a node-mysql database connection
2+
// @param {object} connection - Node-Mysql Connection, Connected
3+
// @param {boolean} debug - Print queries as they execute (optional)
4+
// @param {[string]} queries - Queries to execute, in order
5+
// @param {function} callback - Call when complete
6+
module.exports = function(connection, debug, queries, callback){
7+
if(debug instanceof Array){
8+
callback = queries;
9+
queries = debug;
10+
debug = false;
11+
}
12+
var results = [];
13+
var sequence = queries.map(function(queryStr, index, initQueries){
14+
return function(){
15+
debug && console.log('Query Sequence', index, queryStr);
16+
connection.query(queryStr, function(err, rows, fields){
17+
if(err) throw err;
18+
results.push(rows);
19+
if(index < sequence.length - 1){
20+
sequence[index + 1]();
21+
}else{
22+
callback(results);
23+
}
24+
});
25+
}
26+
});
27+
sequence[0]();
28+
};

test/index.js

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/* mysql-live-select, MIT License [email protected]
2+
test/index.js - Test Suite */
3+
var LiveMysql = require('../');
4+
var settings = require('./settings/mysql');
5+
var querySequence = require('./helpers/querySequence');
6+
var Connector = require('./helpers/connector');
7+
var server = new Connector(settings);
8+
9+
module.exports = {
10+
basic: function(test){
11+
var table = 'simple';
12+
server.on('ready', function(conn, esc, escId){
13+
querySequence(conn.db, [
14+
'DROP TABLE IF EXISTS ' + escId(table),
15+
'CREATE TABLE ' + escId(table) + ' (col INT UNSIGNED)',
16+
'INSERT INTO ' + escId(table) + ' (col) VALUES (10)',
17+
], function(results){
18+
19+
conn.select('SELECT * FROM ' + escId(table), [ {
20+
database: server.database,
21+
table: table
22+
} ]).on('update', function(data){
23+
if(data[0].col === 15){
24+
test.ok(true);
25+
test.done();
26+
}
27+
});
28+
29+
querySequence(conn.db, [
30+
'UPDATE ' + escId(table) +
31+
'SET `col` = 15'
32+
], function(results){
33+
// ...
34+
});
35+
});
36+
});
37+
},
38+
error_no_db_selected: function(test){
39+
var table = 'error_no_db';
40+
server.on('ready', function(conn, esc, escId){
41+
querySequence(conn.db, [
42+
'DROP TABLE IF EXISTS ' + escId(table),
43+
'CREATE TABLE ' + escId(table) + ' (col INT UNSIGNED)',
44+
'INSERT INTO ' + escId(table) + ' (col) VALUES (10)',
45+
], function(results){
46+
47+
conn.select('SELECT * FROM ' + escId(table), [ {
48+
table: table
49+
} ]).on('error', function(error){
50+
test.equal(error.toString(), 'Error: no database selected');
51+
test.done();
52+
});
53+
54+
querySequence(conn.db, [
55+
'UPDATE ' + escId(table) +
56+
'SET `col` = 15'
57+
], function(results){
58+
// ...
59+
});
60+
});
61+
});
62+
}
63+
}

test/settings/mysql.js

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
module.exports = {
2+
host : 'localhost',
3+
user : 'root',
4+
password : 'numtel',
5+
database : 'live_select_test',
6+
serverId : 347,
7+
minInterval : 200
8+
};

0 commit comments

Comments
 (0)