import "../../_dnt.polyfills.js"; import * as $ from "../../deps/scale.js" import { AsyncMemo } from "../memo.js" import { getOrInit, TimedMemo, WeakMemo } from "../mod.js" export abstract class CacheBase { constructor(readonly signal: AbortSignal) { this.stringMemo = new TimedMemo(-1, this.signal) } abstract _getRaw(key: string, init: () => Promise): Promise abstract _has(key: string): Promise hasMemo = new AsyncMemo() has(key: string) { return this.hasMemo.run(key, () => this._has(key)) } rawMemo = new WeakMemo() getRaw(key: string, init: () => Promise): Promise { return this.rawMemo.run(key, () => this._getRaw(key, init)) } decodedMemo = new Map<$.AnyCodec, WeakMemo>() get(key: string, $value: $.Codec, init: () => Promise): Promise { const memo = getOrInit(this.decodedMemo, $value, () => new WeakMemo()) as WeakMemo return memo.run(key, async () => { let value: T | undefined const raw = await this.getRaw(key, async () => $value.encode(value = await init())) value ??= $value.decode(raw) return value }) } stringMemo getString(key: string, ttl: number, init: () => Promise): Promise { return this.stringMemo.run(key, async () => { let value: string | undefined const raw = await this.getRaw(key, async () => new TextEncoder().encode(value = await init())) value ??= new TextDecoder().decode(raw) return value }, ttl) } }