diff --git a/package.json b/package.json index 4e28f4b1..b530a4e0 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "author": "Calvin Montgomery", "name": "CyTube", "description": "Online media synchronizer and chat", - "version": "3.17.0", + "version": "3.17.1", "repository": { "url": "http://github.com/calzoneman/sync" }, @@ -27,6 +27,7 @@ "http-errors": "^1.3.1", "jade": "^1.11.0", "json-typecheck": "^0.1.3", + "lodash": "^4.13.1", "morgan": "^1.6.1", "mysql": "^2.9.0", "nodemailer": "^1.4.0", diff --git a/src/channel/channel.js b/src/channel/channel.js index 2b8ca57a..f999f70a 100644 --- a/src/channel/channel.js +++ b/src/channel/channel.js @@ -11,6 +11,9 @@ import * as ChannelStore from '../channel-storage/channelstore'; import { ChannelStateSizeError } from '../errors'; import Promise from 'bluebird'; import { EventEmitter } from 'events'; +import { throttle } from '../util/throttle'; + +const USERCOUNT_THROTTLE = 10000; class ReferenceCounter { constructor(channel) { @@ -81,6 +84,9 @@ function Channel(name) { this.users = []; this.refCounter = new ReferenceCounter(this); this.flags = 0; + this.broadcastUsercount = throttle(() => { + this.broadcastAll("usercount", this.users.length); + }, USERCOUNT_THROTTLE); var self = this; db.channels.load(this, function (err) { if (err && err !== "Channel is not registered") { @@ -403,7 +409,7 @@ Channel.prototype.acceptUser = function (user) { }); this.sendUserlist([user]); - this.sendUsercount(this.users); + this.broadcastUsercount(); if (!this.is(Flags.C_REGISTERED)) { user.socket.emit("channelNotRegistered"); } @@ -434,7 +440,7 @@ Channel.prototype.partUser = function (user) { Object.keys(this.modules).forEach(function (m) { self.modules[m].onUserPart(user); }); - this.sendUsercount(this.users); + this.broadcastUsercount(); this.refCounter.unref("Channel::user"); user.die(); diff --git a/src/server.js b/src/server.js index 1567d9b3..0e64e961 100644 --- a/src/server.js +++ b/src/server.js @@ -258,6 +258,7 @@ Server.prototype.unloadChannel = function (chan) { } Logger.syslog.log("Unloaded channel " + chan.name); + chan.broadcastUsercount.cancel(); // Empty all outward references from the channel var keys = Object.keys(chan); for (var i in keys) { diff --git a/src/util/throttle.js b/src/util/throttle.js new file mode 100644 index 00000000..fa6f6f42 --- /dev/null +++ b/src/util/throttle.js @@ -0,0 +1,9 @@ +import lo from 'lodash'; + +export function throttle(fn, timeout) { + return lo.debounce(fn, timeout, { + leading: true, + trailing: true, + maxWait: timeout + }); +}