A decentralized music tracking and discovery platform built on AT Protocol 馃幍
at bb78ac5bfdffe97e585d90fa2f2e1b28d475dce6 76 lines 1.7 kB view raw
1import { 2 type CacheResult, 3 type DidCache, 4 type DidDocument, 5} from "@atproto/identity"; 6import type { Storage } from "unstorage"; 7 8const HOUR = 60e3 * 60; 9const DAY = HOUR * 24; 10 11type CacheVal = { 12 doc: DidDocument; 13 updatedAt: number; 14}; 15 16/** 17 * An unstorage based DidCache with staleness and max TTL 18 */ 19export class StorageCache implements DidCache { 20 public staleTTL: number; 21 public maxTTL: number; 22 public cache: Storage<CacheVal>; 23 private prefix: string; 24 constructor({ 25 store, 26 prefix, 27 staleTTL, 28 maxTTL, 29 }: { 30 store: Storage; 31 prefix: string; 32 staleTTL?: number; 33 maxTTL?: number; 34 }) { 35 this.cache = store as Storage<CacheVal>; 36 this.prefix = prefix; 37 this.staleTTL = staleTTL ?? HOUR; 38 this.maxTTL = maxTTL ?? DAY; 39 } 40 41 async cacheDid(did: string, doc: DidDocument): Promise<void> { 42 await this.cache.set(this.prefix + did, { doc, updatedAt: Date.now() }); 43 } 44 45 async refreshCache( 46 did: string, 47 getDoc: () => Promise<DidDocument | null> 48 ): Promise<void> { 49 const doc = await getDoc(); 50 if (doc) { 51 await this.cacheDid(did, doc); 52 } 53 } 54 55 async checkCache(did: string): Promise<CacheResult | null> { 56 const val = await this.cache.get<CacheVal>(this.prefix + did); 57 if (!val) return null; 58 const now = Date.now(); 59 const expired = now > val.updatedAt + this.maxTTL; 60 const stale = now > val.updatedAt + this.staleTTL; 61 return { 62 ...val, 63 did, 64 stale, 65 expired, 66 }; 67 } 68 69 async clearEntry(did: string): Promise<void> { 70 await this.cache.remove(this.prefix + did); 71 } 72 73 async clear(): Promise<void> { 74 await this.cache.clear(this.prefix); 75 } 76}