Fix cache removal queue processing

This commit is contained in:
Cohee
2025-03-21 22:47:45 +02:00
parent 4490c3edd5
commit 8e66ab4d51

View File

@@ -33,6 +33,12 @@ const useShallowCharacters = !!getConfigValue('performance.lazyLoadCharacters',
const useDiskCache = !!getConfigValue('performance.useDiskCache', true, 'boolean'); const useDiskCache = !!getConfigValue('performance.useDiskCache', true, 'boolean');
class DiskCache { class DiskCache {
/**
* @typedef {object} CacheRemovalQueueItem
* @property {string} item Path to the character file
* @property {number} timestamp Timestamp of the last access
*/
/** @type {string} */ /** @type {string} */
static DIRECTORY = 'characters'; static DIRECTORY = 'characters';
@@ -47,9 +53,9 @@ class DiskCache {
/** /**
* Queue for removal of cache entries. * Queue for removal of cache entries.
* @type {Set<string>} * @type {CacheRemovalQueueItem[]}
*/ */
removalQueue = new Set(); removalQueue = [];
/** /**
* Processes the removal queue. * Processes the removal queue.
@@ -57,22 +63,43 @@ class DiskCache {
*/ */
async #removeCacheEntries() { async #removeCacheEntries() {
try { try {
if (!useDiskCache || this.removalQueue.size === 0) { if (!useDiskCache || this.removalQueue.length === 0) {
return; return;
} }
const keys = await this.instance().then(i => i.keys()); /** @type {Map<string, number>} */
for (const item of this.removalQueue) { const latestTimestamps = new Map();
const key = keys.find(k => k.startsWith(item)); for (const { item, timestamp } of this.removalQueue) {
if (key) { if (!latestTimestamps.has(item) || timestamp > (latestTimestamps.get(item) ?? 0)) {
await this.instance().then(i => i.removeItem(key)); latestTimestamps.set(item, timestamp);
}
}
this.removalQueue.length = 0;
const cache = await this.instance();
const keys = await cache.keys();
for (const [item, timestamp] of latestTimestamps.entries()) {
const itemKeys = keys.filter(k => k.startsWith(item));
if (!itemKeys.length) {
continue;
}
for (const key of itemKeys) {
const datumPath = cache.getDatumPath(key);
if (!fs.existsSync(datumPath)) {
continue;
}
const stat = fs.statSync(datumPath);
if (stat.mtimeMs > timestamp) {
continue;
}
await cache.removeItem(key);
} }
} }
this.removalQueue.clear();
} catch (error) { } catch (error) {
console.error('Error while removing cache entries:', error); console.error('Error while removing cache entries:', error);
} }
}; }
/** /**
* Gets the disk cache instance. * Gets the disk cache instance.
@@ -176,7 +203,7 @@ async function writeCharacterData(inputFile, data, outputFile, request, crop = u
} }
} }
if (useDiskCache && !Buffer.isBuffer(inputFile)) { if (useDiskCache && !Buffer.isBuffer(inputFile)) {
diskCache.removalQueue.add(inputFile); diskCache.removalQueue.push({ item: inputFile, timestamp: Date.now() });
} }
/** /**
* Read the image, resize, and save it as a PNG into the buffer. * Read the image, resize, and save it as a PNG into the buffer.