fix: replace TTS FIFO cache with LRU eviction, add database indexes
TTS audioCache now tracks lastAccess timestamp per entry and evicts the least-recently-used entry when full (was FIFO, deleting commonly used phrases). Adds 6 new database indexes for bets, bot type/active filtering, payment status lookups, and tournament entries. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
fbc61ef154
commit
46d560af24
@@ -120,7 +120,7 @@ const _pending = new Map<number, {
|
||||
|
||||
// --- Audio state (main thread only) ---
|
||||
let _audioCtx: AudioContext | null = null
|
||||
const audioCache = new Map<string, AudioBuffer>()
|
||||
const audioCache = new Map<string, { buf: AudioBuffer; lastAccess: number }>()
|
||||
const MAX_CACHE = 50
|
||||
const activeSources: Set<AudioBufferSourceNode> = new Set()
|
||||
|
||||
@@ -265,7 +265,7 @@ async function _generateAndCache(text: string, profile: string): Promise<AudioBu
|
||||
if (!_workerReady) return null
|
||||
const key = _cacheKey(text, profile)
|
||||
const cached = audioCache.get(key)
|
||||
if (cached) return cached
|
||||
if (cached) { cached.lastAccess = Date.now(); return cached.buf }
|
||||
|
||||
// Dedup: if already generating this exact audio, reuse the in-flight promise
|
||||
const existing = _inflight.get(key)
|
||||
@@ -288,12 +288,16 @@ async function _doGenerate(text: string, profile: string, key: string): Promise<
|
||||
const buf = ctx.createBuffer(1, raw.audio.length, raw.sampleRate)
|
||||
buf.getChannelData(0).set(raw.audio)
|
||||
|
||||
// Evict oldest if cache is full
|
||||
// Evict least-recently-used if cache is full
|
||||
if (audioCache.size >= MAX_CACHE) {
|
||||
const oldest = audioCache.keys().next().value
|
||||
if (oldest) audioCache.delete(oldest)
|
||||
let lruKey: string | undefined
|
||||
let lruTime = Infinity
|
||||
for (const [k, v] of audioCache) {
|
||||
if (v.lastAccess < lruTime) { lruTime = v.lastAccess; lruKey = k }
|
||||
}
|
||||
audioCache.set(key, buf)
|
||||
if (lruKey) audioCache.delete(lruKey)
|
||||
}
|
||||
audioCache.set(key, { buf, lastAccess: Date.now() })
|
||||
return buf
|
||||
}
|
||||
|
||||
@@ -355,7 +359,8 @@ export function kokoroSpeak(
|
||||
const key = _cacheKey(text, profileName)
|
||||
const cached = audioCache.get(key)
|
||||
if (cached) {
|
||||
_playBuffer(cached, dest, volume)
|
||||
cached.lastAccess = Date.now()
|
||||
_playBuffer(cached.buf, dest, volume)
|
||||
return true
|
||||
}
|
||||
// Generate in worker — will play when ready
|
||||
|
||||
@@ -182,6 +182,12 @@ export function runMigrations() {
|
||||
CREATE INDEX IF NOT EXISTS idx_payments_status ON payments(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_payments_bot ON payments(bot_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_tournament_matches_tournament ON tournament_matches(tournament_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_bets_fight ON bets(fight_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_bets_bettor ON bets(bettor_pubkey, created_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_bots_type_active ON bots(bot_type, is_active);
|
||||
CREATE INDEX IF NOT EXISTS idx_payments_status_created ON payments(status, created_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_tournament_entries_tournament ON tournament_entries(tournament_id);
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_analytics_date_metric ON analytics(date, metric);
|
||||
`)
|
||||
|
||||
// Run PRAGMA optimize on startup for query planner stats
|
||||
|
||||
Reference in New Issue
Block a user