Connection.ping() implementation

This commit is contained in:
rusher
2018-03-15 18:07:03 +01:00
parent 0cf38965fd
commit db1b43f430
8 changed files with 94 additions and 19 deletions

View File

@ -69,11 +69,11 @@ script:
- docker-compose -f .travis/docker-compose.yml up -d - docker-compose -f .travis/docker-compose.yml up -d
- nvm ls-remote - nvm ls-remote
- npm install - npm install
#to permit benchmark with mariasql
- npm install mariasql
- node --version - node --version
- yarn --version - yarn --version
- node .travis/wait-for-docker-up.js - node .travis/wait-for-docker-up.js
- if [ -n "$LINT" ] ; then yarn run test:lint; fi - if [ -n "$LINT" ] ; then yarn run test:lint; fi
- if [ -z "$BENCH$LINT" ] ; then yarn run test:base; fi - if [ -z "$BENCH$LINT" ] ; then yarn run test:base; fi
# to permit benchmark with mariasql
- if [ -n "$BENCH" ] ; then npm install mariasql; fi
- if [ -n "$BENCH" ] ; then yarn run benchmark; fi - if [ -n "$BENCH" ] ; then yarn run benchmark; fi

View File

@ -11,9 +11,9 @@ common API to mysql/mysql2:
* `connect(callback)`: Connect event with callback * `connect(callback)`: Connect event with callback
* `changeUser(options, callback)`: change current connection user * `changeUser(options, callback)`: change current connection user
* `beginTransaction(options, callback)`: begin transaction * `beginTransaction(options, callback)`: begin transaction
* `commit(options, callback)`: commit current transaction * `commit(options, callback)`: commit current transaction if any
* `rollback(options, callback)`: rollback current transaction * `rollback(options, callback)`: rollback current transaction if any
* `ping(options, callback)`: send an empty packet to server to ensure connection * `ping(options, callback)`: send an empty packet to server to check that connection is active
* `query(sql[, values][,callback])`: execute a [query](#query). * `query(sql[, values][,callback])`: execute a [query](#query).
* `pause()`: pause socket output. * `pause()`: pause socket output.
* `resume()`: resume socket output. * `resume()`: resume socket output.
@ -30,7 +30,7 @@ Not implemented :
* `format(sql, value)` * `format(sql, value)`
* `stats(options, callback)` * `stats(options, callback)`
escape function are not implemented, since it can lead to injection. escape function are not intentionally implemented, since it can lead to injection. use Connection.query(sql, values), it will be more secure and faster
statistic method is public in mysql, but not documented. statistic method is public in mysql, but not documented.
### Initiate a connection ### Initiate a connection
@ -59,7 +59,7 @@ var conn3 = mariadb.createConnection({host: 'mydb.com', port:9999});
### Connection options ### Connection options
#### important option #### Important option
* `user`: string. user * `user`: string. user
* `host`: string. IP or DNS of database server. default: 'localhost' * `host`: string. IP or DNS of database server. default: 'localhost'
@ -81,12 +81,13 @@ For those integer that are not in [safe](https://developer.mozilla.org/en-US/doc
* `bigNumberStrings`: if integer is not in "safe" range, the value will be return as a string. * `bigNumberStrings`: if integer is not in "safe" range, the value will be return as a string.
* `supportBigNumbers`: if integer is not in "safe" range, the value will be return as a [Long](https://www.npmjs.com/package/long) object. * `supportBigNumbers`: if integer is not in "safe" range, the value will be return as a [Long](https://www.npmjs.com/package/long) object.
#### ssl #### Ssl
//TODO describe all solutions
//TODO describe all solutions
* `ssl`: string/object. * `ssl`: string/object.
#### other option #### Other options
* `charset`: string. define charset exchange with server. default: UTF8MB4_UNICODE_CI * `charset`: string. define charset exchange with server. default: UTF8MB4_UNICODE_CI
* `dateStrings`: boolean. indicate if date must be retrived as string (not as date). default: false * `dateStrings`: boolean. indicate if date must be retrived as string (not as date). default: false

View File

@ -29,7 +29,7 @@ class Command extends EventEmitter {
throwError(err) { throwError(err) {
if (this.onResult) { if (this.onResult) {
this.onResult(err); process.nextTick(this.onResult, err);
} else { } else {
this.emit("error", err); this.emit("error", err);
} }

63
src/cmd/ping.js Normal file
View File

@ -0,0 +1,63 @@
"use strict";
const Command = require("./command");
const Utils = require("../misc/utils");
/**
* send a COM_PING: permits sending a packet containing one byte to check that the connection is active.
* see https://mariadb.com/kb/en/library/com_ping/
*/
class Ping extends Command {
constructor(connEvents, onResult) {
super(connEvents);
this.onResult = onResult;
}
start(out, opts, info) {
out.startPacket(this);
out.writeInt8(0x0e);
out.flushBuffer(true);
return this.readPingResponsePacket;
}
/**
* Read ping response packet.
* packet can be :
* - an ERR_Packet
* - a OK_Packet
*
* @param packet query response
* @param out output writer
* @param opts connection options
* @param info connection info
* @returns {null}
*/
readPingResponsePacket(packet, out, opts, info) {
switch (packet.peek()) {
//*********************************************************************************************************
//* OK response
//*********************************************************************************************************
case 0x00:
packet.skip(1); //skip header
info.status = packet.readUInt16();
if (this.onResult) process.nextTick(this.onResult, null);
this.emit("end");
return null;
//*********************************************************************************************************
//* ERROR response
//*********************************************************************************************************
case 0xff:
const err = packet.readError(info);
this.throwError(err);
return null;
default:
const errUnexpected = Utils.createError("unexpected packet", false, info);
this.throwError(errUnexpected);
return null;
}
}
}
module.exports = Ping;

View File

@ -188,11 +188,10 @@ class ResultSet extends Command {
columns = this._columns; columns = this._columns;
} }
const self = this;
if (columns) { if (columns) {
process.nextTick(() => self.onResult(null, rows, columns)); process.nextTick(this.onResult, null, rows, columns);
} else { } else {
process.nextTick(() => self.onResult(null, rows)); process.nextTick(this.onResult, null, rows);
} }
} }

View File

@ -12,6 +12,7 @@ const tls = require("tls");
/*commands*/ /*commands*/
const Handshake = require("./cmd/handshake/handshake"); const Handshake = require("./cmd/handshake/handshake");
const Quit = require("./cmd/quit"); const Quit = require("./cmd/quit");
const Ping = require("./cmd/ping");
const Utils = require("./misc/utils"); const Utils = require("./misc/utils");
const Query = require("./cmd/query"); const Query = require("./cmd/query");
@ -153,7 +154,8 @@ class Connection {
} }
ping(options, callback) { ping(options, callback) {
//TODO const _cb = typeof options === "function" ? options : callback;
return this._addCommand(new Ping(this._events, _cb));
} }
/** /**
@ -205,7 +207,7 @@ class Connection {
self._cmd.emit("error", err); self._cmd.emit("error", err);
} }
} }
process.nextTick(() => self._socket.destroy()); process.nextTick(self._socket.destroy);
killCon.end(); killCon.end();
}); });
} else { } else {
@ -416,7 +418,7 @@ class Connection {
_addCommandEnable(cmd) { _addCommandEnable(cmd) {
let conn = this; let conn = this;
cmd.once("end", () => process.nextTick(() => conn._nextCmd())); cmd.once("end", () => process.nextTick(conn._nextCmd.bind(conn)));
if (!this._cmd && this._cmdQueue.isEmpty()) { if (!this._cmd && this._cmdQueue.isEmpty()) {
this._cmd = cmd; this._cmd = cmd;
this._cmd.init(this._out, this.opts, this.info); this._cmd.init(this._out, this.opts, this.info);

View File

@ -1,3 +1,5 @@
"use strict";
const base = require("../base.js"); const base = require("../base.js");
const assert = require("chai").assert; const assert = require("chai").assert;

View File

@ -3,7 +3,7 @@
const base = require("../base.js"); const base = require("../base.js");
const assert = require("chai").assert; const assert = require("chai").assert;
describe("connection event", () => { describe("connection", () => {
it("multiple connect call", function(done) { it("multiple connect call", function(done) {
const conn = base.createConnection(); const conn = base.createConnection();
conn.connect(err => { conn.connect(err => {
@ -22,7 +22,7 @@ describe("connection event", () => {
}); });
}); });
it("event", function(done) { it("connection event subscription", function(done) {
let eventNumber = 0; let eventNumber = 0;
const conn = base.createConnection(); const conn = base.createConnection();
conn.on("connect", () => { conn.on("connect", () => {
@ -42,4 +42,12 @@ describe("connection event", () => {
const query = conn.query("KILL CONNECTION_ID()"); const query = conn.query("KILL CONNECTION_ID()");
query.on("error", () => {}); query.on("error", () => {});
}); });
it("connection ping", function(done) {
shareConn.ping();
shareConn.ping(err => {
if (err) done(err);
done();
});
});
}); });