Server cleanup after a client disconnects
Solution 1:
One technique is to implement a "keepalive" method that each client regularly calls. This assumes you've got a user_id
held in each client's Session
.
// server code: heartbeat method
Meteor.methods({
keepalive: function (user_id) {
if (!Connections.findOne(user_id))
Connections.insert({user_id: user_id});
Connections.update(user_id, {$set: {last_seen: (new Date()).getTime()}});
}
});
// server code: clean up dead clients after 60 seconds
Meteor.setInterval(function () {
var now = (new Date()).getTime();
Connections.find({last_seen: {$lt: (now - 60 * 1000)}}).forEach(function (user) {
// do something here for each idle user
});
});
// client code: ping heartbeat every 5 seconds
Meteor.setInterval(function () {
Meteor.call('keepalive', Session.get('user_id'));
}, 5000);
Solution 2:
I think better way is to catch socket close event in publish function.
Meteor.publish("your_collection", function() {
this.session.socket.on("close", function() { /*do your thing*/});
}
UPDATE:
Newer version of meteor uses _session like this:
this._session.socket.on("close", function() { /*do your thing*/});
Solution 3:
I've implemented a Meteor smart package that tracks all connected sessions from different sessions and detects both session logout and disconnect events, without an expensive keepalive.
https://github.com/mizzao/meteor-user-status
To detect disconnect/logout events, you can just do the following:
UserStatus.on "connectionLogout", (info) ->
console.log(info.userId + " with session " + info.connectionId + " logged out")
You can also use it reactively. Check it out!
EDIT: v0.3.0
of user-status now tracks users being idle as well!
Solution 4:
if you're using Auth you have access to the user's ID in Method and Publish functions, you could implement your tracking there.. e.g. you could set a "last seen" when the user switches room:
Meteor.publish("messages", function(roomId) {
// assuming ActiveConnections is where you're tracking user connection activity
ActiveConnections.update({ userId: this.userId() }, {
$set:{ lastSeen: new Date().getTime() }
});
return Messages.find({ roomId: roomId});
});