mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-10-26 08:36:12 +01:00
* feat: #8824, cache refactor ability to disable caches ability to download contents of cache refactor cache modules to remove duplicated code * fix: remove duplicate hit/miss tracking check cacheEnabled in getUncachedKeys
This commit is contained in:
committed by
GitHub
parent
bcbc085497
commit
f1f9b225b0
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"post-cache": "Post Cache",
|
||||
"posts-in-cache": "Posts in Cache",
|
||||
"average-post-size": "Average Post Size",
|
||||
"length-to-max": "Length / Max",
|
||||
"percent-full": "%1% Full",
|
||||
"post-cache-size": "Post Cache Size",
|
||||
"items-in-cache": "Items in Cache",
|
||||
"control-panel": "Control Panel",
|
||||
"update-settings": "Update Cache Settings"
|
||||
"update-settings": "Update Cache Settings",
|
||||
"clear": "Clear",
|
||||
"download": "Download",
|
||||
"enabled": "Enabled"
|
||||
}
|
||||
@@ -23,14 +23,14 @@ get:
|
||||
type: number
|
||||
percentFull:
|
||||
type: number
|
||||
avgPostSize:
|
||||
type: number
|
||||
hits:
|
||||
type: string
|
||||
misses:
|
||||
type: string
|
||||
hitRatio:
|
||||
type: string
|
||||
enabled:
|
||||
type: boolean
|
||||
groupCache:
|
||||
type: object
|
||||
properties:
|
||||
@@ -48,6 +48,8 @@ get:
|
||||
type: string
|
||||
hitRatio:
|
||||
type: string
|
||||
enabled:
|
||||
type: boolean
|
||||
localCache:
|
||||
type: object
|
||||
properties:
|
||||
@@ -59,14 +61,14 @@ get:
|
||||
type: number
|
||||
percentFull:
|
||||
type: number
|
||||
dump:
|
||||
type: boolean
|
||||
hits:
|
||||
type: string
|
||||
misses:
|
||||
type: string
|
||||
hitRatio:
|
||||
type: string
|
||||
enabled:
|
||||
type: boolean
|
||||
objectCache:
|
||||
type: object
|
||||
properties:
|
||||
@@ -84,6 +86,8 @@ get:
|
||||
type: string
|
||||
hitRatio:
|
||||
type: string
|
||||
enabled:
|
||||
type: boolean
|
||||
required:
|
||||
- postCache
|
||||
- groupCache
|
||||
|
||||
@@ -15,6 +15,16 @@ define('admin/advanced/cache', function () {
|
||||
ajaxify.refresh();
|
||||
});
|
||||
});
|
||||
$('.checkbox').on('change', function () {
|
||||
var input = $(this).find('input');
|
||||
var flag = input.is(':checked');
|
||||
var name = $(this).attr('data-name');
|
||||
socket.emit('admin.cache.toggle', { name: name, enabled: flag }, function (err) {
|
||||
if (err) {
|
||||
return app.alertError(err.message);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
return Cache;
|
||||
});
|
||||
|
||||
53
src/cache.js
53
src/cache.js
@@ -1,56 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
const LRU = require('lru-cache');
|
||||
const pubsub = require('./pubsub');
|
||||
const cacheCreate = require('./cacheCreate');
|
||||
|
||||
const cache = new LRU({
|
||||
module.exports = cacheCreate({
|
||||
name: 'local',
|
||||
max: 4000,
|
||||
maxAge: 0,
|
||||
});
|
||||
cache.hits = 0;
|
||||
cache.misses = 0;
|
||||
|
||||
const cacheGet = cache.get;
|
||||
const cacheDel = cache.del;
|
||||
const cacheReset = cache.reset;
|
||||
|
||||
cache.get = function (key) {
|
||||
const data = cacheGet.apply(cache, [key]);
|
||||
if (data === undefined) {
|
||||
cache.misses += 1;
|
||||
} else {
|
||||
cache.hits += 1;
|
||||
}
|
||||
return data;
|
||||
};
|
||||
|
||||
cache.del = function (key) {
|
||||
if (!Array.isArray(key)) {
|
||||
key = [key];
|
||||
}
|
||||
pubsub.publish('local:cache:del', key);
|
||||
key.forEach(key => cacheDel.apply(cache, [key]));
|
||||
};
|
||||
|
||||
cache.reset = function () {
|
||||
pubsub.publish('local:cache:reset');
|
||||
localReset();
|
||||
};
|
||||
|
||||
function localReset() {
|
||||
cacheReset.apply(cache);
|
||||
cache.hits = 0;
|
||||
cache.misses = 0;
|
||||
}
|
||||
|
||||
pubsub.on('local:cache:reset', function () {
|
||||
localReset();
|
||||
});
|
||||
|
||||
pubsub.on('local:cache:del', function (keys) {
|
||||
if (Array.isArray(keys)) {
|
||||
keys.forEach(key => cacheDel.apply(cache, [key]));
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = cache;
|
||||
|
||||
91
src/cacheCreate.js
Normal file
91
src/cacheCreate.js
Normal file
@@ -0,0 +1,91 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = function (opts) {
|
||||
const LRU = require('lru-cache');
|
||||
const pubsub = require('./pubsub');
|
||||
|
||||
const cache = new LRU(opts);
|
||||
|
||||
cache.name = opts.name;
|
||||
cache.hits = 0;
|
||||
cache.misses = 0;
|
||||
cache.enabled = opts.hasOwnProperty('enabled') ? opts.enabled : true;
|
||||
|
||||
const cacheSet = cache.set;
|
||||
const cacheGet = cache.get;
|
||||
const cacheDel = cache.del;
|
||||
const cacheReset = cache.reset;
|
||||
|
||||
cache.set = function (key, value) {
|
||||
if (!cache.enabled) {
|
||||
return;
|
||||
}
|
||||
cacheSet.apply(cache, [key, value]);
|
||||
};
|
||||
|
||||
cache.get = function (key) {
|
||||
if (!cache.enabled) {
|
||||
return undefined;
|
||||
}
|
||||
const data = cacheGet.apply(cache, [key]);
|
||||
if (data === undefined) {
|
||||
cache.misses += 1;
|
||||
} else {
|
||||
cache.hits += 1;
|
||||
}
|
||||
return data;
|
||||
};
|
||||
|
||||
cache.del = function (keys) {
|
||||
if (!Array.isArray(keys)) {
|
||||
keys = [keys];
|
||||
}
|
||||
pubsub.publish(cache.name + ':cache:del', keys);
|
||||
keys.forEach(key => cacheDel.apply(cache, [key]));
|
||||
};
|
||||
|
||||
cache.reset = function () {
|
||||
pubsub.publish(cache.name + ':cache:reset');
|
||||
localReset();
|
||||
};
|
||||
|
||||
function localReset() {
|
||||
cacheReset.apply(cache);
|
||||
cache.hits = 0;
|
||||
cache.misses = 0;
|
||||
}
|
||||
|
||||
pubsub.on(cache.name + ':cache:reset', function () {
|
||||
localReset();
|
||||
});
|
||||
|
||||
pubsub.on(cache.name + ':cache:del', function (keys) {
|
||||
if (Array.isArray(keys)) {
|
||||
keys.forEach(key => cacheDel.apply(cache, [key]));
|
||||
}
|
||||
});
|
||||
|
||||
cache.getUnCachedKeys = function (keys, cachedData) {
|
||||
if (!cache.enabled) {
|
||||
return keys;
|
||||
}
|
||||
let data;
|
||||
let isCached;
|
||||
const unCachedKeys = keys.filter(function (key) {
|
||||
data = cache.get(key);
|
||||
isCached = data !== undefined;
|
||||
if (isCached) {
|
||||
cachedData[key] = data;
|
||||
}
|
||||
return !isCached;
|
||||
});
|
||||
|
||||
var hits = keys.length - unCachedKeys.length;
|
||||
var misses = keys.length - hits;
|
||||
cache.hits += hits;
|
||||
cache.misses += misses;
|
||||
return unCachedKeys;
|
||||
};
|
||||
|
||||
return cache;
|
||||
};
|
||||
@@ -10,10 +10,8 @@ cacheController.get = function (req, res) {
|
||||
const objectCache = require('../../database').objectCache;
|
||||
const localCache = require('../../cache');
|
||||
|
||||
let avgPostSize = 0;
|
||||
let percentFull = 0;
|
||||
if (postCache.itemCount > 0) {
|
||||
avgPostSize = parseInt((postCache.length / postCache.itemCount), 10);
|
||||
percentFull = ((postCache.length / postCache.max) * 100).toFixed(2);
|
||||
}
|
||||
|
||||
@@ -23,10 +21,10 @@ cacheController.get = function (req, res) {
|
||||
max: postCache.max,
|
||||
itemCount: postCache.itemCount,
|
||||
percentFull: percentFull,
|
||||
avgPostSize: avgPostSize,
|
||||
hits: utils.addCommas(String(postCache.hits)),
|
||||
misses: utils.addCommas(String(postCache.misses)),
|
||||
hitRatio: ((postCache.hits / (postCache.hits + postCache.misses) || 0)).toFixed(4),
|
||||
enabled: postCache.enabled,
|
||||
},
|
||||
groupCache: {
|
||||
length: groupCache.length,
|
||||
@@ -36,16 +34,17 @@ cacheController.get = function (req, res) {
|
||||
hits: utils.addCommas(String(groupCache.hits)),
|
||||
misses: utils.addCommas(String(groupCache.misses)),
|
||||
hitRatio: (groupCache.hits / (groupCache.hits + groupCache.misses)).toFixed(4),
|
||||
enabled: groupCache.enabled,
|
||||
},
|
||||
localCache: {
|
||||
length: localCache.length,
|
||||
max: localCache.max,
|
||||
itemCount: localCache.itemCount,
|
||||
percentFull: ((localCache.length / localCache.max) * 100).toFixed(2),
|
||||
dump: req.query.debug ? JSON.stringify(localCache.dump(), null, 4) : false,
|
||||
hits: utils.addCommas(String(localCache.hits)),
|
||||
misses: utils.addCommas(String(localCache.misses)),
|
||||
hitRatio: ((localCache.hits / (localCache.hits + localCache.misses) || 0)).toFixed(4),
|
||||
enabled: localCache.enabled,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -58,8 +57,31 @@ cacheController.get = function (req, res) {
|
||||
hits: utils.addCommas(String(objectCache.hits)),
|
||||
misses: utils.addCommas(String(objectCache.misses)),
|
||||
hitRatio: (objectCache.hits / (objectCache.hits + objectCache.misses)).toFixed(4),
|
||||
enabled: objectCache.enabled,
|
||||
};
|
||||
}
|
||||
|
||||
res.render('admin/advanced/cache', data);
|
||||
};
|
||||
|
||||
cacheController.dump = function (req, res, next) {
|
||||
const caches = {
|
||||
post: require('../../posts/cache'),
|
||||
object: require('../../database').objectCache,
|
||||
group: require('../../groups').cache,
|
||||
local: require('../../cache'),
|
||||
};
|
||||
if (!caches[req.query.name]) {
|
||||
return next();
|
||||
}
|
||||
|
||||
const data = JSON.stringify(caches[req.query.name].dump(), null, 4);
|
||||
res.setHeader('Content-disposition', 'attachment; filename= ' + req.query.name + '-cache.json');
|
||||
res.setHeader('Content-type', 'application/json');
|
||||
res.write(data, function (err) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
res.end();
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,56 +1,11 @@
|
||||
'use strict';
|
||||
|
||||
module.exports.create = function (name) {
|
||||
var LRU = require('lru-cache');
|
||||
var pubsub = require('../pubsub');
|
||||
|
||||
var cache = new LRU({
|
||||
const cacheCreate = require('../cacheCreate');
|
||||
return cacheCreate({
|
||||
name: name + '-object',
|
||||
max: 40000,
|
||||
length: function () { return 1; },
|
||||
maxAge: 0,
|
||||
});
|
||||
|
||||
cache.misses = 0;
|
||||
cache.hits = 0;
|
||||
|
||||
pubsub.on(name + ':hash:cache:del', function (keys) {
|
||||
keys.forEach(key => cache.del(key));
|
||||
});
|
||||
|
||||
pubsub.on(name + ':hash:cache:reset', function () {
|
||||
cache.reset();
|
||||
});
|
||||
|
||||
cache.delObjectCache = function (keys) {
|
||||
if (!Array.isArray(keys)) {
|
||||
keys = [keys];
|
||||
}
|
||||
pubsub.publish(name + ':hash:cache:del', keys);
|
||||
keys.forEach(key => cache.del(key));
|
||||
};
|
||||
|
||||
cache.resetObjectCache = function () {
|
||||
pubsub.publish(name + ':hash:cache:reset');
|
||||
cache.reset();
|
||||
};
|
||||
|
||||
cache.getUnCachedKeys = function (keys, cachedData) {
|
||||
let data;
|
||||
let isCached;
|
||||
const unCachedKeys = keys.filter(function (key) {
|
||||
data = cache.get(key);
|
||||
isCached = data !== undefined;
|
||||
if (isCached) {
|
||||
cachedData[key] = data;
|
||||
}
|
||||
return !isCached;
|
||||
});
|
||||
|
||||
var hits = keys.length - unCachedKeys.length;
|
||||
var misses = keys.length - hits;
|
||||
cache.hits += hits;
|
||||
cache.misses += misses;
|
||||
return unCachedKeys;
|
||||
};
|
||||
return cache;
|
||||
};
|
||||
|
||||
@@ -29,7 +29,7 @@ module.exports = function (module) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
cache.delObjectCache(key);
|
||||
cache.del(key);
|
||||
};
|
||||
|
||||
module.setObjectField = async function (key, field, value) {
|
||||
@@ -164,7 +164,7 @@ module.exports = function (module) {
|
||||
});
|
||||
|
||||
await module.client.collection('objects').updateOne({ _key: key }, { $unset: data });
|
||||
cache.delObjectCache(key);
|
||||
cache.del(key);
|
||||
};
|
||||
|
||||
module.incrObjectField = async function (key, field) {
|
||||
@@ -191,13 +191,13 @@ module.exports = function (module) {
|
||||
bulk.find({ _key: key }).upsert().update({ $inc: increment });
|
||||
});
|
||||
await bulk.execute();
|
||||
cache.delObjectCache(key);
|
||||
cache.del(key);
|
||||
const result = await module.getObjectsFields(key, [field]);
|
||||
return result.map(data => data && data[field]);
|
||||
}
|
||||
|
||||
const result = await module.client.collection('objects').findOneAndUpdate({ _key: key }, { $inc: increment }, { returnOriginal: false, upsert: true });
|
||||
cache.delObjectCache(key);
|
||||
cache.del(key);
|
||||
return result && result.value ? result.value[field] : null;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -8,7 +8,7 @@ module.exports = function (module) {
|
||||
|
||||
module.emptydb = async function () {
|
||||
await module.client.collection('objects').deleteMany({});
|
||||
module.objectCache.resetObjectCache();
|
||||
module.objectCache.reset();
|
||||
};
|
||||
|
||||
module.exists = async function (key) {
|
||||
@@ -47,7 +47,7 @@ module.exports = function (module) {
|
||||
return;
|
||||
}
|
||||
await module.client.collection('objects').deleteMany({ _key: key });
|
||||
module.objectCache.delObjectCache(key);
|
||||
module.objectCache.del(key);
|
||||
};
|
||||
|
||||
module.deleteAll = async function (keys) {
|
||||
@@ -55,7 +55,7 @@ module.exports = function (module) {
|
||||
return;
|
||||
}
|
||||
await module.client.collection('objects').deleteMany({ _key: { $in: keys } });
|
||||
module.objectCache.delObjectCache(keys);
|
||||
module.objectCache.del(keys);
|
||||
};
|
||||
|
||||
module.get = async function (key) {
|
||||
@@ -96,7 +96,7 @@ module.exports = function (module) {
|
||||
|
||||
module.rename = async function (oldKey, newKey) {
|
||||
await module.client.collection('objects').updateMany({ _key: oldKey }, { $set: { _key: newKey } });
|
||||
module.objectCache.delObjectCache([oldKey, newKey]);
|
||||
module.objectCache.del([oldKey, newKey]);
|
||||
};
|
||||
|
||||
module.type = async function (key) {
|
||||
|
||||
@@ -33,7 +33,7 @@ module.exports = function (module) {
|
||||
await module.client.async.hmset(key, data);
|
||||
}
|
||||
|
||||
cache.delObjectCache(key);
|
||||
cache.del(key);
|
||||
};
|
||||
|
||||
module.setObjectField = async function (key, field, value) {
|
||||
@@ -48,7 +48,7 @@ module.exports = function (module) {
|
||||
await module.client.async.hset(key, field, value);
|
||||
}
|
||||
|
||||
cache.delObjectCache(key);
|
||||
cache.del(key);
|
||||
};
|
||||
|
||||
module.getObject = async function (key) {
|
||||
@@ -146,7 +146,7 @@ module.exports = function (module) {
|
||||
return;
|
||||
}
|
||||
await module.client.async.hdel(key, field);
|
||||
cache.delObjectCache(key);
|
||||
cache.del(key);
|
||||
};
|
||||
|
||||
module.deleteObjectFields = async function (key, fields) {
|
||||
@@ -158,7 +158,7 @@ module.exports = function (module) {
|
||||
return;
|
||||
}
|
||||
await module.client.async.hdel(key, fields);
|
||||
cache.delObjectCache(key);
|
||||
cache.del(key);
|
||||
};
|
||||
|
||||
module.incrObjectField = async function (key, field) {
|
||||
@@ -182,7 +182,7 @@ module.exports = function (module) {
|
||||
} else {
|
||||
result = await module.client.async.hincrby(key, field, value);
|
||||
}
|
||||
cache.delObjectCache(key);
|
||||
cache.del(key);
|
||||
return Array.isArray(result) ? result.map(value => parseInt(value, 10)) : parseInt(result, 10);
|
||||
};
|
||||
};
|
||||
|
||||
@@ -9,7 +9,7 @@ module.exports = function (module) {
|
||||
|
||||
module.emptydb = async function () {
|
||||
await module.flushdb();
|
||||
module.objectCache.resetObjectCache();
|
||||
module.objectCache.reset();
|
||||
};
|
||||
|
||||
module.exists = async function (key) {
|
||||
@@ -45,7 +45,7 @@ module.exports = function (module) {
|
||||
|
||||
module.delete = async function (key) {
|
||||
await module.client.async.del(key);
|
||||
module.objectCache.delObjectCache(key);
|
||||
module.objectCache.del(key);
|
||||
};
|
||||
|
||||
module.deleteAll = async function (keys) {
|
||||
@@ -53,7 +53,7 @@ module.exports = function (module) {
|
||||
return;
|
||||
}
|
||||
await module.client.async.del(keys);
|
||||
module.objectCache.delObjectCache(keys);
|
||||
module.objectCache.del(keys);
|
||||
};
|
||||
|
||||
module.get = async function (key) {
|
||||
@@ -77,7 +77,7 @@ module.exports = function (module) {
|
||||
}
|
||||
}
|
||||
|
||||
module.objectCache.delObjectCache([oldKey, newKey]);
|
||||
module.objectCache.del([oldKey, newKey]);
|
||||
};
|
||||
|
||||
module.type = async function (key) {
|
||||
|
||||
@@ -1,48 +1,19 @@
|
||||
'use strict';
|
||||
|
||||
var LRU = require('lru-cache');
|
||||
var pubsub = require('../pubsub');
|
||||
const cacheCreate = require('../cacheCreate');
|
||||
|
||||
var cache = new LRU({
|
||||
module.exports = function (Groups) {
|
||||
Groups.cache = cacheCreate({
|
||||
name: 'group',
|
||||
max: 40000,
|
||||
maxAge: 0,
|
||||
});
|
||||
cache.hits = 0;
|
||||
cache.misses = 0;
|
||||
|
||||
module.exports = function (Groups) {
|
||||
Groups.cache = cache;
|
||||
|
||||
pubsub.on('group:cache:reset', function () {
|
||||
localReset();
|
||||
});
|
||||
|
||||
pubsub.on('group:cache:del', function (data) {
|
||||
if (data && data.groupNames) {
|
||||
data.groupNames.forEach(function (groupName) {
|
||||
cache.del(data.uid + ':' + groupName);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Groups.resetCache = function () {
|
||||
pubsub.publish('group:cache:reset');
|
||||
localReset();
|
||||
};
|
||||
|
||||
function localReset() {
|
||||
cache.reset();
|
||||
cache.hits = 0;
|
||||
cache.misses = 0;
|
||||
}
|
||||
|
||||
Groups.clearCache = function (uid, groupNames) {
|
||||
if (!Array.isArray(groupNames)) {
|
||||
groupNames = [groupNames];
|
||||
}
|
||||
pubsub.publish('group:cache:del', { uid: uid, groupNames: groupNames });
|
||||
groupNames.forEach(function (groupName) {
|
||||
cache.del(uid + ':' + groupName);
|
||||
});
|
||||
const keys = groupNames.map(name => uid + ':' + name);
|
||||
Groups.cache.del(keys);
|
||||
};
|
||||
};
|
||||
|
||||
@@ -40,7 +40,7 @@ module.exports = function (Groups) {
|
||||
db.deleteObjectFields('groupslug:groupname', fields),
|
||||
removeGroupsFromPrivilegeGroups(groupNames),
|
||||
]);
|
||||
Groups.resetCache();
|
||||
Groups.cache.reset();
|
||||
plugins.fireHook('action:groups.destroy', { groups: groupsData });
|
||||
};
|
||||
|
||||
|
||||
@@ -31,10 +31,8 @@ module.exports = function (Groups) {
|
||||
const cacheKey = uid + ':' + groupName;
|
||||
let isMember = Groups.cache.get(cacheKey);
|
||||
if (isMember !== undefined) {
|
||||
Groups.cache.hits += 1;
|
||||
return isMember;
|
||||
}
|
||||
Groups.cache.misses += 1;
|
||||
isMember = await db.isSortedSetMember('group:' + groupName + ':members', uid);
|
||||
Groups.cache.set(cacheKey, isMember);
|
||||
return isMember;
|
||||
@@ -88,10 +86,7 @@ module.exports = function (Groups) {
|
||||
const isMember = Groups.cache.get(uid + ':' + groupName);
|
||||
const isInCache = isMember !== undefined;
|
||||
if (isInCache) {
|
||||
Groups.cache.hits += 1;
|
||||
cachedData[uid + ':' + groupName] = isMember;
|
||||
} else {
|
||||
Groups.cache.misses += 1;
|
||||
}
|
||||
return !isInCache;
|
||||
}
|
||||
|
||||
@@ -197,7 +197,7 @@ module.exports = function (Groups) {
|
||||
old: oldName,
|
||||
new: newName,
|
||||
});
|
||||
Groups.resetCache();
|
||||
Groups.cache.reset();
|
||||
};
|
||||
|
||||
async function updateMemberGroupTitles(oldName, newName) {
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
'use strict';
|
||||
|
||||
var LRU = require('lru-cache');
|
||||
var meta = require('../meta');
|
||||
const cacheCreate = require('../cacheCreate');
|
||||
const meta = require('../meta');
|
||||
|
||||
var cache = new LRU({
|
||||
module.exports = cacheCreate({
|
||||
name: 'post',
|
||||
max: meta.config.postCacheSize,
|
||||
length: function (n) { return n.length; },
|
||||
maxAge: 0,
|
||||
enabled: global.env === 'production',
|
||||
});
|
||||
cache.hits = 0;
|
||||
cache.misses = 0;
|
||||
|
||||
module.exports = cache;
|
||||
|
||||
@@ -57,13 +57,12 @@ module.exports = function (Posts) {
|
||||
const cachedContent = cache.get(pid);
|
||||
if (postData.pid && cachedContent !== undefined) {
|
||||
postData.content = cachedContent;
|
||||
cache.hits += 1;
|
||||
return postData;
|
||||
}
|
||||
cache.misses += 1;
|
||||
|
||||
const data = await plugins.fireHook('filter:parse.post', { postData: postData });
|
||||
data.postData.content = translator.escape(data.postData.content);
|
||||
if (global.env === 'production' && data.postData.pid) {
|
||||
if (data.postData.pid) {
|
||||
cache.set(pid, data.postData.content);
|
||||
}
|
||||
return data.postData;
|
||||
|
||||
@@ -41,6 +41,9 @@ helpers.isUserAllowedTo = async function (privilege, uid, cid) {
|
||||
};
|
||||
|
||||
async function isUserAllowedToCids(privilege, uid, cids) {
|
||||
if (!privilege) {
|
||||
return cids.map(() => false);
|
||||
}
|
||||
if (parseInt(uid, 10) <= 0) {
|
||||
return await isSystemGroupAllowedToCids(privilege, uid, cids);
|
||||
}
|
||||
|
||||
@@ -61,6 +61,7 @@ function apiRoutes(router, middleware, controllers) {
|
||||
router.get('/api/admin/users/csv', middleware.authenticate, helpers.tryRoute(controllers.admin.users.getCSV));
|
||||
router.get('/api/admin/groups/:groupname/csv', middleware.authenticate, helpers.tryRoute(controllers.admin.groups.getCSV));
|
||||
router.get('/api/admin/analytics', middleware.authenticate, helpers.tryRoute(controllers.admin.dashboard.getAnalytics));
|
||||
router.get('/api/admin/advanced/cache/dump', middleware.authenticate, helpers.tryRoute(controllers.admin.cache.dump));
|
||||
|
||||
const multipart = require('connect-multiparty');
|
||||
const multipartMiddleware = multipart();
|
||||
|
||||
@@ -8,3 +8,16 @@ SocketCache.clear = async function () {
|
||||
require('../../groups').cache.reset();
|
||||
require('../../cache').reset();
|
||||
};
|
||||
|
||||
SocketCache.toggle = async function (socket, data) {
|
||||
const caches = {
|
||||
post: require('../../posts/cache'),
|
||||
object: require('../../database').objectCache,
|
||||
group: require('../../groups').cache,
|
||||
local: require('../../cache'),
|
||||
};
|
||||
if (!caches[data.name]) {
|
||||
return;
|
||||
}
|
||||
caches[data.name].enabled = data.enabled;
|
||||
};
|
||||
|
||||
@@ -6,7 +6,13 @@
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><i class="fa fa-calendar-o"></i> [[admin/advanced/cache:post-cache]]</div>
|
||||
<div class="panel-body">
|
||||
<label>[[admin/advanced/cache:length-to-max]]</label><br/>
|
||||
<div class="checkbox" data-name="post">
|
||||
<label class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
|
||||
<input class="mdl-switch__input" type="checkbox" {{{if postCache.enabled}}}checked{{{end}}}>
|
||||
<span class="mdl-switch__label"><strong>[[admin/advanced/cache:enabled]]</strong></span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<span>{postCache.length} / {postCache.max}</span><br/>
|
||||
|
||||
<div class="progress">
|
||||
@@ -21,16 +27,11 @@
|
||||
|
||||
<hr/>
|
||||
|
||||
<label>[[admin/advanced/cache:posts-in-cache]]</label><br/>
|
||||
<span>{postCache.itemCount}</span><br/>
|
||||
|
||||
<label>[[admin/advanced/cache:average-post-size]]</label><br/>
|
||||
<span>{postCache.avgPostSize}</span><br/>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="postCacheSize">[[admin/advanced/cache:post-cache-size]]</label>
|
||||
<input id="postCacheSize" type="text" class="form-control" value="" data-field="postCacheSize">
|
||||
</div>
|
||||
<a href="{config.relative_path}/api/admin/advanced/cache/dump?name=post" class="btn btn-default"><i class="fa fa-download"></i> [[admin/advanced/cache:download]]</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -40,7 +41,12 @@
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><i class="fa fa-calendar-o"></i> Object Cache</div>
|
||||
<div class="panel-body">
|
||||
<label>[[admin/advanced/cache:length-to-max]]</label><br/>
|
||||
<div class="checkbox" data-name="object">
|
||||
<label class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
|
||||
<input class="mdl-switch__input" type="checkbox" {{{if objectCache.enabled}}}checked{{{end}}}>
|
||||
<span class="mdl-switch__label"><strong>[[admin/advanced/cache:enabled]]</strong></span>
|
||||
</label>
|
||||
</div>
|
||||
<span>{objectCache.length} / {objectCache.max}</span><br/>
|
||||
<div class="progress">
|
||||
<div class="progress-bar" role="progressbar" aria-valuenow="{objectCache.percentFull}" aria-valuemin="0" aria-valuemax="100" style="width: {objectCache.percentFull}%;">
|
||||
@@ -51,6 +57,7 @@
|
||||
<label>Hits:</label> <span>{objectCache.hits}</span><br/>
|
||||
<label>Misses:</label> <span>{objectCache.misses}</span><br/>
|
||||
<label>Hit Ratio:</label> <span>{objectCache.hitRatio}</span><br/>
|
||||
<a href="{config.relative_path}/api/admin/advanced/cache/dump?name=object" class="btn btn-default"><i class="fa fa-download"></i> [[admin/advanced/cache:download]]</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -59,8 +66,12 @@
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><i class="fa fa-calendar-o"></i> Group Cache</div>
|
||||
<div class="panel-body">
|
||||
|
||||
<label>[[admin/advanced/cache:length-to-max]]</label><br/>
|
||||
<div class="checkbox" data-name="group">
|
||||
<label class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
|
||||
<input class="mdl-switch__input" type="checkbox" {{{if groupCache.enabled}}}checked{{{end}}}>
|
||||
<span class="mdl-switch__label"><strong>[[admin/advanced/cache:enabled]]</strong></span>
|
||||
</label>
|
||||
</div>
|
||||
<span>{groupCache.length} / {groupCache.max}</span><br/>
|
||||
|
||||
<div class="progress">
|
||||
@@ -72,6 +83,7 @@
|
||||
<label>Hits:</label> <span>{groupCache.hits}</span><br/>
|
||||
<label>Misses:</label> <span>{groupCache.misses}</span><br/>
|
||||
<label>Hit Ratio:</label> <span>{groupCache.hitRatio}</span><br/>
|
||||
<a href="{config.relative_path}/api/admin/advanced/cache/dump?name=group" class="btn btn-default"><i class="fa fa-download"></i> [[admin/advanced/cache:download]]</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -79,8 +91,12 @@
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><i class="fa fa-calendar-o"></i> Local Cache</div>
|
||||
<div class="panel-body">
|
||||
|
||||
<label>[[admin/advanced/cache:length-to-max]]</label><br/>
|
||||
<div class="checkbox" data-name="local">
|
||||
<label class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
|
||||
<input class="mdl-switch__input" type="checkbox" {{{if localCache.enabled}}}checked{{{end}}}>
|
||||
<span class="mdl-switch__label"><strong>[[admin/advanced/cache:enabled]]</strong></span>
|
||||
</label>
|
||||
</div>
|
||||
<span>{localCache.length} / {localCache.max}</span><br/>
|
||||
|
||||
<div class="progress">
|
||||
@@ -92,11 +108,7 @@
|
||||
<label>Hits:</label> <span>{localCache.hits}</span><br/>
|
||||
<label>Misses:</label> <span>{localCache.misses}</span><br/>
|
||||
<label>Hit Ratio:</label> <span>{localCache.hitRatio}</span><br/>
|
||||
|
||||
<!-- IF localCache.dump -->
|
||||
<pre>{localCache.dump}</pre>
|
||||
<!-- ENDIF localCache.dump -->
|
||||
|
||||
<a href="{config.relative_path}/api/admin/advanced/cache/dump?name=local" class="btn btn-default"><i class="fa fa-download"></i> [[admin/advanced/cache:download]]</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -16,7 +16,7 @@ describe('meta', function () {
|
||||
var herpUid;
|
||||
|
||||
before(function (done) {
|
||||
Groups.resetCache();
|
||||
Groups.cache.reset();
|
||||
// Create 3 users: 1 admin, 2 regular
|
||||
async.series([
|
||||
async.apply(User.create, { username: 'foo', password: 'barbar' }), // admin
|
||||
|
||||
@@ -168,7 +168,7 @@ async function setupMockDefaults() {
|
||||
const meta = require('../../src/meta');
|
||||
await db.emptydb();
|
||||
|
||||
require('../../src/groups').resetCache();
|
||||
require('../../src/groups').cache.reset();
|
||||
require('../../src/posts/cache').reset();
|
||||
require('../../src/cache').reset();
|
||||
winston.info('test_database flushed');
|
||||
|
||||
Reference in New Issue
Block a user