@waboyz-baileys/shared
Version:
77 lines (76 loc) • 2.33 kB
JavaScript
import { debounce, throttle } from 'lodash-es';
export class PerKeyDebouncer {
constructor(callback, options) {
this.map = new Map();
this.callback = callback;
this.delay = options.delay;
this.expireAfter = options.expireAfter;
this.maxSize = options.maxSize ?? 100;
this.onExpire = options.onExpire;
}
push(key, data) {
if (!this.map.has(key) && this.map.size >= this.maxSize) {
const firstKey = this.map.keys().next().value;
if (firstKey)
this.cancel(firstKey);
}
const existing = this.map.get(key);
if (existing) {
existing.debouncedFn.cancel();
existing.throttledExpireFn?.cancel?.();
}
const debouncedFn = debounce(() => {
this.callback(key, data);
}, this.delay, { leading: true, trailing: false });
const entry = {
data,
debouncedFn,
};
if (this.expireAfter && this.onExpire) {
entry.throttledExpireFn = throttle(() => {
this.map.delete(key);
this.onExpire?.(key, data);
}, this.expireAfter, { trailing: true });
}
this.map.set(key, entry);
debouncedFn();
entry.throttledExpireFn?.();
}
get(key) {
return this.map.get(key)?.data;
}
has(key) {
return this.map.has(key);
}
cancel(key) {
const entry = this.map.get(key);
if (entry) {
entry.debouncedFn.cancel();
entry.throttledExpireFn?.cancel?.();
this.map.delete(key);
}
}
flush(key) {
const entry = this.map.get(key);
if (entry) {
entry.debouncedFn.flush();
entry.throttledExpireFn?.cancel?.();
this.map.delete(key);
this.onExpire?.(key, entry.data);
}
}
clear() {
for (const [key, entry] of this.map.entries()) {
entry.debouncedFn.cancel();
entry.throttledExpireFn?.cancel?.();
this.onExpire?.(key, entry.data);
}
this.map.clear();
}
size() {
return this.map.size;
}
entries() {
return Array.from(this.map.entries()).map(([key, val]) => [key, val.data]);
}
}