Path: blob/main/components/gitpod-protocol/src/util/garbage-collected-cache.ts
2500 views
/**1* Copyright (c) 2020 Gitpod GmbH. All rights reserved.2* Licensed under the GNU Affero General Public License (AGPL).3* See License.AGPL.txt in the project root for license information.4*/56import { repeat } from "./repeat";78interface CacheEntry<T> {9key: string;10value: T;11expiryDate: number;12}1314export class GarbageCollectedCache<T> {15protected readonly store = new Map<string, CacheEntry<T>>();1617constructor(protected readonly defaultMaxAgeSeconds: number, protected readonly gcIntervalSeconds: number) {18this.regularlyCollectGarbage();19}2021public set(key: string, value: T) {22const oldValue = this.store.get(key);23if (oldValue) {24// We don't want values to be cached indefinitely just because their queried often25return;26}27this.store.set(key, {28key,29value,30expiryDate: this.calcExpiryDate(),31});32}3334public get(key: string): T | undefined {35const entry = this.store.get(key);36if (!entry) {37return undefined;38}39// Still valid?40if (entry.expiryDate < Date.now()) {41this.store.delete(entry.key);42return undefined;43}44return entry.value;45}4647public delete(key: string) {48this.store.delete(key);49}5051protected regularlyCollectGarbage() {52repeat(() => this.collectGarbage(), this.gcIntervalSeconds * 1000);53}5455protected collectGarbage() {56const now = Date.now();57for (const entry of this.store.values()) {58if (entry.expiryDate < now) {59this.store.delete(entry.key);60}61}62}6364protected calcExpiryDate(maxAgeSeconds?: number): number {65return Date.now() + (maxAgeSeconds || this.defaultMaxAgeSeconds) * 1000;66}67}686970