mirror of https://github.com/calzoneman/sync.git
Handle errors in broadcast emit
This commit is contained in:
parent
3547a51f2c
commit
f0ba3a998a
|
@ -27,7 +27,7 @@ class UWSWrapper extends EventEmitter {
|
||||||
|
|
||||||
this._uwsSocket = socket;
|
this._uwsSocket = socket;
|
||||||
this._joined = new Set();
|
this._joined = new Set();
|
||||||
this._connected = true;
|
this.disconnected = false;
|
||||||
|
|
||||||
this.context = new UWSContext({
|
this.context = new UWSContext({
|
||||||
connection: {
|
connection: {
|
||||||
|
@ -50,7 +50,7 @@ class UWSWrapper extends EventEmitter {
|
||||||
this._decode(message);
|
this._decode(message);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
LOGGER.warn(
|
LOGGER.warn(
|
||||||
'Decode failed (ip=%s): %s',
|
'Decode failed for client %s: %s',
|
||||||
this.context.ipAddress,
|
this.context.ipAddress,
|
||||||
error
|
error
|
||||||
);
|
);
|
||||||
|
@ -59,7 +59,7 @@ class UWSWrapper extends EventEmitter {
|
||||||
});
|
});
|
||||||
|
|
||||||
this._uwsSocket.on('close', () => {
|
this._uwsSocket.on('close', () => {
|
||||||
this._connected = false;
|
this.disconnected = true;
|
||||||
|
|
||||||
for (let room of this._joined) {
|
for (let room of this._joined) {
|
||||||
rooms.delete(room, this);
|
rooms.delete(room, this);
|
||||||
|
@ -68,27 +68,23 @@ class UWSWrapper extends EventEmitter {
|
||||||
this._joined.clear();
|
this._joined.clear();
|
||||||
this._emit('disconnect');
|
this._emit('disconnect');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this._uwsSocket.on('error', error => {
|
||||||
|
// TODO: determine what conditions cause this
|
||||||
|
LOGGER.error(
|
||||||
|
'Error for client %s: %s',
|
||||||
|
this.context.ipAddress,
|
||||||
|
error.stack
|
||||||
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
disconnect() {
|
disconnect() {
|
||||||
this._uwsSocket.terminate();
|
this._uwsSocket.terminate();
|
||||||
}
|
}
|
||||||
|
|
||||||
get disconnected() {
|
|
||||||
return !this._connected;
|
|
||||||
}
|
|
||||||
|
|
||||||
emit(frame, payload) {
|
emit(frame, payload) {
|
||||||
try {
|
sendSafe(this, encode(frame, payload));
|
||||||
this._uwsSocket.send(encode(frame, payload));
|
|
||||||
} catch (error) {
|
|
||||||
LOGGER.error(
|
|
||||||
'Emit failed (ip=%s): %s',
|
|
||||||
this.context.ipAddress,
|
|
||||||
error.stack
|
|
||||||
);
|
|
||||||
this.disconnect();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
join(room) {
|
join(room) {
|
||||||
|
@ -132,11 +128,14 @@ class UWSWrapper extends EventEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
_ack(ackId, payload) {
|
_ack(ackId, payload) {
|
||||||
this._uwsSocket.send(JSON.stringify({
|
sendSafe(
|
||||||
type: TYPE_ACK,
|
this,
|
||||||
ackId,
|
JSON.stringify({
|
||||||
payload
|
type: TYPE_ACK,
|
||||||
}));
|
ackId,
|
||||||
|
payload
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_decode(message) {
|
_decode(message) {
|
||||||
|
@ -153,13 +152,7 @@ class UWSWrapper extends EventEmitter {
|
||||||
const args = [payload];
|
const args = [payload];
|
||||||
|
|
||||||
if (typeof ackId === 'number') {
|
if (typeof ackId === 'number') {
|
||||||
args.push(payload => {
|
args.push(payload => this._ack(ackId, payload));
|
||||||
try {
|
|
||||||
this._ack(ackId, payload);
|
|
||||||
} catch (error) {
|
|
||||||
LOGGER.error('Error in ack callback: %s', error.stack);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this._emit(frame, ...args);
|
this._emit(frame, ...args);
|
||||||
|
@ -231,13 +224,26 @@ function encode(frame, payload) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function sendSafe(socket, message) {
|
||||||
|
try {
|
||||||
|
socket._uwsSocket.send(message);
|
||||||
|
} catch (error) {
|
||||||
|
LOGGER.error(
|
||||||
|
'Error sending to client %s: %s',
|
||||||
|
socket.context.ipAddress,
|
||||||
|
error.stack
|
||||||
|
);
|
||||||
|
socket.disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function inRoom(room) {
|
function inRoom(room) {
|
||||||
return {
|
return {
|
||||||
emit(frame, payload) {
|
emit(frame, payload) {
|
||||||
const encoded = encode(frame, payload);
|
const encoded = encode(frame, payload);
|
||||||
|
|
||||||
for (let wrapper of rooms.get(room)) {
|
for (let wrapper of rooms.get(room)) {
|
||||||
wrapper._uwsSocket.send(encoded);
|
sendSafe(wrapper, encoded);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -179,4 +179,43 @@ describe('UWSServer', () => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('catches errors during socket.emit()', done => {
|
||||||
|
server.on('connection', s => {
|
||||||
|
s.join('testroom');
|
||||||
|
s._uwsSocket.send = () => { throw new Error('well darn'); };
|
||||||
|
|
||||||
|
s.emit('test', { foo: 'bar' });
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
socket = connect();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('catches errors during inRoom().emit()', done => {
|
||||||
|
server.on('connection', s => {
|
||||||
|
s.join('testroom');
|
||||||
|
s._uwsSocket.send = () => { throw new Error('well darn'); };
|
||||||
|
|
||||||
|
inRoom('testroom').emit('test', { foo: 'bar' });
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
socket = connect();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('sets disconnected = true after a disconnect', done => {
|
||||||
|
server.on('connection', s => {
|
||||||
|
assert.strictEqual(s.disconnected, false);
|
||||||
|
|
||||||
|
s.on('disconnect', () => {
|
||||||
|
assert.strictEqual(s.disconnected, true);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
s.disconnect();
|
||||||
|
});
|
||||||
|
|
||||||
|
socket = connect();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue