diff --git a/src/renderer/src/data/CacheService.ts b/src/renderer/src/data/CacheService.ts index f88432ee10..b3324415a1 100644 --- a/src/renderer/src/data/CacheService.ts +++ b/src/renderer/src/data/CacheService.ts @@ -56,8 +56,8 @@ export class CacheService { private sharedCache = new Map() // Cross-window cache (local copy) private persistCache = new Map() // Persistent cache - // Hook reference tracking - private activeHooks = new Set() + // Hook reference tracking (reference-counted) + private activeHookCounts = new Map() // Subscription management private subscribers = new Map>() @@ -346,7 +346,7 @@ export class CacheService { */ private deleteInternal(key: string): boolean { // Check if key is being used by hooks - if (this.activeHooks.has(key)) { + if (this.activeHookCounts.get(key)) { logger.error(`Cannot delete key "${key}" as it's being used by useCache hook`) return false } @@ -574,7 +574,7 @@ export class CacheService { */ private deleteSharedInternal(key: string): boolean { // Check if key is being used by hooks - if (this.activeHooks.has(key)) { + if (this.activeHookCounts.get(key)) { logger.error(`Cannot delete key "${key}" as it's being used by useSharedCache hook`) return false } @@ -666,7 +666,8 @@ export class CacheService { * @param key - Cache key being used by the hook */ registerHook(key: string): void { - this.activeHooks.add(key) + const currentCount = this.activeHookCounts.get(key) ?? 0 + this.activeHookCounts.set(key, currentCount + 1) } /** @@ -674,7 +675,17 @@ export class CacheService { * @param key - Cache key no longer being used by the hook */ unregisterHook(key: string): void { - this.activeHooks.delete(key) + const currentCount = this.activeHookCounts.get(key) + if (!currentCount) { + return + } + + if (currentCount === 1) { + this.activeHookCounts.delete(key) + return + } + + this.activeHookCounts.set(key, currentCount - 1) } // ============ Shared Cache Ready State Management ============ @@ -998,7 +1009,7 @@ export class CacheService { this.persistCache.clear() // Clear tracking - this.activeHooks.clear() + this.activeHookCounts.clear() this.subscribers.clear() logger.debug('CacheService cleanup completed') diff --git a/tests/__mocks__/renderer/CacheService.ts b/tests/__mocks__/renderer/CacheService.ts index 69f41f8689..6f8a142f14 100644 --- a/tests/__mocks__/renderer/CacheService.ts +++ b/tests/__mocks__/renderer/CacheService.ts @@ -32,7 +32,7 @@ export const createMockCacheService = ( const persistCache = new Map(options.initialPersistCache || []) // Active hooks tracking - const activeHooks = new Set() + const activeHookCounts = new Map() // Mock subscribers const subscribers = new Map>() @@ -102,7 +102,7 @@ export const createMockCacheService = ( }), delete: vi.fn((key: K): boolean => { - if (activeHooks.has(key)) { + if (activeHookCounts.get(key)) { console.error(`Cannot delete key "${key}" as it's being used by useCache hook`) return false } @@ -157,7 +157,7 @@ export const createMockCacheService = ( }), deleteCasual: vi.fn((key: string): boolean => { - if (activeHooks.has(key)) { + if (activeHookCounts.get(key)) { console.error(`Cannot delete key "${key}" as it's being used by useCache hook`) return false } @@ -212,7 +212,7 @@ export const createMockCacheService = ( }), deleteShared: vi.fn((key: K): boolean => { - if (activeHooks.has(key)) { + if (activeHookCounts.get(key)) { console.error(`Cannot delete key "${key}" as it's being used by useSharedCache hook`) return false } @@ -267,7 +267,7 @@ export const createMockCacheService = ( }), deleteSharedCasual: vi.fn((key: string): boolean => { - if (activeHooks.has(key)) { + if (activeHookCounts.get(key)) { console.error(`Cannot delete key "${key}" as it's being used by useSharedCache hook`) return false } @@ -305,11 +305,20 @@ export const createMockCacheService = ( // ============ Hook Reference Management ============ registerHook: vi.fn((key: string): void => { - activeHooks.add(key) + const currentCount = activeHookCounts.get(key) ?? 0 + activeHookCounts.set(key, currentCount + 1) }), unregisterHook: vi.fn((key: string): void => { - activeHooks.delete(key) + const currentCount = activeHookCounts.get(key) + if (!currentCount) { + return + } + if (currentCount === 1) { + activeHookCounts.delete(key) + return + } + activeHookCounts.set(key, currentCount - 1) }), // ============ Shared Cache Ready State ============ @@ -362,7 +371,7 @@ export const createMockCacheService = ( memoryCache.clear() sharedCache.clear() persistCache.clear() - activeHooks.clear() + activeHookCounts.clear() subscribers.clear() }), @@ -372,7 +381,7 @@ export const createMockCacheService = ( memoryCache: new Map(memoryCache), sharedCache: new Map(sharedCache), persistCache: new Map(persistCache), - activeHooks: new Set(activeHooks), + activeHookCounts: new Map(activeHookCounts), subscribers: new Map(subscribers), sharedCacheReady }), @@ -381,7 +390,7 @@ export const createMockCacheService = ( memoryCache.clear() sharedCache.clear() persistCache.clear() - activeHooks.clear() + activeHookCounts.clear() subscribers.clear() sharedCacheReady = true },