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 | import { commonEnumProviders, enumIcons } from './slash-commands/SlashCommandCommonEnumsProvider.js'; | 16 | import { commonEnumProviders, enumIcons } from './slash-commands/SlashCommandCommonEnumsProvider.js'; |
| 17 | import { SlashCommandClosure } from './slash-commands/SlashCommandClosure.js'; | 17 | import { SlashCommandClosure } from './slash-commands/SlashCommandClosure.js'; |
| 18 | import { callGenericPopup, Popup, POPUP_TYPE } from './popup.js'; | 18 | import { callGenericPopup, Popup, POPUP_TYPE } from './popup.js'; |
| 19 | import { StructuredCloneMap } from './util/StructuredCloneMap.js'; | ||
| 19 | 20 | ||
| 20 | export { | 21 | export { |
| 21 | world_info, | 22 | world_info, |
| @@ -746,7 +747,8 @@ export const wi_anchor_position = { | |||
| 746 | after: 1, | 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 | * Gets the world info based on chat messages. | 754 | * Gets the world info based on chat messages. |
| @@ -3280,7 +3282,8 @@ async function saveWorldInfo(name, data, immediately) { | |||
| 3280 | return; | 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 | if (immediately) { | 3288 | if (immediately) { |
| 3286 | return await _save(name, data); | 3289 | return await _save(name, data); |