8 changed files with 268 additions and 26 deletions
@ -0,0 +1,88 @@ |
|||||||
|
/** |
||||||
|
* Markdown rendering cache with IndexedDB persistence |
||||||
|
*/ |
||||||
|
|
||||||
|
import { getDB } from './indexeddb-store.js'; |
||||||
|
|
||||||
|
export interface CachedMarkdown { |
||||||
|
hash: string; |
||||||
|
rendered: string; |
||||||
|
cached_at: number; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Simple hash function for content (djb2 algorithm) |
||||||
|
*/ |
||||||
|
function hashContent(content: string): string { |
||||||
|
let hash = 5381; |
||||||
|
for (let i = 0; i < content.length; i++) { |
||||||
|
hash = ((hash << 5) + hash) + content.charCodeAt(i); |
||||||
|
} |
||||||
|
return hash.toString(36); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get cached rendered markdown |
||||||
|
*/ |
||||||
|
export async function getCachedMarkdown(content: string): Promise<string | null> { |
||||||
|
try { |
||||||
|
const hash = hashContent(content); |
||||||
|
const db = await getDB(); |
||||||
|
const cached = await db.get('markdown', hash) as CachedMarkdown | undefined; |
||||||
|
|
||||||
|
if (cached) { |
||||||
|
// Check if cache is still valid (30 days TTL)
|
||||||
|
const maxAge = 30 * 24 * 60 * 60 * 1000; // 30 days
|
||||||
|
if (Date.now() - cached.cached_at < maxAge) { |
||||||
|
return cached.rendered; |
||||||
|
} |
||||||
|
// Cache expired, delete it
|
||||||
|
await db.delete('markdown', hash); |
||||||
|
} |
||||||
|
|
||||||
|
return null; |
||||||
|
} catch (error) { |
||||||
|
console.debug('Error getting cached markdown:', error); |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Cache rendered markdown |
||||||
|
*/ |
||||||
|
export async function cacheMarkdown(content: string, rendered: string): Promise<void> { |
||||||
|
try { |
||||||
|
const hash = hashContent(content); |
||||||
|
const db = await getDB(); |
||||||
|
const cached: CachedMarkdown = { |
||||||
|
hash, |
||||||
|
rendered, |
||||||
|
cached_at: Date.now() |
||||||
|
}; |
||||||
|
await db.put('markdown', cached); |
||||||
|
} catch (error) { |
||||||
|
console.debug('Error caching markdown:', error); |
||||||
|
// Don't throw - caching failures shouldn't break the app
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Clear old markdown cache entries (older than specified timestamp) |
||||||
|
*/ |
||||||
|
export async function clearOldMarkdownCache(olderThan: number): Promise<void> { |
||||||
|
try { |
||||||
|
const db = await getDB(); |
||||||
|
const tx = db.transaction('markdown', 'readwrite'); |
||||||
|
const index = tx.store.index('cached_at'); |
||||||
|
|
||||||
|
for await (const cursor of index.iterate()) { |
||||||
|
if (cursor.value.cached_at < olderThan) { |
||||||
|
await cursor.delete(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
await tx.done; |
||||||
|
} catch (error) { |
||||||
|
console.debug('Error clearing old markdown cache:', error); |
||||||
|
} |
||||||
|
} |
||||||
Loading…
Reference in new issue