mirror of
https://github.com/apache/superset.git
synced 2026-04-18 23:55:00 +00:00
feat: a simple LRUCache in frontend (#20842)
This commit is contained in:
@@ -26,6 +26,7 @@ export { default as makeSingleton } from './makeSingleton';
|
||||
export { default as promiseTimeout } from './promiseTimeout';
|
||||
export { default as logging } from './logging';
|
||||
export { default as removeDuplicates } from './removeDuplicates';
|
||||
export { lruCache } from './lruCache';
|
||||
export * from './featureFlags';
|
||||
export * from './random';
|
||||
export * from './typedMemo';
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
class LRUCache<T> {
|
||||
private cache: Map<string, T>;
|
||||
|
||||
readonly capacity: number;
|
||||
|
||||
constructor(capacity: number) {
|
||||
if (capacity < 1) {
|
||||
throw new Error('The capacity in LRU must be greater than 0.');
|
||||
}
|
||||
this.capacity = capacity;
|
||||
this.cache = new Map<string, T>();
|
||||
}
|
||||
|
||||
public has(key: string): boolean {
|
||||
return this.cache.has(key);
|
||||
}
|
||||
|
||||
public get(key: string): T | undefined {
|
||||
// Prevent runtime errors
|
||||
if (typeof key !== 'string') {
|
||||
throw new TypeError('The LRUCache key must be string.');
|
||||
}
|
||||
|
||||
if (this.cache.has(key)) {
|
||||
const tmp = this.cache.get(key) as T;
|
||||
this.cache.delete(key);
|
||||
this.cache.set(key, tmp);
|
||||
return tmp;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
public set(key: string, value: T) {
|
||||
// Prevent runtime errors
|
||||
if (typeof key !== 'string') {
|
||||
throw new TypeError('The LRUCache key must be string.');
|
||||
}
|
||||
if (this.cache.size >= this.capacity) {
|
||||
this.cache.delete(this.cache.keys().next().value);
|
||||
}
|
||||
this.cache.set(key, value);
|
||||
}
|
||||
|
||||
public clear() {
|
||||
this.cache.clear();
|
||||
}
|
||||
|
||||
public get size() {
|
||||
return this.cache.size;
|
||||
}
|
||||
}
|
||||
|
||||
export function lruCache<T>(capacity = 100) {
|
||||
return new LRUCache<T>(capacity);
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { lruCache } from '@superset-ui/core';
|
||||
|
||||
test('initial LRU', () => {
|
||||
expect(lruCache().capacity).toBe(100);
|
||||
expect(lruCache(10).capacity).toBe(10);
|
||||
expect(lruCache(10).size).toBe(0);
|
||||
expect(() => lruCache(0)).toThrow(Error);
|
||||
});
|
||||
|
||||
test('LRU operations', () => {
|
||||
const cache = lruCache<string>(3);
|
||||
cache.set('1', 'a');
|
||||
cache.set('2', 'b');
|
||||
cache.set('3', 'c');
|
||||
cache.set('4', 'd');
|
||||
expect(cache.size).toBe(3);
|
||||
expect(cache.has('1')).toBeFalsy();
|
||||
expect(cache.get('1')).toBeUndefined();
|
||||
cache.get('2');
|
||||
cache.set('5', 'e');
|
||||
expect(cache.has('2')).toBeTruthy();
|
||||
expect(cache.has('3')).toBeFalsy();
|
||||
// @ts-expect-error
|
||||
expect(() => cache.set(0)).toThrow(TypeError);
|
||||
// @ts-expect-error
|
||||
expect(() => cache.get(0)).toThrow(TypeError);
|
||||
expect(cache.size).toBe(3);
|
||||
cache.clear();
|
||||
expect(cache.size).toBe(0);
|
||||
expect(cache.capacity).toBe(3);
|
||||
});
|
||||
|
||||
test('LRU handle null and undefined', () => {
|
||||
const cache = lruCache();
|
||||
cache.set('a', null);
|
||||
cache.set('b', undefined);
|
||||
expect(cache.has('a')).toBeTruthy();
|
||||
expect(cache.has('b')).toBeTruthy();
|
||||
expect(cache.get('a')).toBeNull();
|
||||
expect(cache.get('b')).toBeUndefined();
|
||||
});
|
||||
Reference in New Issue
Block a user