Add config.yaml value for cards cache capacity.
| @@ -1,6 +1,8 @@ | |||
| 1 | # -- DATA CONFIGURATION -- | 1 | # -- DATA CONFIGURATION -- |
| 2 | # Root directory for user data storage | 2 | # Root directory for user data storage |
| 3 | dataRoot: ./data | 3 | dataRoot: ./data |
| 4 | # The maximum amount of memory that parsed character cards can use in MB | ||
| 5 | cardsCacheCapacity: 100 | ||
| 4 | # -- SERVER CONFIGURATION -- | 6 | # -- SERVER CONFIGURATION -- |
| 5 | # Listen for incoming connections | 7 | # Listen for incoming connections |
| 6 | listen: false | 8 | listen: false |
| @@ -14,7 +14,7 @@ import jimp from 'jimp'; | |||
| 14 | 14 | ||
| 15 | import { AVATAR_WIDTH, AVATAR_HEIGHT } from '../constants.js'; | 15 | import { AVATAR_WIDTH, AVATAR_HEIGHT } from '../constants.js'; |
| 16 | import { jsonParser, urlencodedParser } from '../express-common.js'; | 16 | import { jsonParser, urlencodedParser } from '../express-common.js'; |
| 17 | import { deepMerge, humanizedISO8601DateTime, tryParse, extractFileFromZipBuffer, MemoryLimitedMap } from '../util.js'; | 17 | import { deepMerge, humanizedISO8601DateTime, tryParse, extractFileFromZipBuffer, MemoryLimitedMap, getConfigValue } from '../util.js'; |
| 18 | import { TavernCardValidator } from '../validator/TavernCardValidator.js'; | 18 | import { TavernCardValidator } from '../validator/TavernCardValidator.js'; |
| 19 | import { parse, write } from '../character-card-parser.js'; | 19 | import { parse, write } from '../character-card-parser.js'; |
| 20 | import { readWorldInfoFile } from './worldinfo.js'; | 20 | import { readWorldInfoFile } from './worldinfo.js'; |
| @@ -23,8 +23,9 @@ import { importRisuSprites } from './sprites.js'; | |||
| 23 | const defaultAvatarPath = './public/img/ai4.png'; | 23 | const defaultAvatarPath = './public/img/ai4.png'; |
| 24 | 24 | ||
| 25 | // KV-store for parsed character data | 25 | // KV-store for parsed character data |
| 26 | // 100 MB limit. Would take roughly 3000 characters to reach this limit | 26 | const cacheCapacity = Number(getConfigValue('cardsCacheCapacity', 100)); // MB |
| 27 | const characterDataCache = new MemoryLimitedMap(1024 * 1024 * 100); | 27 | // With 100 MB limit it would take roughly 3000 characters to reach this limit |
| 28 | const characterDataCache = new MemoryLimitedMap(1024 * 1024 * cacheCapacity); | ||
| 28 | // Some Android devices require tighter memory management | 29 | // Some Android devices require tighter memory management |
| 29 | const isAndroid = process.platform === 'android'; | 30 | const isAndroid = process.platform === 'android'; |
| 30 | 31 | ||
| @@ -680,8 +680,9 @@ export class MemoryLimitedMap { | |||
| 680 | * @param {number} maxMemoryInBytes - The maximum allowed memory in bytes for string values. | 680 | * @param {number} maxMemoryInBytes - The maximum allowed memory in bytes for string values. |
| 681 | */ | 681 | */ |
| 682 | constructor(maxMemoryInBytes) { | 682 | constructor(maxMemoryInBytes) { |
| 683 | if (typeof maxMemoryInBytes !== 'number' || maxMemoryInBytes <= 0) { | 683 | if (typeof maxMemoryInBytes !== 'number' || maxMemoryInBytes <= 0 || isNaN(maxMemoryInBytes)) { |
| 684 | throw new Error('maxMemoryInBytes must be a positive number'); | 684 | console.warn('Invalid maxMemoryInBytes, using a fallback value of 1 GB.'); |
| 685 | maxMemoryInBytes = 1024 * 1024 * 1024; // 1 GB | ||
| 685 | } | 686 | } |
| 686 | this.maxMemory = maxMemoryInBytes; | 687 | this.maxMemory = maxMemoryInBytes; |
| 687 | this.currentMemory = 0; | 688 | this.currentMemory = 0; |