Implement disk caching for character data using node-persist

3c65b2dcf319f6af5745a661dc03a78a867b8b89

Cohee <18619528+Cohee1207@users.noreply.github.com>

1 files changed, +42 -0Showing whitespace changes
src/endpoints/characters.js+42 -0
@@ -11,6 +11,7 @@ import yaml from 'yaml';
1111import _ from 'lodash';
1212import mime from 'mime-types';
1313import jimp from 'jimp';
14+import storage from 'node-persist';
1415
1516import { AVATAR_WIDTH, AVATAR_HEIGHT } from '../constants.js';
1617import { jsonParser, urlencodedParser } from '../express-common.js';
@@ -30,6 +31,29 @@ const memoryCache = new MemoryLimitedMap(memoryCacheCapacity);
3031const isAndroid = process.platform === 'android';
3132// Use shallow character data for the character list
3233const useShallowCharacters = !!getConfigValue('performance.lazyLoadCharacters', false, 'boolean');
34+const useDiskCache = true; // !!getConfigValue('performance.useDiskCache', false, 'boolean');
35+
36+const diskCache = {
37+ /**
38+ * @type {import('node-persist').LocalStorage?}
39+ * @private
40+ */
41+ _instance: null,
42+ /**
43+ * Gets the disk cache instance.
44+ * @returns {Promise<import('node-persist').LocalStorage>}
45+ */
46+ instance: async function() {
47+ if (this._instance) {
48+ return this._instance;
49+ }
50+
51+ const cacheDir = path.join(globalThis.DATA_ROOT, '_cache', 'characters');
52+ this._instance = storage.create({ dir: cacheDir, ttl: true });
53+ await this._instance.init();
54+ return this._instance;
55+ },
56+};
3357
3458/**
3559 * Reads the character card from the specified image file.
@@ -43,9 +67,18 @@ async function readCharacterData(inputFile, inputFormat = 'png') {
4367 if (memoryCache.has(cacheKey)) {
4468 return memoryCache.get(cacheKey);
4569 }
70+ if (useDiskCache) {
71+ const cachedData = await diskCache.instance().then(i => i.getItem(cacheKey));
72+ if (cachedData) {
73+ return cachedData;
74+ }
75+ }
4676
4777 const result = parse(inputFile, inputFormat);
4878 !isAndroid && memoryCache.set(cacheKey, result);
79+ if (useDiskCache) {
80+ await diskCache.instance().then(i => i.setItem(cacheKey, result));
81+ }
4982 return result;
5083}
5184
@@ -70,6 +103,15 @@ async function writeCharacterData(inputFile, data, outputFile, request, crop = u
70103 break;
71104 }
72105 }
106+ if (useDiskCache && !Buffer.isBuffer(inputFile)) {
107+ const keys = await diskCache.instance().then(i => i.keys());
108+ for (const key of keys) {
109+ if (key.startsWith(inputFile)) {
110+ await diskCache.instance().then(i => i.removeItem(key));
111+ break;
112+ }
113+ }
114+ }
73115
74116 /**
75117 * Read the image, resize, and save it as a PNG into the buffer.