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';
11import _ from 'lodash';11import _ from 'lodash';
12import mime from 'mime-types';12import mime from 'mime-types';
13import jimp from 'jimp';13import jimp from 'jimp';
14import storage from 'node-persist';
1415
15import { AVATAR_WIDTH, AVATAR_HEIGHT } from '../constants.js';16import { AVATAR_WIDTH, AVATAR_HEIGHT } from '../constants.js';
16import { jsonParser, urlencodedParser } from '../express-common.js';17import { jsonParser, urlencodedParser } from '../express-common.js';
@@ -30,6 +31,29 @@ const memoryCache = new MemoryLimitedMap(memoryCacheCapacity);
30const isAndroid = process.platform === 'android';31const isAndroid = process.platform === 'android';
31// Use shallow character data for the character list32// Use shallow character data for the character list
32const useShallowCharacters = !!getConfigValue('performance.lazyLoadCharacters', false, 'boolean');33const useShallowCharacters = !!getConfigValue('performance.lazyLoadCharacters', false, 'boolean');
34const useDiskCache = true; // !!getConfigValue('performance.useDiskCache', false, 'boolean');
35
36const 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
34/**58/**
35 * Reads the character card from the specified image file.59 * Reads the character card from the specified image file.
@@ -43,9 +67,18 @@ async function readCharacterData(inputFile, inputFormat = 'png') {
43 if (memoryCache.has(cacheKey)) {67 if (memoryCache.has(cacheKey)) {
44 return memoryCache.get(cacheKey);68 return memoryCache.get(cacheKey);
45 }69 }
70 if (useDiskCache) {
71 const cachedData = await diskCache.instance().then(i => i.getItem(cacheKey));
72 if (cachedData) {
73 return cachedData;
74 }
75 }
4676
47 const result = parse(inputFile, inputFormat);77 const result = parse(inputFile, inputFormat);
48 !isAndroid && memoryCache.set(cacheKey, result);78 !isAndroid && memoryCache.set(cacheKey, result);
79 if (useDiskCache) {
80 await diskCache.instance().then(i => i.setItem(cacheKey, result));
81 }
49 return result;82 return result;
50}83}
5184
@@ -70,6 +103,15 @@ async function writeCharacterData(inputFile, data, outputFile, request, crop = u
70 break;103 break;
71 }104 }
72 }105 }
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
74 /**116 /**
75 * Read the image, resize, and save it as a PNG into the buffer.117 * Read the image, resize, and save it as a PNG into the buffer.