UNPKG

@jay-js/system

Version:

A powerful and flexible TypeScript library for UI, state management, lazy loading, routing and managing draggable elements in modern web applications.

151 lines 4.95 kB
import { addConfigChangeListener, lazyOptions, moduleCache, removeConfigChangeListener, } from "../core/configuration.js"; /** * Singleton class responsible for managing the lifecycle of lazy-loaded modules. * Implements garbage collection and idle detection to optimize memory usage. * * Features: * - Automatic garbage collection of unused modules * - Idle detection to pause collection when app is inactive * - Dynamic configuration through lazyOptions */ class ModuleCollector { constructor() { this.collectorInterval = null; this.idleTime = 0; this.idleOptions = { passive: true, capture: true, }; this.setupEventListeners(); this.startCollector(); this.setupIdleMonitor(); addConfigChangeListener(this.handleConfigChange.bind(this)); } /** * Returns the singleton instance of ModuleCollector. * Creates a new instance if one doesn't exist. * * @returns {ModuleCollector} The singleton collector instance */ static getInstance() { if (!ModuleCollector.instance) { ModuleCollector.instance = new ModuleCollector(); } return ModuleCollector.instance; } /** * Handles changes in lazy loading configuration. * Restarts the collector with new settings if running. * * @param {TLazyOptions} options - New configuration options * @private */ handleConfigChange(_options) { if (this.collectorInterval) { clearInterval(this.collectorInterval); this.startCollector(); } } /** * Sets up event listeners for mousemove and keypress events * to detect user activity. * * @private */ setupEventListeners() { window.addEventListener("mousemove", this.resetIdle.bind(this), this.idleOptions); window.addEventListener("keypress", this.resetIdle.bind(this), this.idleOptions); } /** * Resets the idle timer and restarts collection if stopped. * Called when user activity is detected. * * @private */ resetIdle() { this.idleTime = 0; if (!this.collectorInterval) { this.startCollector(); } } /** * Starts the garbage collection interval. * Uses gcInterval from lazyOptions for timing. * * @private */ startCollector() { this.collectorInterval = setInterval(this.runCollector.bind(this), lazyOptions.gcInterval || 60000); } /** * Runs a garbage collection cycle. * - Increments usage counters for all modules * - Removes modules that exceed gcThreshold * - Manages collection pausing during idle periods * * @private */ runCollector() { const toRemove = []; const gcThreshold = lazyOptions.gcThreshold ? lazyOptions.gcThreshold / 60000 : 5; for (const [key, module] of moduleCache) { if (module.lastUsed > gcThreshold && module.collect) { toRemove.push({ key, module }); } else { module.lastUsed++; } } for (const { key, module } of toRemove) { moduleCache.delete(key); module.lastUsed = 0; module.collect = false; } if (toRemove.length > 0) { console.log("Garbage collector removed modules:", toRemove.map((item) => item.key)); } this.idleTime++; if (this.idleTime > 6) { if (this.collectorInterval) { clearInterval(this.collectorInterval); this.collectorInterval = null; } for (const [_, module] of moduleCache) { module.lastUsed = 0; } } } /** * Sets up the idle monitoring interval. * Resets module usage counters during extended idle periods. * * @private */ setupIdleMonitor() { setInterval(() => { this.idleTime++; if (this.idleTime > 3) { for (const [_, module] of moduleCache) { module.lastUsed = 0; } } }, 60000); } /** * Disposes of the collector instance. * Cleans up event listeners and intervals. */ dispose() { if (this.collectorInterval) { clearInterval(this.collectorInterval); this.collectorInterval = null; } window.removeEventListener("mousemove", this.resetIdle.bind(this), this.idleOptions); window.removeEventListener("keypress", this.resetIdle.bind(this), this.idleOptions); removeConfigChangeListener(this.handleConfigChange.bind(this)); ModuleCollector.instance = null; } } ModuleCollector.instance = null; export const moduleCollector = ModuleCollector.getInstance(); //# sourceMappingURL=collector.js.map