Skip to content

Commit

Permalink
feat: allow plugins to add to admin cache list (#10833)
Browse files Browse the repository at this point in the history
* feat: allow plugins to add to admin cache list

resolves  #10820

plugins will have to use `filter:admin.cache.get` hook and just add their own cache to the object there.

* feat: add dump to ttlCache and expose properties

* feat: also expose properties under their current names

* feat: display TTL if set
  • Loading branch information
oplik0 committed Aug 14, 2022
1 parent 2568986 commit a9bbb58
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 113 deletions.
3 changes: 3 additions & 0 deletions public/language/en-GB/admin/advanced/cache.json
@@ -1,5 +1,8 @@
{
"post-cache": "Post Cache",
"group-cache": "Group Cache",
"local-cache": "Local Cache",
"object-cache": "Object Cache",
"percent-full": "%1% Full",
"post-cache-size": "Post Cache Size",
"items-in-cache": "Items in Cache"
Expand Down
5 changes: 4 additions & 1 deletion src/cache/lru.js
Expand Up @@ -37,12 +37,15 @@ module.exports = function (opts) {
cache.enabled = opts.hasOwnProperty('enabled') ? opts.enabled : true;
const cacheSet = lruCache.set;

// backwards compatibility
// expose properties while keeping backwards compatibility
const propertyMap = new Map([
['length', 'calculatedSize'],
['calculatedSize', 'calculatedSize'],
['max', 'max'],
['maxSize', 'maxSize'],
['itemCount', 'size'],
['size', 'size'],
['ttl', 'ttl'],
]);
propertyMap.forEach((lruProp, cacheProp) => {
Object.defineProperty(cache, cacheProp, {
Expand Down
25 changes: 25 additions & 0 deletions src/cache/ttl.js
Expand Up @@ -13,6 +13,23 @@ module.exports = function (opts) {
cache.enabled = opts.hasOwnProperty('enabled') ? opts.enabled : true;
const cacheSet = ttlCache.set;

// expose properties
const propertyMap = new Map([
['max', 'max'],
['itemCount', 'size'],
['size', 'size'],
['ttl', 'ttl'],
]);
propertyMap.forEach((ttlProp, cacheProp) => {
Object.defineProperty(cache, cacheProp, {
get: function () {
return ttlCache[ttlProp];
},
configurable: true,
enumerable: true,
});
});

cache.set = function (key, value, ttl) {
if (!cache.enabled) {
return;
Expand Down Expand Up @@ -90,5 +107,13 @@ module.exports = function (opts) {
return unCachedKeys;
};

cache.dump = function () {
return Array.from(ttlCache.entries());
};

cache.peek = function (key) {
return ttlCache.get(key, { updateAgeOnGet: false });
};

return cache;
};
27 changes: 16 additions & 11 deletions src/controllers/admin/cache.js
Expand Up @@ -3,8 +3,9 @@
const cacheController = module.exports;

const utils = require('../../utils');
const plugins = require('../../plugins');

cacheController.get = function (req, res) {
cacheController.get = async function (req, res) {
const postCache = require('../../posts/cache');
const groupCache = require('../../groups').cache;
const { objectCache } = require('../../database');
Expand All @@ -23,29 +24,33 @@ cacheController.get = function (req, res) {
misses: utils.addCommas(String(cache.misses)),
hitRatio: ((cache.hits / (cache.hits + cache.misses) || 0)).toFixed(4),
enabled: cache.enabled,
ttl: cache.ttl,
};
}

const data = {
postCache: getInfo(postCache),
groupCache: getInfo(groupCache),
localCache: getInfo(localCache),
let caches = {
post: postCache,
group: groupCache,
local: localCache,
};

if (objectCache) {
data.objectCache = getInfo(objectCache);
caches.object = objectCache;
}
caches = await plugins.hooks.fire('filter:admin.cache.get', caches);
for (const [key, value] of Object.entries(caches)) {
caches[key] = getInfo(value);
}

res.render('admin/advanced/cache', data);
res.render('admin/advanced/cache', { caches });
};

cacheController.dump = function (req, res, next) {
const caches = {
cacheController.dump = async function (req, res, next) {
let caches = {
post: require('../../posts/cache'),
object: require('../../database').objectCache,
group: require('../../groups').cache,
local: require('../../cache'),
};
caches = await plugins.hooks.fire('filter:admin.cache.get', caches);
if (!caches[req.query.name]) {
return next();
}
Expand Down
22 changes: 13 additions & 9 deletions src/socket.io/admin/cache.js
Expand Up @@ -3,26 +3,30 @@
const SocketCache = module.exports;

const db = require('../../database');
const plugins = require('../../plugins');

SocketCache.clear = async function (socket, data) {
if (data.name === 'post') {
require('../../posts/cache').reset();
} else if (data.name === 'object' && db.objectCache) {
db.objectCache.reset();
} else if (data.name === 'group') {
require('../../groups').cache.reset();
} else if (data.name === 'local') {
require('../../cache').reset();
let caches = {
post: require('../../posts/cache'),
object: db.objectCache,
group: require('../../groups').cache,
local: require('../../cache'),
};
caches = await plugins.hooks.fire('filter:admin.cache.get', caches);
if (!caches[data.name]) {
return;
}
caches[data.name].reset();
};

SocketCache.toggle = async function (socket, data) {
const caches = {
let caches = {
post: require('../../posts/cache'),
object: db.objectCache,
group: require('../../groups').cache,
local: require('../../cache'),
};
caches = await plugins.hooks.fire('filter:admin.cache.get', caches);
if (!caches[data.name]) {
return;
}
Expand Down
109 changes: 17 additions & 92 deletions src/views/admin/advanced/cache.tpl
Expand Up @@ -2,118 +2,43 @@
<div class="row post-cache">
<div class="col-lg-12">
<div class="row">
{{{each caches}}}
<div class="col-lg-3">
<div class="panel panel-default">
<div class="panel-heading">[[admin/advanced/cache:post-cache]]</div>
<div class="panel-heading">[[admin/advanced/cache:{@key}-cache]]</div>
<div class="panel-body">
<div class="checkbox" data-name="post">
<div class="checkbox" data-name="{@key}">
<label class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
<input class="mdl-switch__input" type="checkbox" {{{if postCache.enabled}}}checked{{{end}}}>
<input class="mdl-switch__input" type="checkbox" {{{if caches.enabled}}}checked{{{end}}}>
</label>
</div>

<span>{postCache.length} / {postCache.maxSize}</span><br/>
<span>{{{if ../length}}}{../length}{{{else}}}{../itemCount}{{{end}}} / {{{if ../max}}}{../max}{{{else}}}{../maxSize}{{{end}}}</span><br/>

<div class="progress">
<div class="progress-bar" role="progressbar" aria-valuenow="{postCache.percentFull}" aria-valuemin="0" aria-valuemax="100" style="width: {postCache.percentFull}%;">
[[admin/advanced/cache:percent-full, {postCache.percentFull}]]
<div class="progress-bar" role="progressbar" aria-valuenow="{../percentFull}" aria-valuemin="0" aria-valuemax="100" style="width: {../percentFull}%;">
[[admin/advanced/cache:percent-full, {../percentFull}]]
</div>
</div>

<label>Hits:</label> <span>{postCache.hits}</span><br/>
<label>Misses:</label> <span>{postCache.misses}</span><br/>
<label>Hit Ratio:</label> <span>{postCache.hitRatio}</span><br/>

<label>Hits:</label> <span>{../hits}</span><br/>
<label>Misses:</label> <span>{../misses}</span><br/>
<label>Hit Ratio:</label> <span>{../hitRatio}</span><br/>
{{{if ../ttl}}}<label>TTL:</label> <span>{../ttl}</span></br>{{{end}}}
{{{if (@key == "post")}}}
<hr/>

<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-sm btn-default"><i class="fa fa-download"></i></a>
<a class="btn btn-sm btn-danger clear" data-name="post"><i class="fa fa-trash"></i></a>
</div>
</div>
</div>

<!-- IF objectCache -->
<div class="col-lg-3">
<div class="panel panel-default">
<div class="panel-heading">Object Cache</div>
<div class="panel-body">
<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}}}>
</label>
</div>
<span>{objectCache.itemCount} / {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}%;">
[[admin/advanced/cache:percent-full, {objectCache.percentFull}]]
</div>
</div>

<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-sm btn-default"><i class="fa fa-download"></i></a>
<a class="btn btn-sm btn-danger clear" data-name="object"><i class="fa fa-trash"></i></a>
</div>
</div>
</div>
<!-- ENDIF objectCache -->

<div class="col-lg-3">
<div class="panel panel-default">
<div class="panel-heading">Group Cache</div>
<div class="panel-body">
<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}}}>
</label>
</div>
<span>{groupCache.itemCount} / {groupCache.max}</span><br/>

<div class="progress">
<div class="progress-bar" role="progressbar" aria-valuenow="{groupCache.percentFull}" aria-valuemin="0" aria-valuemax="100" style="width: {groupCache.percentFull}%;">
[[admin/advanced/cache:percent-full, {groupCache.percentFull}]]
</div>
</div>

<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-sm btn-default"><i class="fa fa-download"></i></a>
<a class="btn btn-sm btn-danger clear" data-name="group"><i class="fa fa-trash"></i></a>
</div>
</div>
</div>

<div class="col-lg-3">
<div class="panel panel-default">
<div class="panel-heading">Local Cache</div>
<div class="panel-body">
<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}}}>
</label>
</div>
<span>{localCache.itemCount} / {localCache.max}</span><br/>

<div class="progress">
<div class="progress-bar" role="progressbar" aria-valuenow="{localCache.percentFull}" aria-valuemin="0" aria-valuemax="100" style="width: {localCache.percentFull}%;">
[[admin/advanced/cache:percent-full, {localCache.percentFull}]]
</div>
</div>

<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/>
<a href="{config.relative_path}/api/admin/advanced/cache/dump?name=local" class="btn btn-sm btn-default"><i class="fa fa-download"></i></a>
<a class="btn btn-sm btn-danger clear" data-name="local"><i class="fa fa-trash"></i></a>
{{{end}}}
<a href="{config.relative_path}/api/admin/advanced/cache/dump?name={@key}" class="btn btn-sm btn-default"><i class="fa fa-download"></i></a>
<a class="btn btn-sm btn-danger clear" data-name="{@key}"><i class="fa fa-trash"></i></a>
</div>
</div>
</div>
{{{end}}}

</div>
</div>
</div>
Expand Down

0 comments on commit a9bbb58

Please sign in to comment.