Данные о сокетах, хранить нужно только в ОЗУ node.js сервера. Бд об этом знать не нужно вообще.
Вот я написал пример кода, как хранить в ОЗУ список пользователей, их списки соединений и кэш друзей и т.п.
Твоя задача следить за кешем, чтобы он был всегда обновлен. Когда делаешь обновления через API добавляя/убирая там друзей, важно держать кеш обновленным тоже.
По сути users кеш - это все пользователи онлайн.
т.к. они хранятся по ключу, то проверка на онлайн и доступ к ним очень быстрый.
Вот код, думаю идея понятна.
// users cache object
var users = { };
// users load requests queue
var userRequests = { };
// user class
function User(data) {
this.id = data.id;
this.name = data.name;
this.friends = data.friend_ids;
this.sockets = { };
this.connections = 0;
}
// send message to all user connections
User.prototype.send = function(name, data) {
for(var key in this.sockets)
this.sockets[key].emit(name, data);
};
// add user connection
User.prototype.socketAdd = function(socket) {
if (this.sockets[socket.id])
return false;
this.sockets[socket.id] = socket;
this.connections++;
return true;
};
// remove user connection
User.prototype.socketRemove = function(socket) {
if (! this.sockets[socket.id])
return false;
delete this.sockets[socket.id];
this.connections--;
return true;
};
// try get or load user
var userGetOrLoad = function(id, fn) {
if (users[id])
return fn(null, users[id]);
// loading in progress, just queue then
if (userRequests[id])
return userRequests[id].push(fn);
// first one to try loading
userRequests[id] = [ fn ];
// once loaded, report to all who need this info
var finish = function(err, user) {
for(var i = 0; i < userRequests[id].length; i++)
userRequests[id](err, user);
delete userRequests[id];
};
// try load user from db
db.collection('users').findOne({
_id: id
}, {
fields: {
name: 1,
friend_ids: 1
}
}, function(err, item) {
var user = null;
// if user loaded, create cache
if (! err && item)
user = users[id] = new User(item);
finish(err, user);
});
};
// add client to user
var addClient = function(userId, socket) {
userGetOrLoad(userId, function(err, user) {
if (err || ! user)
return;
var added = user.socketAdd(socket);
if (added) {
// notify all friends about user being online
for(var i = 0; i < user.friends.length; i++) {
var friend = users[user.friends[i]];
if (! friend) continue;
friend.send('friend:online', { id: user.id });
}
}
});
};
// remove client from user
var removeClient = function(userId, socket) {
var user = users[userId];
if (! user)
return;
user.socketRemove(socket);
if (user.connections === 0) {
delete users[userId];
// notify all friends that user is offline now
for(var i = 0; i < user.friends.length; i++) {
var friend = users[user.friends[i]];
if (! friend) continue;
friend.send('friend:offline', { id: user.id });
}
}
};