diff --git a/src/util/collection.ts b/src/util/collection.ts index 23b2933ea..4689208bd 100644 --- a/src/util/collection.ts +++ b/src/util/collection.ts @@ -1,5 +1,38 @@ export class Collection extends Map { maxSize?: number; + private sweeper?: CollectionSweeper & { intervalId?: number }; + + constructor( + entries?: (readonly (readonly [K, V])[] | null) | Map, + options?: CollectionOptions, + ) { + super(entries ?? []); + + this.maxSize = options?.maxSize; + if (!options?.sweeper) return; + + this.startSweeper(options.sweeper); + } + + startSweeper(options: CollectionSweeper): number { + if (this.sweeper?.intervalId) clearInterval(this.sweeper.intervalId); + + this.sweeper = options; + this.sweeper.intervalId = setInterval(() => { + this.map(async (value, key) => { + if (!(await this.sweeper?.filter(value, key))) return; + + this.delete(key); + return key; + }); + }, options.interval); + + return this.sweeper.intervalId!; + } + + stopSweeper(): void { + return clearInterval(this.sweeper?.intervalId); + } set(key: K, value: V) { // When this collection is maxSizeed make sure we can add first @@ -87,3 +120,15 @@ export class Collection extends Map { return accumulator; } } + +interface CollectionOptions { + sweeper?: CollectionSweeper; + maxSize?: number; +} + +interface CollectionSweeper { + /** The filter to determine whether an element should be deleted or not */ + filter: ((value: V, key: K) => boolean | Promise); + /** The interval in which the sweeper should run */ + interval: number; +}