Files
Bjorn/web/js/core/resource-tracker.js
Fabien POLLY eb20b168a6 Add RLUtils class for managing RL/AI dashboard endpoints
- Implemented methods for fetching AI stats, training history, and recent experiences.
- Added functionality to set operation mode (MANUAL, AUTO, AI) with appropriate handling.
- Included helper methods for querying the database and sending JSON responses.
- Integrated model metadata extraction for visualization purposes.
2026-02-18 22:36:10 +01:00

104 lines
2.6 KiB
JavaScript

/**
* ResourceTracker — tracks intervals, timeouts, listeners, AbortControllers.
* Each page module gets one tracker; calling cleanupAll() on unmount
* guarantees zero leaked resources.
*/
export class ResourceTracker {
constructor(label = 'anon') {
this._label = label;
this._intervals = new Set();
this._timeouts = new Set();
this._listeners = []; // {target, event, handler, options}
this._abortControllers = new Set();
}
/* -- Intervals -- */
trackInterval(fn, ms) {
const id = setInterval(fn, ms);
this._intervals.add(id);
return id;
}
clearTrackedInterval(id) {
clearInterval(id);
this._intervals.delete(id);
}
/* -- Timeouts -- */
trackTimeout(fn, ms) {
const id = setTimeout(() => {
this._timeouts.delete(id);
fn();
}, ms);
this._timeouts.add(id);
return id;
}
clearTrackedTimeout(id) {
clearTimeout(id);
this._timeouts.delete(id);
}
/* -- Event listeners -- */
trackEventListener(target, event, handler, options) {
target.addEventListener(event, handler, options);
this._listeners.push({ target, event, handler, options });
}
/* -- AbortControllers (for fetch) -- */
trackAbortController() {
const ac = new AbortController();
this._abortControllers.add(ac);
return ac;
}
removeAbortController(ac) {
this._abortControllers.delete(ac);
}
/* -- Cleanup everything -- */
cleanupAll() {
// Intervals
for (const id of this._intervals) clearInterval(id);
this._intervals.clear();
// Timeouts
for (const id of this._timeouts) clearTimeout(id);
this._timeouts.clear();
// Listeners & Generic cleanups
for (const item of this._listeners) {
if (item.cleanup) {
try { item.cleanup(); } catch (err) { console.warn(`[ResourceTracker:${this._label}] cleanup error`, err); }
} else if (item.target) {
item.target.removeEventListener(item.event, item.handler, item.options);
}
}
this._listeners.length = 0;
// Abort controllers
for (const ac of this._abortControllers) {
try { ac.abort(); } catch { /* already aborted */ }
}
this._abortControllers.clear();
}
/* -- Generic resources -- */
trackResource(fn) {
if (typeof fn === 'function') {
this._listeners.push({ cleanup: fn });
}
}
/* -- Diagnostics -- */
stats() {
return {
label: this._label,
intervals: this._intervals.size,
timeouts: this._timeouts.size,
listeners: this._listeners.length,
abortControllers: this._abortControllers.size
};
}
}