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); } } } |