Proper caching for loaded WI - Implement StructurecCloneMap, which is a map that provides structured clones on both get and set - Don't delete WI cache on save, but update the cache - Ensure that cache is updated immediately, so any future get will load the new saved data already - Still be consistent with clones, so requested cache data that wasn't saved isn't taken into account
| @@ -0,0 +1,36 @@ | ||
| 1 | +/** | |
| 2 | + * A specialized Map class that provides consistent data storage by performing deep cloning of values. | |
| 3 | + * | |
| 4 | + * @template K, V | |
| 5 | + * @extends Map<K, V> | |
| 6 | + */ | |
| 7 | +export class StructuredCloneMap extends Map { | |
| 8 | + /** | |
| 9 | + * Adds a new element with a specified key and value to the Map. If an element with the same key already exists, the element will be updated. | |
| 10 | + * | |
| 11 | + * The set value will always be a deep clone of the provided value to provide consistent data storage. | |
| 12 | + * | |
| 13 | + * @param {K} key - The key to set | |
| 14 | + * @param {V} value - The value to set | |
| 15 | + * @returns {this} The updated map | |
| 16 | + */ | |
| 17 | + set(key, value) { | |
| 18 | + const clonedValue = structuredClone(value); | |
| 19 | + super.set(key, clonedValue); | |
| 20 | + return this; | |
| 21 | + } | |
| 22 | + | |
| 23 | + /** | |
| 24 | + * Returns a specified element from the Map object. | |
| 25 | + * If the value that is associated to the provided key is an object, then you will get a reference to that object and any change made to that object will effectively modify it inside the Map. | |
| 26 | + * | |
| 27 | + * The returned value will always be a deep clone of the cached value. | |
| 28 | + * | |
| 29 | + * @param {K} key - The key to get the value for | |
| 30 | + * @returns {V | undefined} Returns the element associated with the specified key. If no element is associated with the specified key, undefined is returned. | |
| 31 | + */ | |
| 32 | + get(key) { | |
| 33 | + const value = super.get(key); | |
| 34 | + return structuredClone(value); | |
| 35 | + } | |
| 36 | +} | |
| @@ -16,6 +16,7 @@ import { SlashCommandEnumValue, enumTypes } from './slash-commands/SlashCommandE | ||
| 16 | 16 | import { commonEnumProviders, enumIcons } from './slash-commands/SlashCommandCommonEnumsProvider.js'; |
| 17 | 17 | import { SlashCommandClosure } from './slash-commands/SlashCommandClosure.js'; |
| 18 | 18 | import { callGenericPopup, Popup, POPUP_TYPE } from './popup.js'; |
| 19 | +import { StructuredCloneMap } from './util/StructuredCloneMap.js'; | |
| 19 | 20 | |
| 20 | 21 | export { |
| 21 | 22 | world_info, |
| @@ -746,7 +747,8 @@ export const wi_anchor_position = { | ||
| 746 | 747 | after: 1, |
| 747 | 748 | }; |
| 748 | 749 | |
| 749 | -const worldInfoCache = new Map(); | |
| 750 | +/** @type {StructuredCloneMap<string,object>} */ | |
| 751 | +const worldInfoCache = new StructuredCloneMap(); | |
| 750 | 752 | |
| 751 | 753 | /** |
| 752 | 754 | * Gets the world info based on chat messages. |
| @@ -3280,7 +3282,8 @@ async function saveWorldInfo(name, data, immediately) { | ||
| 3280 | 3282 | return; |
| 3281 | 3283 | } |
| 3282 | 3284 | |
| 3283 | - worldInfoCache.delete(name); | |
| 3285 | + // Update cache immediately, so any future call can pull from this | |
| 3286 | + worldInfoCache.set(name, structuredClone(data)); | |
| 3284 | 3287 | |
| 3285 | 3288 | if (immediately) { |
| 3286 | 3289 | return await _save(name, data); |