Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | 36x 36x 36x 15x 15x 15x 10x 1x 27x 27x 20x 7x 7x 7x 7x 36x 10x 10x 2x 17x 17x 17x 17x 17x 17x 17x 17x 13x 4x | import { AsyncAction, InMemoryCache, Key } from './InMemoryCache';
import { Seconds } from '@cardano-sdk/core';
import NodeCache from 'node-cache';
interface WarmCacheItem<T> {
asyncAction: AsyncAction<T>;
value: T;
ttl: number;
updateTime: number;
}
export class WarmCache extends InMemoryCache {
constructor(ttl: Seconds, expireCheckPeriod: Seconds) {
const cache = new NodeCache({
checkperiod: expireCheckPeriod,
deleteOnExpire: true,
stdTTL: ttl,
useClones: false
});
super(ttl, cache);
this.cache.on('expired', (key, value) => {
this.#warm(key, value, this.cache);
});
}
public mockCache(cache: NodeCache) {
this.cache = cache;
}
public async get<T>(key: Key, asyncAction: AsyncAction<T>, ttl = this.ttlDefault): Promise<T> {
const cachedValue: WarmCacheItem<T> | undefined = this.cache.get(key);
if (cachedValue && cachedValue.value) {
return cachedValue.value;
}
const updateTime = Date.now();
const promise = this.#setWarmCacheItem<T>(key, asyncAction, ttl, this.cache, updateTime);
this.cache.set(
key,
{
asyncAction,
ttl,
updateTime,
value: promise
// value: _resolved ? Promise.resolve(value) : Promise.reject(value)
} as WarmCacheItem<T>,
ttl
);
return promise;
}
#warm<T>(key: string, item: WarmCacheItem<T> | undefined, cacheNode: NodeCache) {
if (item && item.asyncAction) {
this.#setWarmCacheItem(key, item.asyncAction, item.ttl, cacheNode, Date.now()).catch(
() => 'rejected in the background'
);
}
}
async #setWarmCacheItem<T>(
key: Key,
asyncAction: AsyncAction<T>,
ttl: number,
cacheNode: NodeCache,
updateTime: number
) {
const handleValue = (value: T, _resolved = true) => {
const item = this.cache.get(key) as WarmCacheItem<T>;
Iif (item && item.updateTime > updateTime) {
return item.value;
}
const promise = _resolved ? Promise.resolve(value) : Promise.reject(value);
cacheNode.set(
key,
{
asyncAction,
ttl,
updateTime,
value: promise
// value: _resolved ? Promise.resolve(value) : Promise.reject(value)
} as WarmCacheItem<T>,
ttl
);
return promise;
};
try {
const value = await asyncAction();
return handleValue(value, true);
} catch (error) {
return handleValue(error as T, false);
}
}
}
|