-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Description
As pointed out to me by a user of this generator. When a socket.io connection is made and the socket is registered to the model's post('save')
hook, there is no method to remove these listeners. As a side effect as connections continue to be made (reloads or new) the hook's event listener list grows proportionally. For him this is causing an unwanted amount of events to be fired off, and due to his modifications, redundant effects (don't know the details, doesn't affect the issue).
I've searched the documentation on mongoose and I don't believe you can remove middleware
events, at least not easily?
With that "assumption" I've rewritten thing.socket.js
to roughly be:
module.exports = function(socketio) {
thing.schema.post('save', function (doc) {
socketio.to('thing').emit('thing:save', doc);
});
thing.schema.post('remove', function (doc) {
socketio.to('thing').emit('thing:remove', doc);
});
};
Notice that I only export one function, and it receives socketio
the socket.io server, not an individual socket
. This is because I only bind to the pre save hook once at server startup, like so:
server/config/socketio.js
module.exports = function (socketio) {
socketio.on('connection', function (socket) {
socket.address = socket.handshake.address !== null ?
socket.handshake.address.address + ':' + socket.handshake.address.port :
process.env.DOMAIN;
socket.connectedAt = new Date();
// Call onDisconnect.
socket.on('disconnect', function () {
onDisconnect(socket);
});
// Call onConnect.
onConnect(socket);
});
// Insert sockets below
require('../api/thing/thing.socket')(socketio);
};
I use socket.io rooms to handle the different clients/listeners. Since rooms are managed by the socket.io server I added listeners for join
and leave
events from the client sockets:
// When the user connects.. perform this
function onConnect(socket) {
...
socket.on('join', function(room) {
socket.join(room);
});
socket.on('leave', function(room) {
socket.leave(room);
});
}
The client can then sync updates as usual and only needs to call socket.emit('join', modelName)
when syncUpdates
and call socket.emit('leave', modelName)
when unsyncUpdates
(in addition to the normal actions). This should have the added benefit of not sending events to clients that they are not subscribed to; instead of the client simply ignoring the events. Also, the server does not have a continually growing list of event listeners on a model's schema; which would most likely appear as a mem leak over time.
2¢
EDIT: typo