mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-21 23:05:46 +00:00
fix(analysis): persist failed tracks and reconcile progress counts (#867)
* fix(analysis): persist failed-track suppression and reduce aggressive polling Persist unsupported/broken analysis tracks as failed entries and expose them in Settings with track metadata, export, and targeted rescan actions. Also make aggressive-mode completion checks cheap by gating re-entry on live track-count changes with a startup seed and 5-minute recheck cadence. * fix(analysis): mark unsupported decode tracks as failed in cpu-seed When full-seed falls back to waveform-only (no EBU loudness) or enrichment decode fails, persist analysis_track status as failed so aggressive backfill does not requeue the same unsupported tracks indefinitely. * fix(analysis): reconcile legacy ready tracks without loudness Auto-mark legacy ready tracks that only miss loudness as failed during needs-work checks so analysis progress converges instead of staying permanently pending. * docs(changelog): add failed-analysis recovery notes for PR 867 Document persistent failed-track handling, analytics strategy controls, and low-cost aggressive-mode recheck behavior in the 1.47.0 changelog. * fix(i18n): align settings locale coverage across all languages Sync missing Settings keys for all shipped locales and replace recent English fallbacks with localized strings so analytics and backup UI text stays consistent outside en/ru.
This commit is contained in:
@@ -5,6 +5,8 @@ import {
|
||||
analysisGetPipelineQueueStats,
|
||||
analysisSetPipelineParallelism,
|
||||
libraryAnalysisBackfillBatch,
|
||||
libraryCountLiveTracks,
|
||||
libraryAnalysisProgress,
|
||||
} from '../api/analysis';
|
||||
import { useAuthStore } from '../store/authStore';
|
||||
import { useAnalysisStrategyStore } from '../store/analysisStrategyStore';
|
||||
@@ -19,6 +21,7 @@ const TOP_UP_POLL_MS = 500;
|
||||
const STEADY_POLL_MS = 2000;
|
||||
const READY_POLL_MS = 5000;
|
||||
const EXHAUSTED_PAUSE_MS = 60_000;
|
||||
const COMPLETED_RECHECK_MS = 5 * 60_000;
|
||||
|
||||
const EMPTY_PIPELINE_STATS = {
|
||||
pipelineWorkers: 1,
|
||||
@@ -52,6 +55,7 @@ export function useLibraryAnalysisBackfill(enabled = true): void {
|
||||
s => s.getAdvancedParallelismForServer(activeServerId),
|
||||
);
|
||||
const cursorRef = useRef<string | null>(null);
|
||||
const completedTotalRef = useRef<number | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!enabled) return;
|
||||
@@ -65,9 +69,33 @@ export function useLibraryAnalysisBackfill(enabled = true): void {
|
||||
|
||||
let cancelled = false;
|
||||
const serverId = activeServerId;
|
||||
let initialized = false;
|
||||
|
||||
void (async () => {
|
||||
while (!cancelled) {
|
||||
if (!initialized) {
|
||||
initialized = true;
|
||||
const progress = await libraryAnalysisProgress(serverId).catch(() => null);
|
||||
if (progress && progress.pendingTracks <= 0) {
|
||||
completedTotalRef.current = progress.totalTracks;
|
||||
cursorRef.current = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (completedTotalRef.current !== null) {
|
||||
const totalTracks = await libraryCountLiveTracks(serverId).catch(() => null);
|
||||
if (!Number.isFinite(totalTracks)) {
|
||||
await new Promise(r => setTimeout(r, COMPLETED_RECHECK_MS));
|
||||
continue;
|
||||
}
|
||||
if (totalTracks === completedTotalRef.current) {
|
||||
await new Promise(r => setTimeout(r, COMPLETED_RECHECK_MS));
|
||||
continue;
|
||||
}
|
||||
completedTotalRef.current = null;
|
||||
cursorRef.current = null;
|
||||
}
|
||||
|
||||
if (!(await libraryIsReady(serverId))) {
|
||||
await new Promise(r => setTimeout(r, READY_POLL_MS));
|
||||
continue;
|
||||
@@ -119,6 +147,12 @@ export function useLibraryAnalysisBackfill(enabled = true): void {
|
||||
|
||||
if (batch.exhausted) {
|
||||
cursorRef.current = null;
|
||||
const progress = await libraryAnalysisProgress(serverId).catch(() => null);
|
||||
if (progress && progress.pendingTracks <= 0) {
|
||||
completedTotalRef.current = progress.totalTracks;
|
||||
await new Promise(r => setTimeout(r, COMPLETED_RECHECK_MS));
|
||||
continue;
|
||||
}
|
||||
await new Promise(r => setTimeout(r, EXHAUSTED_PAUSE_MS));
|
||||
} else if (batch.trackIds.length === 0) {
|
||||
await new Promise(r => setTimeout(r, TOP_UP_POLL_MS));
|
||||
@@ -130,6 +164,7 @@ export function useLibraryAnalysisBackfill(enabled = true): void {
|
||||
return () => {
|
||||
cancelled = true;
|
||||
cursorRef.current = null;
|
||||
completedTotalRef.current = null;
|
||||
};
|
||||
}, [strategy, activeServerId, advancedParallelism, enabled]);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user