mirror of https://github.com/calzoneman/sync.git
Remove channel reference counter
This was an old attempt at gracefully unloading channels that still had pending callbacks. Its implementation was always flawed, and the number of places where it was used is small enough to replace with straightforward checks for whether the channel has been unloaded after an asynchronous operation. Hopefully fixes the stuck 0 user channels issue.
This commit is contained in:
parent
66fadab492
commit
d678fa56d1
|
@ -16,10 +16,6 @@ describe('KickbanModule', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
mockChannel = {
|
mockChannel = {
|
||||||
name: channelName,
|
name: channelName,
|
||||||
refCounter: {
|
|
||||||
ref() { },
|
|
||||||
unref() { }
|
|
||||||
},
|
|
||||||
logger: {
|
logger: {
|
||||||
log() { }
|
log() { }
|
||||||
},
|
},
|
||||||
|
@ -69,11 +65,22 @@ describe('KickbanModule', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function patch(fn, after) {
|
||||||
|
let existing = kickban[fn];
|
||||||
|
kickban[fn] = async function () {
|
||||||
|
try {
|
||||||
|
await existing.apply(this, arguments)
|
||||||
|
} finally {
|
||||||
|
after();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
describe('#handleCmdBan', () => {
|
describe('#handleCmdBan', () => {
|
||||||
it('inserts a valid ban', done => {
|
it('inserts a valid ban', done => {
|
||||||
let kicked = false;
|
let kicked = false;
|
||||||
|
|
||||||
mockChannel.refCounter.unref = () => {
|
patch('banName', () => {
|
||||||
assert(kicked, 'Expected user to be kicked');
|
assert(kicked, 'Expected user to be kicked');
|
||||||
|
|
||||||
database.getDB().runTransaction(async tx => {
|
database.getDB().runTransaction(async tx => {
|
||||||
|
@ -90,7 +97,7 @@ describe('KickbanModule', () => {
|
||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
};
|
});
|
||||||
|
|
||||||
mockChannel.users = [{
|
mockChannel.users = [{
|
||||||
getLowerName() {
|
getLowerName() {
|
||||||
|
@ -247,7 +254,7 @@ describe('KickbanModule', () => {
|
||||||
let firstUserKicked = false;
|
let firstUserKicked = false;
|
||||||
let secondUserKicked = false;
|
let secondUserKicked = false;
|
||||||
|
|
||||||
mockChannel.refCounter.unref = () => {
|
patch('banAll', () => {
|
||||||
assert(firstUserKicked, 'Expected banned user to be kicked');
|
assert(firstUserKicked, 'Expected banned user to be kicked');
|
||||||
assert(
|
assert(
|
||||||
secondUserKicked,
|
secondUserKicked,
|
||||||
|
@ -279,7 +286,7 @@ describe('KickbanModule', () => {
|
||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
};
|
});
|
||||||
|
|
||||||
mockChannel.users = [{
|
mockChannel.users = [{
|
||||||
getLowerName() {
|
getLowerName() {
|
||||||
|
@ -313,7 +320,7 @@ describe('KickbanModule', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('inserts a valid range ban', done => {
|
it('inserts a valid range ban', done => {
|
||||||
mockChannel.refCounter.unref = () => {
|
patch('banIP', () => {
|
||||||
database.getDB().runTransaction(async tx => {
|
database.getDB().runTransaction(async tx => {
|
||||||
const ipBan = await tx.table('channel_bans')
|
const ipBan = await tx.table('channel_bans')
|
||||||
.where({
|
.where({
|
||||||
|
@ -328,7 +335,7 @@ describe('KickbanModule', () => {
|
||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
};
|
});
|
||||||
|
|
||||||
kickban.handleCmdIPBan(
|
kickban.handleCmdIPBan(
|
||||||
mockUser,
|
mockUser,
|
||||||
|
@ -338,7 +345,7 @@ describe('KickbanModule', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('inserts a valid wide-range ban', done => {
|
it('inserts a valid wide-range ban', done => {
|
||||||
mockChannel.refCounter.unref = () => {
|
patch('banIP', () => {
|
||||||
database.getDB().runTransaction(async tx => {
|
database.getDB().runTransaction(async tx => {
|
||||||
const ipBan = await tx.table('channel_bans')
|
const ipBan = await tx.table('channel_bans')
|
||||||
.where({
|
.where({
|
||||||
|
@ -353,7 +360,7 @@ describe('KickbanModule', () => {
|
||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
};
|
});
|
||||||
|
|
||||||
kickban.handleCmdIPBan(
|
kickban.handleCmdIPBan(
|
||||||
mockUser,
|
mockUser,
|
||||||
|
@ -365,7 +372,7 @@ describe('KickbanModule', () => {
|
||||||
it('inserts a valid IPv6 ban', done => {
|
it('inserts a valid IPv6 ban', done => {
|
||||||
const longIP = require('../../lib/utilities').expandIPv6('::abcd');
|
const longIP = require('../../lib/utilities').expandIPv6('::abcd');
|
||||||
|
|
||||||
mockChannel.refCounter.unref = () => {
|
patch('banAll', () => {
|
||||||
database.getDB().runTransaction(async tx => {
|
database.getDB().runTransaction(async tx => {
|
||||||
const ipBan = await tx.table('channel_bans')
|
const ipBan = await tx.table('channel_bans')
|
||||||
.where({
|
.where({
|
||||||
|
@ -380,7 +387,7 @@ describe('KickbanModule', () => {
|
||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
};
|
});
|
||||||
|
|
||||||
database.getDB().runTransaction(async tx => {
|
database.getDB().runTransaction(async tx => {
|
||||||
await tx.table('aliases')
|
await tx.table('aliases')
|
||||||
|
@ -546,7 +553,7 @@ describe('KickbanModule', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('still adds the IP ban even if the name is already banned', done => {
|
it('still adds the IP ban even if the name is already banned', done => {
|
||||||
mockChannel.refCounter.unref = () => {
|
patch('banIP', () => {
|
||||||
database.getDB().runTransaction(async tx => {
|
database.getDB().runTransaction(async tx => {
|
||||||
const ipBan = await tx.table('channel_bans')
|
const ipBan = await tx.table('channel_bans')
|
||||||
.where({
|
.where({
|
||||||
|
@ -561,7 +568,7 @@ describe('KickbanModule', () => {
|
||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
};
|
});
|
||||||
|
|
||||||
database.getDB().runTransaction(tx => {
|
database.getDB().runTransaction(tx => {
|
||||||
return tx.table('channel_bans')
|
return tx.table('channel_bans')
|
||||||
|
|
|
@ -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.73.0",
|
"version": "3.74.0",
|
||||||
"repository": {
|
"repository": {
|
||||||
"url": "http://github.com/calzoneman/sync"
|
"url": "http://github.com/calzoneman/sync"
|
||||||
},
|
},
|
||||||
|
|
|
@ -14,67 +14,6 @@ const LOGGER = require('@calzoneman/jsli')('channel');
|
||||||
|
|
||||||
const USERCOUNT_THROTTLE = 10000;
|
const USERCOUNT_THROTTLE = 10000;
|
||||||
|
|
||||||
class ReferenceCounter {
|
|
||||||
constructor(channel) {
|
|
||||||
this.channel = channel;
|
|
||||||
this.channelName = channel.name;
|
|
||||||
this.refCount = 0;
|
|
||||||
this.references = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
ref(caller) {
|
|
||||||
if (caller) {
|
|
||||||
if (this.references.hasOwnProperty(caller)) {
|
|
||||||
this.references[caller]++;
|
|
||||||
} else {
|
|
||||||
this.references[caller] = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.refCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
unref(caller) {
|
|
||||||
if (caller) {
|
|
||||||
if (this.references.hasOwnProperty(caller)) {
|
|
||||||
this.references[caller]--;
|
|
||||||
if (this.references[caller] === 0) {
|
|
||||||
delete this.references[caller];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
LOGGER.error("ReferenceCounter::unref() called by caller [" +
|
|
||||||
caller + "] but this caller had no active references! " +
|
|
||||||
`(channel: ${this.channelName})`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.refCount--;
|
|
||||||
this.checkRefCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
checkRefCount() {
|
|
||||||
if (this.refCount === 0) {
|
|
||||||
if (Object.keys(this.references).length > 0) {
|
|
||||||
LOGGER.error("ReferenceCounter::refCount reached 0 but still had " +
|
|
||||||
"active references: " +
|
|
||||||
JSON.stringify(Object.keys(this.references)) +
|
|
||||||
` (channel: ${this.channelName})`);
|
|
||||||
for (var caller in this.references) {
|
|
||||||
this.refCount += this.references[caller];
|
|
||||||
}
|
|
||||||
} else if (this.channel.users && this.channel.users.length > 0) {
|
|
||||||
LOGGER.error("ReferenceCounter::refCount reached 0 but still had " +
|
|
||||||
this.channel.users.length + " active users" +
|
|
||||||
` (channel: ${this.channelName})`);
|
|
||||||
this.refCount = this.channel.users.length;
|
|
||||||
} else {
|
|
||||||
this.channel.emit("empty");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function Channel(name) {
|
function Channel(name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.uniqueName = name.toLowerCase();
|
this.uniqueName = name.toLowerCase();
|
||||||
|
@ -85,7 +24,6 @@ function Channel(name) {
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
this.users = [];
|
this.users = [];
|
||||||
this.refCounter = new ReferenceCounter(this);
|
|
||||||
this.flags = 0;
|
this.flags = 0;
|
||||||
this.id = 0;
|
this.id = 0;
|
||||||
this.ownerName = null;
|
this.ownerName = null;
|
||||||
|
@ -282,17 +220,16 @@ Channel.prototype.saveState = async function () {
|
||||||
|
|
||||||
Channel.prototype.checkModules = function (fn, args, cb) {
|
Channel.prototype.checkModules = function (fn, args, cb) {
|
||||||
const self = this;
|
const self = this;
|
||||||
const refCaller = `Channel::checkModules/${fn}`;
|
|
||||||
this.waitFlag(Flags.C_READY, function () {
|
this.waitFlag(Flags.C_READY, function () {
|
||||||
if (self.dead) return;
|
if (self.dead) return;
|
||||||
|
|
||||||
self.refCounter.ref(refCaller);
|
|
||||||
var keys = Object.keys(self.modules);
|
var keys = Object.keys(self.modules);
|
||||||
var next = function (err, result) {
|
var next = function (err, result) {
|
||||||
|
if (self.dead) return;
|
||||||
|
|
||||||
if (result !== ChannelModule.PASSTHROUGH) {
|
if (result !== ChannelModule.PASSTHROUGH) {
|
||||||
/* Either an error occured, or the module denied the user access */
|
/* Either an error occured, or the module denied the user access */
|
||||||
cb(err, result);
|
cb(err, result);
|
||||||
self.refCounter.unref(refCaller);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,7 +237,6 @@ Channel.prototype.checkModules = function (fn, args, cb) {
|
||||||
if (m === undefined) {
|
if (m === undefined) {
|
||||||
/* No more modules to check */
|
/* No more modules to check */
|
||||||
cb(null, ChannelModule.PASSTHROUGH);
|
cb(null, ChannelModule.PASSTHROUGH);
|
||||||
self.refCounter.unref(refCaller);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -339,28 +275,32 @@ Channel.prototype.notifyModules = function (fn, args) {
|
||||||
Channel.prototype.joinUser = function (user, data) {
|
Channel.prototype.joinUser = function (user, data) {
|
||||||
const self = this;
|
const self = this;
|
||||||
|
|
||||||
self.refCounter.ref("Channel::user");
|
|
||||||
self.waitFlag(Flags.C_READY, function () {
|
self.waitFlag(Flags.C_READY, function () {
|
||||||
|
|
||||||
/* User closed the connection before the channel finished loading */
|
/* User closed the connection before the channel finished loading */
|
||||||
if (user.socket.disconnected) {
|
if (user.socket.disconnected) {
|
||||||
self.refCounter.unref("Channel::user");
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self.dead) {
|
||||||
|
user.kick('Channel is not loaded');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
user.channel = self;
|
user.channel = self;
|
||||||
user.waitFlag(Flags.U_LOGGED_IN, () => {
|
user.waitFlag(Flags.U_LOGGED_IN, () => {
|
||||||
if (self.dead) {
|
if (self.dead) {
|
||||||
LOGGER.warn(
|
user.kick('Channel is not loaded');
|
||||||
'Got U_LOGGED_IN for %s after channel already unloaded',
|
|
||||||
user.getName()
|
|
||||||
);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user.is(Flags.U_REGISTERED)) {
|
if (user.is(Flags.U_REGISTERED)) {
|
||||||
db.channels.getRank(self.name, user.getName(), (error, rank) => {
|
db.channels.getRank(self.name, user.getName(), (error, rank) => {
|
||||||
if (!error) {
|
if (!error) {
|
||||||
|
if (self.dead) {
|
||||||
|
user.kick('Channel is not loaded');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
user.setChannelRank(rank);
|
user.setChannelRank(rank);
|
||||||
user.setFlag(Flags.U_HAS_CHANNEL_RANK);
|
user.setFlag(Flags.U_HAS_CHANNEL_RANK);
|
||||||
if (user.inChannel()) {
|
if (user.inChannel()) {
|
||||||
|
@ -374,13 +314,6 @@ Channel.prototype.joinUser = function (user, data) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (user.socket.disconnected) {
|
|
||||||
self.refCounter.unref("Channel::user");
|
|
||||||
return;
|
|
||||||
} else if (self.dead) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.checkModules("onUserPreJoin", [user, data], function (err, result) {
|
self.checkModules("onUserPreJoin", [user, data], function (err, result) {
|
||||||
if (result === ChannelModule.PASSTHROUGH) {
|
if (result === ChannelModule.PASSTHROUGH) {
|
||||||
user.channel = self;
|
user.channel = self;
|
||||||
|
@ -389,7 +322,6 @@ Channel.prototype.joinUser = function (user, data) {
|
||||||
user.channel = null;
|
user.channel = null;
|
||||||
user.account.channelRank = 0;
|
user.account.channelRank = 0;
|
||||||
user.account.effectiveRank = user.account.globalRank;
|
user.account.effectiveRank = user.account.globalRank;
|
||||||
self.refCounter.unref("Channel::user");
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -493,8 +425,8 @@ Channel.prototype.partUser = function (user) {
|
||||||
});
|
});
|
||||||
this.broadcastUsercount();
|
this.broadcastUsercount();
|
||||||
|
|
||||||
this.refCounter.unref("Channel::user");
|
|
||||||
user.die();
|
user.die();
|
||||||
|
if (this.users.length === 0) this.emit('empty');
|
||||||
};
|
};
|
||||||
|
|
||||||
Channel.prototype.maybeResendUserlist = function maybeResendUserlist(user, newRank, oldRank) {
|
Channel.prototype.maybeResendUserlist = function maybeResendUserlist(user, newRank, oldRank) {
|
||||||
|
@ -655,13 +587,14 @@ Channel.prototype.sendUserJoin = function (users, user) {
|
||||||
Channel.prototype.readLog = function (cb) {
|
Channel.prototype.readLog = function (cb) {
|
||||||
const maxLen = 102400;
|
const maxLen = 102400;
|
||||||
const file = this.logger.filename;
|
const file = this.logger.filename;
|
||||||
this.refCounter.ref("Channel::readLog");
|
|
||||||
const self = this;
|
const self = this;
|
||||||
fs.stat(file, function (err, data) {
|
fs.stat(file, function (err, data) {
|
||||||
if (err) {
|
if (err) {
|
||||||
self.refCounter.unref("Channel::readLog");
|
|
||||||
return cb(err, null);
|
return cb(err, null);
|
||||||
}
|
}
|
||||||
|
if (self.dead) {
|
||||||
|
return cb(new Error('Channel unloaded'), null);
|
||||||
|
}
|
||||||
|
|
||||||
const start = Math.max(data.size - maxLen, 0);
|
const start = Math.max(data.size - maxLen, 0);
|
||||||
const end = data.size - 1;
|
const end = data.size - 1;
|
||||||
|
@ -677,7 +610,6 @@ Channel.prototype.readLog = function (cb) {
|
||||||
});
|
});
|
||||||
read.on("end", function () {
|
read.on("end", function () {
|
||||||
cb(null, buffer);
|
cb(null, buffer);
|
||||||
self.refCounter.unref("Channel::readLog");
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -744,10 +676,6 @@ Channel.prototype.packInfo = function (isAdmin) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isAdmin) {
|
|
||||||
data.activeLockCount = this.refCounter.refCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
var keys = Object.keys(this.modules);
|
var keys = Object.keys(this.modules);
|
||||||
keys.forEach(function (k) {
|
keys.forEach(function (k) {
|
||||||
|
|
|
@ -77,10 +77,11 @@ KickBanModule.prototype.onUserPostJoin = function (user) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const chan = this.channel;
|
const chan = this.channel;
|
||||||
const refCaller = "KickBanModule::onUserPostJoin";
|
|
||||||
user.waitFlag(Flags.U_LOGGED_IN, function () {
|
user.waitFlag(Flags.U_LOGGED_IN, function () {
|
||||||
chan.refCounter.ref(refCaller);
|
|
||||||
db.channels.isNameBanned(chan.name, user.getName(), function (err, banned) {
|
db.channels.isNameBanned(chan.name, user.getName(), function (err, banned) {
|
||||||
|
if (chan.dead) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!err && banned) {
|
if (!err && banned) {
|
||||||
user.kick("You are banned from this channel.");
|
user.kick("You are banned from this channel.");
|
||||||
if (chan.modules.chat) {
|
if (chan.modules.chat) {
|
||||||
|
@ -88,7 +89,6 @@ KickBanModule.prototype.onUserPostJoin = function (user) {
|
||||||
"name is banned)");
|
"name is banned)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
chan.refCounter.unref(refCaller);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -226,14 +226,9 @@ KickBanModule.prototype.handleCmdBan = function (user, msg, _meta) {
|
||||||
var name = args.shift().toLowerCase();
|
var name = args.shift().toLowerCase();
|
||||||
var reason = args.join(" ");
|
var reason = args.join(" ");
|
||||||
|
|
||||||
const chan = this.channel;
|
|
||||||
chan.refCounter.ref("KickBanModule::handleCmdBan");
|
|
||||||
|
|
||||||
this.banName(user, name, reason).catch(error => {
|
this.banName(user, name, reason).catch(error => {
|
||||||
const message = error.message || error;
|
const message = error.message || error;
|
||||||
user.socket.emit("errorMsg", { msg: message });
|
user.socket.emit("errorMsg", { msg: message });
|
||||||
}).then(() => {
|
|
||||||
chan.refCounter.unref("KickBanModule::handleCmdBan");
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -257,15 +252,9 @@ KickBanModule.prototype.handleCmdIPBan = function (user, msg, _meta) {
|
||||||
}
|
}
|
||||||
var reason = args.join(" ");
|
var reason = args.join(" ");
|
||||||
|
|
||||||
const chan = this.channel;
|
|
||||||
chan.refCounter.ref("KickBanModule::handleCmdIPBan");
|
|
||||||
|
|
||||||
this.banAll(user, name, range, reason).catch(error => {
|
this.banAll(user, name, range, reason).catch(error => {
|
||||||
//console.log('!!!', error.stack);
|
|
||||||
const message = error.message || error;
|
const message = error.message || error;
|
||||||
user.socket.emit("errorMsg", { msg: message });
|
user.socket.emit("errorMsg", { msg: message });
|
||||||
}).then(() => {
|
|
||||||
chan.refCounter.unref("KickBanModule::handleCmdIPBan");
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -427,14 +416,15 @@ KickBanModule.prototype.handleUnban = function (user, data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
this.channel.refCounter.ref("KickBanModule::handleUnban");
|
|
||||||
db.channels.unbanId(this.channel.name, data.id, function (err) {
|
db.channels.unbanId(this.channel.name, data.id, function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
self.channel.refCounter.unref("KickBanModule::handleUnban");
|
|
||||||
return user.socket.emit("errorMsg", {
|
return user.socket.emit("errorMsg", {
|
||||||
msg: err
|
msg: err
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (self.channel.dead) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
self.sendUnban(self.channel.users, data);
|
self.sendUnban(self.channel.users, data);
|
||||||
self.channel.logger.log("[mod] " + user.getName() + " unbanned " + data.name);
|
self.channel.logger.log("[mod] " + user.getName() + " unbanned " + data.name);
|
||||||
|
@ -445,7 +435,6 @@ KickBanModule.prototype.handleUnban = function (user, data) {
|
||||||
banperm
|
banperm
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
self.channel.refCounter.unref("KickBanModule::handleUnban");
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -55,18 +55,15 @@ LibraryModule.prototype.handleUncache = function (user, data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const chan = this.channel;
|
const chan = this.channel;
|
||||||
chan.refCounter.ref("LibraryModule::handleUncache");
|
|
||||||
db.channels.deleteFromLibrary(chan.name, data.id, function (err, _res) {
|
db.channels.deleteFromLibrary(chan.name, data.id, function (err, _res) {
|
||||||
if (chan.dead) {
|
if (chan.dead) {
|
||||||
return;
|
return;
|
||||||
} else if (err) {
|
} else if (err) {
|
||||||
chan.refCounter.unref("LibraryModule::handleUncache");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
chan.logger.log("[library] " + user.getName() + " deleted " + data.id +
|
chan.logger.log("[library] " + user.getName() + " deleted " + data.id +
|
||||||
"from the library");
|
"from the library");
|
||||||
chan.refCounter.unref("LibraryModule::handleUncache");
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -47,9 +47,8 @@ MediaRefresherModule.prototype.initVimeo = function (data, cb) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const self = this;
|
const self = this;
|
||||||
self.channel.refCounter.ref("MediaRefresherModule::initVimeo");
|
|
||||||
Vimeo.extract(data.id).then(function (direct) {
|
Vimeo.extract(data.id).then(function (direct) {
|
||||||
if (self.dead || self.channel.dead) {
|
if (self.channel.dead) {
|
||||||
self.unload();
|
self.unload();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -63,9 +62,11 @@ MediaRefresherModule.prototype.initVimeo = function (data, cb) {
|
||||||
if (cb) cb();
|
if (cb) cb();
|
||||||
}).catch(function (err) {
|
}).catch(function (err) {
|
||||||
LOGGER.error("Unexpected vimeo::extract() fail: " + err.stack);
|
LOGGER.error("Unexpected vimeo::extract() fail: " + err.stack);
|
||||||
|
if (self.channel.dead) {
|
||||||
|
self.unload();
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (cb) cb();
|
if (cb) cb();
|
||||||
}).finally(() => {
|
|
||||||
self.channel.refCounter.unref("MediaRefresherModule::initVimeo");
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -511,19 +511,19 @@ PlaylistModule.prototype.queueStandard = function (user, data) {
|
||||||
};
|
};
|
||||||
|
|
||||||
const self = this;
|
const self = this;
|
||||||
this.channel.refCounter.ref("PlaylistModule::queueStandard");
|
|
||||||
counters.add("playlist:queue:count", 1);
|
counters.add("playlist:queue:count", 1);
|
||||||
this.semaphore.queue(function (lock) {
|
this.semaphore.queue(function (lock) {
|
||||||
InfoGetter.getMedia(data.id, data.type, function (err, media) {
|
InfoGetter.getMedia(data.id, data.type, function (err, media) {
|
||||||
if (err) {
|
if (err) {
|
||||||
error(XSS.sanitizeText(String(err)));
|
error(XSS.sanitizeText(String(err)));
|
||||||
self.channel.refCounter.unref("PlaylistModule::queueStandard");
|
return lock.release();
|
||||||
|
}
|
||||||
|
if (self.channel.dead) {
|
||||||
return lock.release();
|
return lock.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
self._addItem(media, data, user, function () {
|
self._addItem(media, data, user, function () {
|
||||||
lock.release();
|
lock.release();
|
||||||
self.channel.refCounter.unref("PlaylistModule::queueStandard");
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -546,7 +546,7 @@ PlaylistModule.prototype.queueYouTubePlaylist = function (user, data) {
|
||||||
return lock.release();
|
return lock.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self.dead) {
|
if (self.channel.dead) {
|
||||||
return lock.release();
|
return lock.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -562,8 +562,6 @@ PlaylistModule.prototype.queueYouTubePlaylist = function (user, data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.channel.refCounter.ref("PlaylistModule::queueYouTubePlaylist");
|
|
||||||
|
|
||||||
if (self.channel.modules.library && data.shouldAddToLibrary) {
|
if (self.channel.modules.library && data.shouldAddToLibrary) {
|
||||||
self.channel.modules.library.cacheMediaList(vids);
|
self.channel.modules.library.cacheMediaList(vids);
|
||||||
data.shouldAddToLibrary = false;
|
data.shouldAddToLibrary = false;
|
||||||
|
@ -574,8 +572,6 @@ PlaylistModule.prototype.queueYouTubePlaylist = function (user, data) {
|
||||||
self._addItem(media, data, user);
|
self._addItem(media, data, user);
|
||||||
});
|
});
|
||||||
|
|
||||||
self.channel.refCounter.unref("PlaylistModule::queueYouTubePlaylist");
|
|
||||||
|
|
||||||
lock.release();
|
lock.release();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -593,7 +589,6 @@ PlaylistModule.prototype.handleDelete = function (user, data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var plitem = this.items.find(data);
|
var plitem = this.items.find(data);
|
||||||
self.channel.refCounter.ref("PlaylistModule::handleDelete");
|
|
||||||
this.semaphore.queue(function (lock) {
|
this.semaphore.queue(function (lock) {
|
||||||
if (self._delete(data)) {
|
if (self._delete(data)) {
|
||||||
self.channel.logger.log("[playlist] " + user.getName() + " deleted " +
|
self.channel.logger.log("[playlist] " + user.getName() + " deleted " +
|
||||||
|
@ -601,7 +596,6 @@ PlaylistModule.prototype.handleDelete = function (user, data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
lock.release();
|
lock.release();
|
||||||
self.channel.refCounter.unref("PlaylistModule::handleDelete");
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -637,26 +631,24 @@ PlaylistModule.prototype.handleMoveMedia = function (user, data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const self = this;
|
const self = this;
|
||||||
self.channel.refCounter.ref("PlaylistModule::handleMoveMedia");
|
|
||||||
self.semaphore.queue(function (lock) {
|
self.semaphore.queue(function (lock) {
|
||||||
|
if (self.channel.dead) {
|
||||||
|
return lock.release();
|
||||||
|
}
|
||||||
if (!self.items.remove(data.from)) {
|
if (!self.items.remove(data.from)) {
|
||||||
self.channel.refCounter.unref("PlaylistModule::handleMoveMedia");
|
|
||||||
return lock.release();
|
return lock.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.after === "prepend") {
|
if (data.after === "prepend") {
|
||||||
if (!self.items.prepend(from)) {
|
if (!self.items.prepend(from)) {
|
||||||
self.channel.refCounter.unref("PlaylistModule::handleMoveMedia");
|
|
||||||
return lock.release();
|
return lock.release();
|
||||||
}
|
}
|
||||||
} else if (data.after === "append") {
|
} else if (data.after === "append") {
|
||||||
if (!self.items.append(from)) {
|
if (!self.items.append(from)) {
|
||||||
self.channel.refCounter.unref("PlaylistModule::handleMoveMedia");
|
|
||||||
return lock.release();
|
return lock.release();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!self.items.insertAfter(from, data.after)) {
|
if (!self.items.insertAfter(from, data.after)) {
|
||||||
self.channel.refCounter.unref("PlaylistModule::handleMoveMedia");
|
|
||||||
return lock.release();
|
return lock.release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -668,7 +660,6 @@ PlaylistModule.prototype.handleMoveMedia = function (user, data) {
|
||||||
(after ? " after " + after.media.title : ""));
|
(after ? " after " + after.media.title : ""));
|
||||||
self._listDirty = true;
|
self._listDirty = true;
|
||||||
lock.release();
|
lock.release();
|
||||||
self.channel.refCounter.unref("PlaylistModule::handleMoveMedia");
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1356,14 +1347,15 @@ PlaylistModule.prototype.handleQueuePlaylist = function (user, data) {
|
||||||
};
|
};
|
||||||
|
|
||||||
const self = this;
|
const self = this;
|
||||||
self.channel.refCounter.ref("PlaylistModule::handleQueuePlaylist");
|
|
||||||
db.getUserPlaylist(user.getName(), data.name, function (err, pl) {
|
db.getUserPlaylist(user.getName(), data.name, function (err, pl) {
|
||||||
if (err) {
|
if (err) {
|
||||||
self.channel.refCounter.unref("PlaylistModule::handleQueuePlaylist");
|
|
||||||
return user.socket.emit("errorMsg", {
|
return user.socket.emit("errorMsg", {
|
||||||
msg: "Playlist load failed: " + err
|
msg: "Playlist load failed: " + err
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (self.channel.dead) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (data.pos === "next") {
|
if (data.pos === "next") {
|
||||||
|
@ -1398,8 +1390,6 @@ PlaylistModule.prototype.handleQueuePlaylist = function (user, data) {
|
||||||
msg: "Internal error occurred when loading playlist.",
|
msg: "Internal error occurred when loading playlist.",
|
||||||
link: null
|
link: null
|
||||||
});
|
});
|
||||||
} finally {
|
|
||||||
self.channel.refCounter.unref("PlaylistModule::handleQueuePlaylist");
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -357,11 +357,9 @@ Server.prototype.unloadChannel = function (chan, options) {
|
||||||
|
|
||||||
LOGGER.info("Unloaded channel " + chan.name);
|
LOGGER.info("Unloaded channel " + chan.name);
|
||||||
chan.broadcastUsercount.cancel();
|
chan.broadcastUsercount.cancel();
|
||||||
// Empty all outward references from the channel
|
// Empty all outward references from the channel | TODO does this actually help?
|
||||||
Object.keys(chan).forEach(key => {
|
Object.keys(chan).forEach(key => {
|
||||||
if (key !== "refCounter") {
|
delete chan[key];
|
||||||
delete chan[key];
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
chan.dead = true;
|
chan.dead = true;
|
||||||
promActiveChannels.dec();
|
promActiveChannels.dec();
|
||||||
|
|
|
@ -421,10 +421,6 @@ function showChannelDetailModal(c) {
|
||||||
$("<td/>").text("Public").appendTo(tr);
|
$("<td/>").text("Public").appendTo(tr);
|
||||||
$("<td/>").text(c.public).appendTo(tr);
|
$("<td/>").text(c.public).appendTo(tr);
|
||||||
|
|
||||||
tr = $("<tr/>").appendTo(table);
|
|
||||||
$("<td/>").text("ActiveLock Count").appendTo(tr);
|
|
||||||
$("<td/>").text(c.activeLockCount).appendTo(tr);
|
|
||||||
|
|
||||||
tr = $("<tr/>").appendTo(table);
|
tr = $("<tr/>").appendTo(table);
|
||||||
$("<td/>").text("Chat Filter Count").appendTo(tr);
|
$("<td/>").text("Chat Filter Count").appendTo(tr);
|
||||||
$("<td/>").text(c.chatFilterCount).appendTo(tr);
|
$("<td/>").text(c.chatFilterCount).appendTo(tr);
|
||||||
|
|
Loading…
Reference in New Issue