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