fix(memory): bound visualizer PCM cache and feed episode cache
The visualizer's PCM cache decoded the entire episode into RAM (22050 Hz mono s16 ~160 MB/hr of audio) and held it until stop() — a 3-hour episode pinned ~500 MB and long-form content hit 2.5 GB. The 4x decode also pulled the whole remote file even when only minutes were listened to. - audio-pcm-cache: sliding window around the playback position — the decode head caps at maxAheadSec (600s) ahead of the cursor, segments older than keepBehindSec (300s) are pruned, and the tail refills as playback advances. Steady state ~40 MB regardless of episode length; a backward seek past the window restarts a segment there (the existing seek-hole mechanism, no new failure mode). - feed: cap the full-parse episode cache at 1000 episodes/feed so archive-heavy subscriptions can't pin their entire history in RAM; the visible list stays bounded by the user's cache preference and fetch-more keeps working within the ceiling. - tests: pin the new head-cap and prune contracts (8/8 in audio-pcm-cache.test.ts; full suite 193 pass). Also includes the in-flight cleanup/refactor pass (cover-art resolve helper, page and comment tightening, ESLint config removal).
This commit is contained in:
@@ -62,7 +62,6 @@ const defaultState: AppState = {
|
||||
|
||||
// ── App State (config.json) ─────────────────────────────────────────────────
|
||||
|
||||
/** Load app state from config.json */
|
||||
export async function loadAppStateFromFile(): Promise<AppState> {
|
||||
try {
|
||||
const cfg = await loadConfig();
|
||||
@@ -88,7 +87,6 @@ export async function loadAppStateFromFile(): Promise<AppState> {
|
||||
}
|
||||
}
|
||||
|
||||
/** Save app state to config.json */
|
||||
export function saveAppStateToFile(state: AppState): void {
|
||||
updateConfig({
|
||||
settings: state.settings,
|
||||
@@ -109,7 +107,6 @@ interface ProgressEntry {
|
||||
playbackSpeed?: number;
|
||||
}
|
||||
|
||||
/** Load progress map from JSON file */
|
||||
export async function loadProgressFromFile(): Promise<
|
||||
Record<string, ProgressEntry>
|
||||
> {
|
||||
@@ -145,7 +142,6 @@ export function saveProgressToFile(data: Record<string, unknown>): void {
|
||||
|
||||
const SEARCH_HISTORY_FILE = "search-history.json";
|
||||
|
||||
/** Load search history from JSON file */
|
||||
export async function loadSearchHistoryFromFile(): Promise<string[]> {
|
||||
try {
|
||||
const file = Bun.file(getConfigFilePath(SEARCH_HISTORY_FILE));
|
||||
@@ -159,7 +155,6 @@ export async function loadSearchHistoryFromFile(): Promise<string[]> {
|
||||
}
|
||||
}
|
||||
|
||||
/** Save search history to JSON file (overwrite, no backup) */
|
||||
export function saveSearchHistoryToFile(history: string[]): void {
|
||||
(async () => {
|
||||
try {
|
||||
@@ -178,7 +173,6 @@ export function saveSearchHistoryToFile(history: string[]): void {
|
||||
|
||||
const AUDIO_NAV_FILE = "audio-nav.json";
|
||||
|
||||
/** Load audio navigation state from JSON file */
|
||||
export async function loadAudioNavFromFile<T>(): Promise<T | null> {
|
||||
try {
|
||||
const file = Bun.file(getConfigFilePath(AUDIO_NAV_FILE));
|
||||
|
||||
Reference in New Issue
Block a user