From 31bc9ea2a499c8c7d068305a370b47a3f0238dd7 Mon Sep 17 00:00:00 2001 From: Nuwan Date: Wed, 14 Jan 2026 15:55:27 +0530 Subject: [PATCH] feat(03-02): handle file and network edge cases Implemented defensive handling for edge cases and failure scenarios: Cleanup on unmount: - Added useEffect to stop playback on component unmount - Prevents stale state when player closes while playing - Catches errors gracefully File format validation: - Validates duration in fetchDuration (rejects 0 or NaN) - Warns about suspicious durations (<1s or >10h) - May indicate parsing errors Network handling: - Already implemented: consecutivePollingErrorsRef tracks failures - Shows error after 3 consecutive polling failures - Stops polling and allows retry jamClient guards: - Already implemented: null checks in all handlers - Early return with error message if unavailable Invalid state recovery: - Polling detects mismatched isPlaying state - Force syncs UI to jamClient state - Logs warnings for debugging Graceful degradation: - Error states show but player stays open - Provides Dismiss and Retry options - No crashes or frozen UI All edge cases handled with defensive coding and proper cleanup. --- .../client/JKSessionBackingTrackPlayer.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/jam-ui/src/components/client/JKSessionBackingTrackPlayer.js b/jam-ui/src/components/client/JKSessionBackingTrackPlayer.js index d9972a503..3248c1c4d 100644 --- a/jam-ui/src/components/client/JKSessionBackingTrackPlayer.js +++ b/jam-ui/src/components/client/JKSessionBackingTrackPlayer.js @@ -111,6 +111,13 @@ const JKSessionBackingTrackPlayer = ({ return; } + // Warn about suspicious durations (file format validation) + const tenHoursMs = 10 * 60 * 60 * 1000; // 10 hours + const oneSecondMs = 1000; + if (validDuration > tenHoursMs || validDuration < oneSecondMs) { + console.warn('[BTP] Suspicious duration detected:', validDuration, 'ms. May indicate parsing error.'); + } + setDurationMs(validDuration); setDuration(formatTime(validDuration)); clearError(); // Clear any previous errors @@ -191,6 +198,18 @@ const JKSessionBackingTrackPlayer = ({ }; }, [isPlaying, jamClient, backingTrack]); + // Cleanup on unmount: stop playback to prevent stale state + useEffect(() => { + return () => { + // Stop playback when component unmounts + if (jamClient && isPlaying) { + jamClient.SessionStopPlay().catch((err) => { + console.error('[BTP] Error stopping playback on unmount:', err); + }); + } + }; + }, [jamClient, isPlaying]); + const handlePlay = async () => { if (isOperating) return; // Prevent rapid clicks setIsOperating(true);