Skip to content

Commit 9157342

Browse files
authored
Merge pull request #576 from share/ping-pong
✨ Add ping/pong
2 parents 8b531be + 56ac7a8 commit 9157342

File tree

5 files changed

+71
-0
lines changed

5 files changed

+71
-0
lines changed

lib/agent.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,8 @@ Agent.prototype._handleMessage = function(request, callback) {
447447
return this._subscribePresence(request.ch, request.seq, callback);
448448
case ACTIONS.presenceUnsubscribe:
449449
return this._unsubscribePresence(request.ch, request.seq, callback);
450+
case ACTIONS.pingPong:
451+
return this._pingPong(callback);
450452
default:
451453
callback(new ShareDBError(ERROR_CODE.ERR_MESSAGE_BADLY_FORMED, 'Invalid or unknown message'));
452454
}
@@ -540,6 +542,14 @@ Agent.prototype._querySubscribe = function(queryId, collection, query, options,
540542
});
541543
};
542544

545+
Agent.prototype._pingPong = function(callback) {
546+
var error = null;
547+
var message = {
548+
a: ACTIONS.pingPong
549+
};
550+
callback(error, message);
551+
};
552+
543553
function getResultsData(results) {
544554
var items = [];
545555
for (var i = 0; i < results.length; i++) {

lib/client/connection.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,8 @@ Connection.prototype.handleMessage = function(message) {
253253
return this._handlePresenceUnsubscribe(err, message);
254254
case ACTIONS.presenceRequest:
255255
return this._handlePresenceRequest(err, message);
256+
case ACTIONS.pingPong:
257+
return this._handlePingPong(err);
256258

257259
default:
258260
logger.warn('Ignoring unrecognized message', message);
@@ -476,6 +478,19 @@ Connection.prototype.send = function(message) {
476478
this.socket.send(JSON.stringify(message));
477479
};
478480

481+
Connection.prototype.ping = function() {
482+
if (!this.canSend) {
483+
throw new ShareDBError(
484+
ERROR_CODE.ERR_CANNOT_PING_OFFLINE,
485+
'Socket must be CONNECTED to ping'
486+
);
487+
}
488+
489+
var message = {
490+
a: ACTIONS.pingPong
491+
};
492+
this.send(message);
493+
};
479494

480495
/**
481496
* Closes the socket and emits 'closed'
@@ -725,6 +740,11 @@ Connection.prototype._handleHandshake = function(error, message) {
725740
this._initialize(message);
726741
};
727742

743+
Connection.prototype._handlePingPong = function(error) {
744+
if (error) return this.emit('error', error);
745+
this.emit('pong');
746+
};
747+
728748
Connection.prototype._initialize = function(message) {
729749
if (this.state !== 'connecting') return;
730750

lib/error.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ ShareDBError.CODES = {
1616
ERR_APPLY_OP_VERSION_DOES_NOT_MATCH_SNAPSHOT: 'ERR_APPLY_OP_VERSION_DOES_NOT_MATCH_SNAPSHOT',
1717
ERR_APPLY_SNAPSHOT_NOT_PROVIDED: 'ERR_APPLY_SNAPSHOT_NOT_PROVIDED',
1818
ERR_CLIENT_ID_BADLY_FORMED: 'ERR_CLIENT_ID_BADLY_FORMED',
19+
ERR_CANNOT_PING_OFFLINE: 'ERR_CANNOT_PING_OFFLINE',
1920
ERR_CONNECTION_SEQ_INTEGER_OVERFLOW: 'ERR_CONNECTION_SEQ_INTEGER_OVERFLOW',
2021
ERR_CONNECTION_STATE_TRANSITION_INVALID: 'ERR_CONNECTION_STATE_TRANSITION_INVALID',
2122
ERR_DATABASE_ADAPTER_NOT_FOUND: 'ERR_DATABASE_ADAPTER_NOT_FOUND',

lib/message-actions.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ exports.ACTIONS = {
1414
op: 'op',
1515
snapshotFetch: 'nf',
1616
snapshotFetchByTimestamp: 'nt',
17+
pingPong: 'pp',
1718
presence: 'p',
1819
presenceSubscribe: 'ps',
1920
presenceUnsubscribe: 'pu',

test/client/connection.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,45 @@ describe('client connection', function() {
124124
});
125125
});
126126

127+
describe('ping/pong', function() {
128+
it('pings the backend', function(done) {
129+
var connection = this.backend.connect();
130+
131+
connection.on('pong', function() {
132+
done();
133+
});
134+
135+
connection.on('connected', function() {
136+
connection.ping();
137+
});
138+
});
139+
140+
it('handles errors', function(done) {
141+
this.backend.use('receive', function(request, next) {
142+
var error = request.data.a === 'pp' && new Error('bad');
143+
next(error);
144+
});
145+
146+
var connection = this.backend.connect();
147+
148+
connection.on('error', function(error) {
149+
expect(error.message).to.equal('bad');
150+
done();
151+
});
152+
153+
connection.on('connected', function() {
154+
connection.ping();
155+
});
156+
});
157+
158+
it('throws if pinging offline', function() {
159+
var connection = this.backend.connect();
160+
expect(function() {
161+
connection.ping();
162+
}).to.throw('Socket must be CONNECTED to ping');
163+
});
164+
});
165+
127166
describe('backend.agentsCount', function() {
128167
it('updates after connect and connection.close()', function(done) {
129168
var backend = this.backend;

0 commit comments

Comments
 (0)