@v4fire/core
Version:
V4Fire core library
127 lines (102 loc) • 2.46 kB
text/typescript
/*!
* V4Fire Core
* https://github.com/V4Fire/Core
*
* Released under the MIT license
* https://github.com/V4Fire/Core/blob/master/LICENSE
*/
/**
* [[include:core/cache/restricted/README.md]]
* @packageDocumentation
*/
import SimpleCache, { ClearFilter } from 'core/cache/simple';
export * from 'core/cache/simple';
/**
* Implementation for an in-memory data structure with support for limiting of values in the cache
*
* @typeparam V - value type
* @typeparam K - key type (`string` by default)
*/
export default class RestrictedCache<V = unknown, K = string> extends SimpleCache<V, K> {
/**
* Queue object
*/
protected readonly queue: Set<K> = new Set();
/**
* Number of maximum records in the cache
*/
protected capacity: number = 20;
/**
* @override
* @param [max] - number of maximum records in the cache
*/
constructor(max?: number) {
super();
if (max != null) {
this.setCapacity(max);
}
}
override get(key: K): CanUndef<V> {
if (this.has(key)) {
this.queue.delete(key);
this.queue.add(key);
}
return super.get(key);
}
override set(key: K, value: V): V {
this.queue.delete(key);
if (this.queue.size === this.capacity) {
const
key = this.queue.values().next().value;
if (key !== undefined) {
this.remove(key);
}
}
this.queue.add(key);
return super.set(key, value);
}
override remove(key: K): CanUndef<V> {
if (this.has(key)) {
this.queue.delete(key);
return super.remove(key);
}
}
override clear(filter?: ClearFilter<V, K>): Map<K, V> {
const
removed = super.clear(filter);
for (let o = this.queue.values(), i = o.next(); !i.done; i = o.next()) {
const
el = i.value;
if (removed.has(el)) {
this.queue.delete(el);
}
}
return removed;
}
/**
* Sets a new capacity of the cache.
* The method returns a map of truncated elements that the cache can't fit anymore.
*
* @param value
*/
setCapacity(value: number): Map<K, V> {
if (!Number.isInteger(value) || value < 0) {
throw new TypeError('A value of `max` can be defined only as a non-negative integer number');
}
const
removed = new Map<K, V>(),
amount = value - this.capacity;
this.capacity = value;
if (amount < 0) {
while (this.capacity < this.queue.size) {
const
key = this.queue.values().next().value,
el = this.remove(key);
if (el) {
removed.set(key, el);
}
}
}
return removed;
}
}