fix globalsearch perf issue

This commit is contained in:
pa
2026-03-14 01:01:05 +09:00
parent 1f5acd546d
commit 45f3eacf21

View File

@@ -1,4 +1,4 @@
import { ref, watch, computed } from 'vue'; import { computed, effectScope, ref, watch } from 'vue';
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import { useAvatarStore } from './avatar'; import { useAvatarStore } from './avatar';
import { useFavoriteStore } from './favorite'; import { useFavoriteStore } from './favorite';
@@ -27,6 +27,7 @@ export const useGlobalSearchStore = defineStore('GlobalSearch', () => {
// Worker instance (lazy) // Worker instance (lazy)
let worker = null; let worker = null;
let indexUpdateTimer = null; let indexUpdateTimer = null;
let indexWatchScope = null;
function getWorker() { function getWorker() {
if (!worker) { if (!worker) {
@@ -36,6 +37,12 @@ export const useGlobalSearchStore = defineStore('GlobalSearch', () => {
return worker; return worker;
} }
function disposeWorker() {
if (!worker) return;
worker.terminate();
worker = null;
}
// Search results (updated from worker messages) // Search results (updated from worker messages)
const friendResults = ref([]); const friendResults = ref([]);
const ownAvatarResults = ref([]); const ownAvatarResults = ref([]);
@@ -58,18 +65,13 @@ export const useGlobalSearchStore = defineStore('GlobalSearch', () => {
const currentUserId = computed(() => userStore.currentUser?.id); const currentUserId = computed(() => userStore.currentUser?.id);
watch(isOpen, (open) => {
if (!open) {
query.value = '';
clearResults();
}
});
// Send index update to worker when data changes // Send index update to worker when data changes
function scheduleIndexUpdate() { function scheduleIndexUpdate() {
if (!isOpen.value) return;
if (indexUpdateTimer) clearTimeout(indexUpdateTimer); if (indexUpdateTimer) clearTimeout(indexUpdateTimer);
indexUpdateTimer = setTimeout(() => { indexUpdateTimer = setTimeout(() => {
indexUpdateTimer = null; indexUpdateTimer = null;
if (!isOpen.value) return;
sendIndexUpdate(); sendIndexUpdate();
}, 200); }, 200);
} }
@@ -148,41 +150,59 @@ export const useGlobalSearchStore = defineStore('GlobalSearch', () => {
}); });
} }
watch( function stopIndexWatchers() {
() => friendStore.friends, if (indexUpdateTimer) {
() => scheduleIndexUpdate(), clearTimeout(indexUpdateTimer);
{ deep: true } indexUpdateTimer = null;
); }
if (indexWatchScope) {
indexWatchScope.stop();
indexWatchScope = null;
}
}
watch( function startIndexWatchers() {
() => avatarStore.cachedAvatars, if (indexWatchScope) return;
() => scheduleIndexUpdate(),
{ deep: true }
);
watch( indexWatchScope = effectScope();
() => worldStore.cachedWorlds, indexWatchScope.run(() => {
() => scheduleIndexUpdate(), watch(
{ deep: true } () => friendStore.friends,
); () => scheduleIndexUpdate(),
{ deep: true }
);
watch( watch(
() => groupStore.currentUserGroups, () => avatarStore.cachedAvatars,
() => scheduleIndexUpdate(), () => scheduleIndexUpdate(),
{ deep: true } { deep: true }
); );
watch( watch(
() => favoriteStore.favoriteAvatars, () => worldStore.cachedWorlds,
() => scheduleIndexUpdate(), () => scheduleIndexUpdate(),
{ deep: true } { deep: true }
); );
watch( watch(
() => favoriteStore.favoriteWorlds, () => groupStore.currentUserGroups,
() => scheduleIndexUpdate(), () => scheduleIndexUpdate(),
{ deep: true } { deep: true }
); );
watch(
() => favoriteStore.favoriteAvatars,
() => scheduleIndexUpdate(),
{ deep: true }
);
watch(
() => favoriteStore.favoriteWorlds,
() => scheduleIndexUpdate(),
{ deep: true }
);
});
}
let searchSeq = 0; let searchSeq = 0;
@@ -208,7 +228,25 @@ export const useGlobalSearchStore = defineStore('GlobalSearch', () => {
watch(query, dispatchSearch); watch(query, dispatchSearch);
watch(currentUserId, () => { watch(currentUserId, () => {
if (query.value && query.value.length >= 2) dispatchSearch(); if (query.value && query.value.length >= 2) {
dispatchSearch();
}
});
watch(isOpen, (open) => {
if (open) {
startIndexWatchers();
sendIndexUpdate();
if (query.value && query.value.length >= 2) {
dispatchSearch();
}
return;
}
query.value = '';
clearResults();
stopIndexWatchers();
disposeWorker();
}); });
function handleWorkerMessage(event) { function handleWorkerMessage(event) {
@@ -242,7 +280,6 @@ export const useGlobalSearchStore = defineStore('GlobalSearch', () => {
} }
function open() { function open() {
sendIndexUpdate();
isOpen.value = true; isOpen.value = true;
} }