Make polls more efficient

Instead of emitting frames to each individual socket, group them into
socket.io rooms of people who can see hidden poll results and people who
can't, then just do 2 broadcasts.
This commit is contained in:
calzoneman 2016-04-02 11:57:26 -07:00
parent 20538e328f
commit 0ee7f05213
6 changed files with 58 additions and 33 deletions

View file

@ -2,7 +2,7 @@
"author": "Calvin Montgomery", "author": "Calvin Montgomery",
"name": "CyTube", "name": "CyTube",
"description": "Online media synchronizer and chat", "description": "Online media synchronizer and chat",
"version": "3.14.6", "version": "3.15.0",
"repository": { "repository": {
"url": "http://github.com/calzoneman/sync" "url": "http://github.com/calzoneman/sync"
}, },

View file

@ -646,12 +646,12 @@ Channel.prototype.handleReadLog = function (user) {
}); });
}; };
Channel.prototype._broadcast = function (msg, data, ns) { Channel.prototype.broadcastToRoom = function (msg, data, ns) {
sio.instance.in(ns).emit(msg, data); sio.instance.in(ns).emit(msg, data);
}; };
Channel.prototype.broadcastAll = function (msg, data) { Channel.prototype.broadcastAll = function (msg, data) {
this._broadcast(msg, data, this.name); this.broadcastToRoom(msg, data, this.name);
}; };
Channel.prototype.packInfo = function (isAdmin) { Channel.prototype.packInfo = function (isAdmin) {

View file

@ -740,6 +740,7 @@ PlaylistModule.prototype.handleAssignLeader = function (user, data) {
this.leader = null; this.leader = null;
if (old.account.effectiveRank === 1.5) { if (old.account.effectiveRank === 1.5) {
old.account.effectiveRank = old.account.oldRank; old.account.effectiveRank = old.account.oldRank;
old.emit("effectiveRankChange", old.account.effectiveRank);
old.socket.emit("rank", old.account.effectiveRank); old.socket.emit("rank", old.account.effectiveRank);
} }
@ -766,6 +767,7 @@ PlaylistModule.prototype.handleAssignLeader = function (user, data) {
if (this.leader.account.effectiveRank < 1.5) { if (this.leader.account.effectiveRank < 1.5) {
this.leader.account.oldRank = this.leader.account.effectiveRank; this.leader.account.oldRank = this.leader.account.effectiveRank;
this.leader.account.effectiveRank = 1.5; this.leader.account.effectiveRank = 1.5;
this.leader.emit("effectiveRankChange", 1.5);
this.leader.socket.emit("rank", 1.5); this.leader.socket.emit("rank", 1.5);
} }

View file

@ -12,10 +12,15 @@ const TYPE_VOTE = {
option: "number" option: "number"
}; };
const ROOM_VIEW_HIDDEN = ":viewHidden";
const ROOM_NO_VIEW_HIDDEN = ":noViewHidden";
function PollModule(channel) { function PollModule(channel) {
ChannelModule.apply(this, arguments); ChannelModule.apply(this, arguments);
this.poll = null; this.poll = null;
this.roomViewHidden = this.channel.uniqueName + ROOM_VIEW_HIDDEN;
this.roomNoViewHidden = this.channel.uniqueName + ROOM_NO_VIEW_HIDDEN;
if (this.channel.modules.chat) { if (this.channel.modules.chat) {
this.channel.modules.chat.registerCommand("poll", this.handlePollCmd.bind(this, false)); this.channel.modules.chat.registerCommand("poll", this.handlePollCmd.bind(this, false));
this.channel.modules.chat.registerCommand("hpoll", this.handlePollCmd.bind(this, true)); this.channel.modules.chat.registerCommand("hpoll", this.handlePollCmd.bind(this, true));
@ -59,20 +64,53 @@ PollModule.prototype.save = function (data) {
}; };
PollModule.prototype.onUserPostJoin = function (user) { PollModule.prototype.onUserPostJoin = function (user) {
this.sendPoll([user]); this.sendPoll(user);
user.socket.typecheckedOn("newPoll", TYPE_NEW_POLL, this.handleNewPoll.bind(this, user)); user.socket.typecheckedOn("newPoll", TYPE_NEW_POLL, this.handleNewPoll.bind(this, user));
user.socket.typecheckedOn("vote", TYPE_VOTE, this.handleVote.bind(this, user)); user.socket.typecheckedOn("vote", TYPE_VOTE, this.handleVote.bind(this, user));
user.socket.on("closePoll", this.handleClosePoll.bind(this, user)); user.socket.on("closePoll", this.handleClosePoll.bind(this, user));
this.addUserToPollRoom(user);
const self = this;
user.on("effectiveRankChange", () => {
self.addUserToPollRoom(user);
});
};
PollModule.prototype.addUserToPollRoom = function (user) {
const perms = this.channel.modules.permissions;
if (perms.canViewHiddenPoll(user)) {
user.socket.leave(this.roomNoViewHidden);
user.socket.join(this.roomViewHidden);
} else {
user.socket.leave(this.roomViewHidden);
user.socket.join(this.roomNoViewHidden);
}
}; };
PollModule.prototype.onUserPart = function(user) { PollModule.prototype.onUserPart = function(user) {
if (this.poll) { if (this.poll) {
this.poll.unvote(user.realip); this.poll.unvote(user.realip);
this.sendPollUpdate(this.channel.users); this.broadcastPoll(false);
} }
}; };
PollModule.prototype.sendPoll = function (users) { PollModule.prototype.sendPoll = function (user) {
if (!this.poll) {
return;
}
var perms = this.channel.modules.permissions;
user.socket.emit("closePoll");
if (perms.canViewHiddenPoll(user)) {
var unobscured = this.poll.packUpdate(true);
user.socket.emit("newPoll", unobscured);
} else {
var obscured = this.poll.packUpdate(false);
user.socket.emit("newPoll", obscured);
}
};
PollModule.prototype.broadcastPoll = function (isNewPoll) {
if (!this.poll) { if (!this.poll) {
return; return;
} }
@ -81,32 +119,13 @@ PollModule.prototype.sendPoll = function (users) {
var unobscured = this.poll.packUpdate(true); var unobscured = this.poll.packUpdate(true);
var perms = this.channel.modules.permissions; var perms = this.channel.modules.permissions;
users.forEach(function (u) { const event = isNewPoll ? "newPoll" : "updatePoll";
u.socket.emit("closePoll"); if (isNewPoll) {
if (perms.canViewHiddenPoll(u)) { this.channel.broadcastAll("closePoll");
u.socket.emit("newPoll", unobscured);
} else {
u.socket.emit("newPoll", obscured);
}
});
};
PollModule.prototype.sendPollUpdate = function (users) {
if (!this.poll) {
return;
} }
var obscured = this.poll.packUpdate(false); this.channel.broadcastToRoom(event, unobscured, this.roomViewHidden);
var unobscured = this.poll.packUpdate(true); this.channel.broadcastToRoom(event, obscured, this.roomNoViewHidden);
var perms = this.channel.modules.permissions;
users.forEach(function (u) {
if (perms.canViewHiddenPoll(u)) {
u.socket.emit("updatePoll", unobscured);
} else {
u.socket.emit("updatePoll", obscured);
}
});
}; };
PollModule.prototype.handleNewPoll = function (user, data) { PollModule.prototype.handleNewPoll = function (user, data) {
@ -132,7 +151,7 @@ PollModule.prototype.handleNewPoll = function (user, data) {
} }
this.poll = poll; this.poll = poll;
this.sendPoll(this.channel.users); this.broadcastPoll(true);
this.channel.logger.log("[poll] " + user.getName() + " opened poll: '" + poll.title + "'"); this.channel.logger.log("[poll] " + user.getName() + " opened poll: '" + poll.title + "'");
}; };
@ -143,7 +162,7 @@ PollModule.prototype.handleVote = function (user, data) {
if (this.poll) { if (this.poll) {
this.poll.vote(user.realip, data.option); this.poll.vote(user.realip, data.option);
this.sendPollUpdate(this.channel.users); this.broadcastPoll(false);
} }
}; };
@ -179,7 +198,7 @@ PollModule.prototype.handlePollCmd = function (obscured, user, msg, meta) {
var title = args.shift(); var title = args.shift();
var poll = new Poll(user.getName(), title, args, obscured); var poll = new Poll(user.getName(), title, args, obscured);
this.poll = poll; this.poll = poll;
this.sendPoll(this.channel.users); this.broadcastPoll(true);
this.channel.logger.log("[poll] " + user.getName() + " opened poll: '" + poll.title + "'"); this.channel.logger.log("[poll] " + user.getName() + " opened poll: '" + poll.title + "'");
}; };

View file

@ -121,6 +121,7 @@ RankModule.prototype.handleRankChange = function (user, data) {
receiver.account.channelRank = rank; receiver.account.channelRank = rank;
receiver.account.effectiveRank = Math.max(receiver.account.globalRank, rank); receiver.account.effectiveRank = Math.max(receiver.account.globalRank, rank);
receiver.emit("effectiveRankChange", receiver.account.effectiveRank);
receiver.socket.emit("rank", receiver.account.effectiveRank); receiver.socket.emit("rank", receiver.account.effectiveRank);
this.channel.logger.log("[mod] " + user.getName() + " set " + name + "'s rank " + this.channel.logger.log("[mod] " + user.getName() + " set " + name + "'s rank " +
"to " + rank); "to " + rank);

View file

@ -429,6 +429,9 @@ User.prototype.refreshAccount = function (opts, cb) {
} }
} }
self.account = account; self.account = account;
if (account.effectiveRank !== old.effectiveRank) {
self.emit("effectiveRankChange", self.account.effectiveRank);
}
} }
cb(err, account); cb(err, account);
}); });