Handle stale cache

2661881bc4c95f752786b35daa06af3cffe05e15

Joe <joenunezb@gmail.com>

1 files changed, +153 -51Showing whitespace changes
public/scripts/power-user.js+153 -51
@@ -330,12 +330,6 @@ const debug_functions = [];
330330
331const setHotswapsDebounced = debounce(favsToHotswap);331const setHotswapsDebounced = debounce(favsToHotswap);
332332
333const fuzzySearchCharactersCache = new Map();
334const fuzzySearchWorldInfoCache = new Map();
335const fuzzySearchPersonasCache = new Map();
336const fuzzySearchTagsCache = new Map();
337const fuzzySearchGroupsCache = new Map();
338
339function playMessageSound() {333function playMessageSound() {
340 if (!power_user.play_message_sound) {334 if (!power_user.play_message_sound) {
341 return;335 return;
@@ -1830,20 +1824,37 @@ async function loadContextSettings() {
1830 });1824 });
1831}1825}
18321826
1827// Create separate caches for each type of fuzzy search
1828const fuzzySearchCaches = {
1829 characters: { keyHash: null, resultMap: new Map() },
1830 worldInfo: { keyHash: null, resultMap: new Map() },
1831 personas: { keyHash: null, resultMap: new Map() },
1832 tags: { keyHash: null, resultMap: new Map() },
1833 groups: { keyHash: null, resultMap: new Map() },
1834};
1835
1833/**1836/**
1834 * Fuzzy search characters by a search term1837 * Generates a hash of the Fuse configuration keys
1835 * @param {string} searchValue - The search term1838 * @param {Array<{name: string, weight: number, getFn?: Function}>} keys
1836 * @returns {import('fuse.js').FuseResult<any>[]} Results as items with their score1839 * @returns {number} Hash of the keys configuration
1837 */1840 */
1838export function fuzzySearchCharacters(searchValue) {1841function hashFuseKeys(keys) {
1842 // Convert keys to a stable string representation
1843 const keyString = keys.map(k => {
1844 const getFnString = k.getFn ? k.getFn.toString() : '';
1845 return `${k.name}:${k.weight}:${getFnString}`;
1846 }).join('|');
18391847
1840 if (fuzzySearchCharactersCache.has(searchValue)) {1848 return getStringHash(keyString);
1841 return fuzzySearchCharactersCache.get(searchValue);
1842}1849}
18431850
1844 // @ts-ignore1851/**
1845 const fuse = new Fuse(characters, {1852 * Fuzzy search characters by a search term with caching
1846 keys: [1853 * @param {string} searchValue - The search term
1854 * @returns {import('fuse.js').FuseResult<any>[]} Results as items with their score
1855 */
1856export function fuzzySearchCharacters(searchValue) {
1857 const fuseKeys = [
1847 { name: 'data.name', weight: 20 },1858 { name: 'data.name', weight: 20 },
1848 { name: '#tags', weight: 10, getFn: (character) => getTagsList(character.avatar).map(x => x.name).join('||') },1859 { name: '#tags', weight: 10, getFn: (character) => getTagsList(character.avatar).map(x => x.name).join('||') },
1849 { name: 'data.description', weight: 3 },1860 { name: 'data.description', weight: 3 },
@@ -1855,7 +1866,28 @@ export function fuzzySearchCharacters(searchValue) {
1855 { name: 'data.creator', weight: 1 },1866 { name: 'data.creator', weight: 1 },
1856 { name: 'data.tags', weight: 1 },1867 { name: 'data.tags', weight: 1 },
1857 { name: 'data.alternate_greetings', weight: 1 },1868 { name: 'data.alternate_greetings', weight: 1 },
1858 ],1869 ];
1870
1871 // Generate hash of current keys configuration
1872 const currentKeyHash = hashFuseKeys(fuseKeys);
1873 const cache = fuzzySearchCaches.characters;
1874
1875 // Check if we have a cached result for this search value
1876 if (cache.keyHash === currentKeyHash && cache.resultMap.has(searchValue)) {
1877 console.debug('Using cached fuzzy search results for ' + searchValue);
1878 return cache.resultMap.get(searchValue);
1879 }
1880
1881 // If key configuration changed, clear the cache
1882 if (cache.keyHash !== currentKeyHash) {
1883 console.debug('Fuse keys changed, clearing cache');
1884 cache.keyHash = currentKeyHash;
1885 cache.resultMap.clear();
1886 }
1887
1888 // Create new Fuse instance and perform search
1889 const fuse = new Fuse(characters, {
1890 keys: fuseKeys,
1859 includeScore: true,1891 includeScore: true,
1860 ignoreLocation: true,1892 ignoreLocation: true,
1861 useExtendedSearch: true,1893 useExtendedSearch: true,
@@ -1863,8 +1895,11 @@ export function fuzzySearchCharacters(searchValue) {
1863 });1895 });
18641896
1865 const results = fuse.search(searchValue);1897 const results = fuse.search(searchValue);
1898
1899 // Cache the results
1900 cache.resultMap.set(searchValue, results);
1901
1866 console.debug('Characters fuzzy search results for ' + searchValue, results);1902 console.debug('Characters fuzzy search results for ' + searchValue, results);
1867 fuzzySearchCharactersCache.set(searchValue, results);
1868 return results;1903 return results;
1869}1904}
18701905
@@ -1875,13 +1910,7 @@ export function fuzzySearchCharacters(searchValue) {
1875 * @returns {import('fuse.js').FuseResult<any>[]} Results as items with their score1910 * @returns {import('fuse.js').FuseResult<any>[]} Results as items with their score
1876 */1911 */
1877export function fuzzySearchWorldInfo(data, searchValue) {1912export function fuzzySearchWorldInfo(data, searchValue) {
1878 if (fuzzySearchWorldInfoCache.has(searchValue)) {1913 const fuseKeys = [
1879 return fuzzySearchWorldInfoCache.get(searchValue);
1880 }
1881
1882 // @ts-ignore
1883 const fuse = new Fuse(data, {
1884 keys: [
1885 { name: 'key', weight: 20 },1914 { name: 'key', weight: 20 },
1886 { name: 'group', weight: 15 },1915 { name: 'group', weight: 15 },
1887 { name: 'comment', weight: 10 },1916 { name: 'comment', weight: 10 },
@@ -1889,7 +1918,26 @@ export function fuzzySearchWorldInfo(data, searchValue) {
1889 { name: 'content', weight: 3 },1918 { name: 'content', weight: 3 },
1890 { name: 'uid', weight: 1 },1919 { name: 'uid', weight: 1 },
1891 { name: 'automationId', weight: 1 },1920 { name: 'automationId', weight: 1 },
1892 ],1921 ];
1922
1923 const currentKeyHash = hashFuseKeys(fuseKeys);
1924 const cache = fuzzySearchCaches.worldInfo;
1925
1926 // Check cache for existing results
1927 if (cache.keyHash === currentKeyHash && cache.resultMap.has(searchValue)) {
1928 console.debug('Using cached WI fuzzy search results for ' + searchValue);
1929 return cache.resultMap.get(searchValue);
1930 }
1931
1932 // Clear cache if keys changed
1933 if (cache.keyHash !== currentKeyHash) {
1934 console.debug('WI Fuse keys changed, clearing cache');
1935 cache.keyHash = currentKeyHash;
1936 cache.resultMap.clear();
1937 }
1938
1939 const fuse = new Fuse(data, {
1940 keys: fuseKeys,
1893 includeScore: true,1941 includeScore: true,
1894 ignoreLocation: true,1942 ignoreLocation: true,
1895 useExtendedSearch: true,1943 useExtendedSearch: true,
@@ -1897,8 +1945,9 @@ export function fuzzySearchWorldInfo(data, searchValue) {
1897 });1945 });
18981946
1899 const results = fuse.search(searchValue);1947 const results = fuse.search(searchValue);
1948 cache.resultMap.set(searchValue, results);
1949
1900 console.debug('World Info fuzzy search results for ' + searchValue, results);1950 console.debug('World Info fuzzy search results for ' + searchValue, results);
1901 fuzzySearchWorldInfoCache.set(searchValue, results);
1902 return results;1951 return results;
1903}1952}
19041953
@@ -1909,17 +1958,31 @@ export function fuzzySearchWorldInfo(data, searchValue) {
1909 * @returns {import('fuse.js').FuseResult<any>[]} Results as items with their score1958 * @returns {import('fuse.js').FuseResult<any>[]} Results as items with their score
1910 */1959 */
1911export function fuzzySearchPersonas(data, searchValue) {1960export function fuzzySearchPersonas(data, searchValue) {
1912 if (fuzzySearchPersonasCache.has(searchValue)) {
1913 return fuzzySearchPersonasCache.get(searchValue);
1914 }
1915
1916 data = data.map(x => ({ key: x, name: power_user.personas[x] ?? '', description: power_user.persona_descriptions[x]?.description ?? '' }));1961 data = data.map(x => ({ key: x, name: power_user.personas[x] ?? '', description: power_user.persona_descriptions[x]?.description ?? '' }));
1917 // @ts-ignore1962
1918 const fuse = new Fuse(data, {1963 const fuseKeys = [
1919 keys: [
1920 { name: 'name', weight: 20 },1964 { name: 'name', weight: 20 },
1921 { name: 'description', weight: 3 },1965 { name: 'description', weight: 3 },
1922 ],1966 ];
1967
1968 const currentKeyHash = hashFuseKeys(fuseKeys);
1969 const cache = fuzzySearchCaches.personas;
1970
1971 // Check cache for existing results
1972 if (cache.keyHash === currentKeyHash && cache.resultMap.has(searchValue)) {
1973 console.debug('Using cached personas fuzzy search results for ' + searchValue);
1974 return cache.resultMap.get(searchValue);
1975 }
1976
1977 // Clear cache if keys changed
1978 if (cache.keyHash !== currentKeyHash) {
1979 console.debug('Personas Fuse keys changed, clearing cache');
1980 cache.keyHash = currentKeyHash;
1981 cache.resultMap.clear();
1982 }
1983
1984 const fuse = new Fuse(data, {
1985 keys: fuseKeys,
1923 includeScore: true,1986 includeScore: true,
1924 ignoreLocation: true,1987 ignoreLocation: true,
1925 useExtendedSearch: true,1988 useExtendedSearch: true,
@@ -1927,8 +1990,9 @@ export function fuzzySearchPersonas(data, searchValue) {
1927 });1990 });
19281991
1929 const results = fuse.search(searchValue);1992 const results = fuse.search(searchValue);
1993 cache.resultMap.set(searchValue, results);
1994
1930 console.debug('Personas fuzzy search results for ' + searchValue, results);1995 console.debug('Personas fuzzy search results for ' + searchValue, results);
1931 fuzzySearchPersonasCache.set(searchValue, results);
1932 return results;1996 return results;
1933}1997}
19341998
@@ -1938,15 +2002,28 @@ export function fuzzySearchPersonas(data, searchValue) {
1938 * @returns {import('fuse.js').FuseResult<any>[]} Results as items with their score2002 * @returns {import('fuse.js').FuseResult<any>[]} Results as items with their score
1939 */2003 */
1940export function fuzzySearchTags(searchValue) {2004export function fuzzySearchTags(searchValue) {
1941 if (fuzzySearchTagsCache.has(searchValue)) {2005 const fuseKeys = [
1942 return fuzzySearchTagsCache.get(searchValue);2006 { name: 'name', weight: 1 },
2007 ];
2008
2009 const currentKeyHash = hashFuseKeys(fuseKeys);
2010 const cache = fuzzySearchCaches.tags;
2011
2012 // Check cache for existing results
2013 if (cache.keyHash === currentKeyHash && cache.resultMap.has(searchValue)) {
2014 console.debug('Using cached tags fuzzy search results for ' + searchValue);
2015 return cache.resultMap.get(searchValue);
2016 }
2017
2018 // Clear cache if keys changed
2019 if (cache.keyHash !== currentKeyHash) {
2020 console.debug('Tags Fuse keys changed, clearing cache');
2021 cache.keyHash = currentKeyHash;
2022 cache.resultMap.clear();
1943 }2023 }
19442024
1945 // @ts-ignore
1946 const fuse = new Fuse(tags, {2025 const fuse = new Fuse(tags, {
1947 keys: [2026 keys: fuseKeys,
1948 { name: 'name', weight: 1 },
1949 ],
1950 includeScore: true,2027 includeScore: true,
1951 ignoreLocation: true,2028 ignoreLocation: true,
1952 useExtendedSearch: true,2029 useExtendedSearch: true,
@@ -1954,8 +2031,9 @@ export function fuzzySearchTags(searchValue) {
1954 });2031 });
19552032
1956 const results = fuse.search(searchValue);2033 const results = fuse.search(searchValue);
2034 cache.resultMap.set(searchValue, results);
2035
1957 console.debug('Tags fuzzy search results for ' + searchValue, results);2036 console.debug('Tags fuzzy search results for ' + searchValue, results);
1958 fuzzySearchTagsCache.set(searchValue, results);
1959 return results;2037 return results;
1960}2038}
19612039
@@ -1965,18 +2043,31 @@ export function fuzzySearchTags(searchValue) {
1965 * @returns {import('fuse.js').FuseResult<any>[]} Results as items with their score2043 * @returns {import('fuse.js').FuseResult<any>[]} Results as items with their score
1966 */2044 */
1967export function fuzzySearchGroups(searchValue) {2045export function fuzzySearchGroups(searchValue) {
1968 if (fuzzySearchGroupsCache.has(searchValue)) {2046 const fuseKeys = [
1969 return fuzzySearchGroupsCache.get(searchValue);
1970 }
1971
1972 // @ts-ignore
1973 const fuse = new Fuse(groups, {
1974 keys: [
1975 { name: 'name', weight: 20 },2047 { name: 'name', weight: 20 },
1976 { name: 'members', weight: 15 },2048 { name: 'members', weight: 15 },
1977 { name: '#tags', weight: 10, getFn: (group) => getTagsList(group.id).map(x => x.name).join('||') },2049 { name: '#tags', weight: 10, getFn: (group) => getTagsList(group.id).map(x => x.name).join('||') },
1978 { name: 'id', weight: 1 },2050 { name: 'id', weight: 1 },
1979 ],2051 ];
2052
2053 const currentKeyHash = hashFuseKeys(fuseKeys);
2054 const cache = fuzzySearchCaches.groups;
2055
2056 // Check cache for existing results
2057 if (cache.keyHash === currentKeyHash && cache.resultMap.has(searchValue)) {
2058 console.debug('Using cached groups fuzzy search results for ' + searchValue);
2059 return cache.resultMap.get(searchValue);
2060 }
2061
2062 // Clear cache if keys changed
2063 if (cache.keyHash !== currentKeyHash) {
2064 console.debug('Groups Fuse keys changed, clearing cache');
2065 cache.keyHash = currentKeyHash;
2066 cache.resultMap.clear();
2067 }
2068
2069 const fuse = new Fuse(groups, {
2070 keys: fuseKeys,
1980 includeScore: true,2071 includeScore: true,
1981 ignoreLocation: true,2072 ignoreLocation: true,
1982 useExtendedSearch: true,2073 useExtendedSearch: true,
@@ -1984,12 +2075,23 @@ export function fuzzySearchGroups(searchValue) {
1984 });2075 });
19852076
1986 const results = fuse.search(searchValue);2077 const results = fuse.search(searchValue);
2078 cache.resultMap.set(searchValue, results);
2079
1987 console.debug('Groups fuzzy search results for ' + searchValue, results);2080 console.debug('Groups fuzzy search results for ' + searchValue, results);
1988 fuzzySearchGroupsCache.set(searchValue, results);
1989 return results;2081 return results;
1990}2082}
19912083
1992/**2084/**
2085 * Clears all fuzzy search caches
2086 */
2087export function clearFuzzySearchCaches() {
2088 for (const cache of Object.values(fuzzySearchCaches)) {
2089 cache.keyHash = null;
2090 cache.resultMap.clear();
2091 }
2092}
2093
2094/**
1993 * Renders a story string template with the given parameters.2095 * Renders a story string template with the given parameters.
1994 * @param {object} params Template parameters.2096 * @param {object} params Template parameters.
1995 * @returns {string} The rendered story string.2097 * @returns {string} The rendered story string.