|
|
import { FileCache } from '@/hooks/use-cached-file'; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export function initializeCacheSystem() { |
|
|
|
|
|
const CLEANUP_INTERVAL = 5 * 60 * 1000; |
|
|
|
|
|
|
|
|
const DEFAULT_EXPIRATION = 30 * 60 * 1000; |
|
|
|
|
|
|
|
|
let cleanupInterval: NodeJS.Timeout | null = null; |
|
|
|
|
|
|
|
|
const cleanupCache = () => { |
|
|
const now = Date.now(); |
|
|
let blobUrlsToRevoke: string[] = []; |
|
|
|
|
|
|
|
|
|
|
|
const cache = (FileCache as any).cache; |
|
|
|
|
|
if (cache && typeof cache.forEach === 'function') { |
|
|
const keysToDelete: string[] = []; |
|
|
|
|
|
cache.forEach((entry: any, key: string) => { |
|
|
|
|
|
if (now - entry.timestamp > DEFAULT_EXPIRATION) { |
|
|
keysToDelete.push(key); |
|
|
|
|
|
|
|
|
if (entry.type === 'url' && typeof entry.content === 'string' && entry.content.startsWith('blob:')) { |
|
|
blobUrlsToRevoke.push(entry.content); |
|
|
} |
|
|
} |
|
|
}); |
|
|
|
|
|
|
|
|
keysToDelete.forEach(key => { |
|
|
FileCache.delete(key); |
|
|
}); |
|
|
|
|
|
|
|
|
blobUrlsToRevoke.forEach(url => { |
|
|
try { |
|
|
URL.revokeObjectURL(url); |
|
|
} catch (err) { |
|
|
console.error(`Failed to revoke blob URL: ${url}`, err); |
|
|
} |
|
|
}); |
|
|
|
|
|
if (keysToDelete.length > 0) { |
|
|
console.log(`Cache cleanup: removed ${keysToDelete.length} expired entries`); |
|
|
} |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
const handleVisibilityChange = () => { |
|
|
if (document.visibilityState === 'visible') { |
|
|
|
|
|
cleanupCache(); |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
const handleBeforeUnload = () => { |
|
|
|
|
|
const cache = (FileCache as any).cache; |
|
|
|
|
|
if (cache && typeof cache.forEach === 'function') { |
|
|
cache.forEach((entry: any) => { |
|
|
if (entry.type === 'url' && typeof entry.content === 'string' && entry.content.startsWith('blob:')) { |
|
|
try { |
|
|
URL.revokeObjectURL(entry.content); |
|
|
} catch (err) { |
|
|
|
|
|
} |
|
|
} |
|
|
}); |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
const startCleanupInterval = () => { |
|
|
|
|
|
if (cleanupInterval) { |
|
|
clearInterval(cleanupInterval); |
|
|
} |
|
|
|
|
|
|
|
|
cleanupInterval = setInterval(cleanupCache, CLEANUP_INTERVAL); |
|
|
}; |
|
|
|
|
|
|
|
|
const initEventListeners = () => { |
|
|
document.addEventListener('visibilitychange', handleVisibilityChange); |
|
|
window.addEventListener('beforeunload', handleBeforeUnload); |
|
|
}; |
|
|
|
|
|
|
|
|
const removeEventListeners = () => { |
|
|
document.removeEventListener('visibilitychange', handleVisibilityChange); |
|
|
window.removeEventListener('beforeunload', handleBeforeUnload); |
|
|
|
|
|
if (cleanupInterval) { |
|
|
clearInterval(cleanupInterval); |
|
|
cleanupInterval = null; |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
startCleanupInterval(); |
|
|
initEventListeners(); |
|
|
|
|
|
|
|
|
return { |
|
|
stopCacheSystem: removeEventListeners, |
|
|
clearCache: () => { |
|
|
|
|
|
const cache = (FileCache as any).cache; |
|
|
if (cache && typeof cache.forEach === 'function') { |
|
|
cache.forEach((entry: any) => { |
|
|
if (entry.type === 'url' && typeof entry.content === 'string' && entry.content.startsWith('blob:')) { |
|
|
try { |
|
|
URL.revokeObjectURL(entry.content); |
|
|
} catch (err) { |
|
|
console.error('Failed to revoke URL during cache clear', err); |
|
|
} |
|
|
} |
|
|
}); |
|
|
} |
|
|
|
|
|
|
|
|
FileCache.clear(); |
|
|
} |
|
|
}; |
|
|
} |