Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(android): promises leak caused by player not in the HashMap #136

Conversation

dprevost-LMI
Copy link
Contributor

@dprevost-LMI dprevost-LMI commented Nov 16, 2024

After calling stopAllPlayers, if we call some Android native function and the player is not in the HashMap, multiple functions will forget to reject the promise and end up with promise leaks. This is affecting startPlayer, pausePlayer, seekToPlayer, setVolume, getDuration

Below is an example where the console log after await AudioWaveform.startPlayer never shows since the call leaked the promise
STR:

  • Start a player
  • Pause de player
  • Call useAudioPlayer.stopAllPlayers()
  • Start the the player again
  • The useAudioPlayer.startPlayer() never returns
Screenshot 2024-11-16 at 1 34 30 PM



Once the promise is rejected correctly, the error is propagated to the JS correctly, proof: image

@dprevost-LMI dprevost-LMI marked this pull request as ready for review November 16, 2024 18:43
@dprevost-LMI
Copy link
Contributor Author

Do I need to enter a ticket for this PR, or can we merge it as it is?

@dprevost-LMI dprevost-LMI changed the title [BUG] Fix promises leak caused by missing player fix(android): promises leak caused by player not in the HashMap Nov 16, 2024
kuldip-simform
kuldip-simform previously approved these changes Nov 18, 2024
@kuldip-simform kuldip-simform self-requested a review November 18, 2024 06:32
@nilesh-simform
Copy link
Contributor

nilesh-simform commented Nov 18, 2024

Hi @dprevost-LMI

We need to manage the seekTo function with a try-catch block because we do not initialize the player until the user starts playing. Therefore, when the user attempts to seek before the player is initialized, it will reject the promise.

To handle this, Please add the necessary changes here as shown below.

const seekToPlayerAction = async () => {
   if (!isNil(seekPosition)) {
     if (mode === 'static') {
       const seekAmount =
         (seekPosition?.pageX - (viewLayout?.x ?? 0)) /
         (viewLayout?.width ?? 1);
       const clampedSeekAmount = clamp(seekAmount, 0, 1);

       if (!panMoving) {
         try {
           await seekToPlayer({
             playerKey: `PlayerFor${path}`,
             progress: clampedSeekAmount * songDuration,
           });
         } catch (e) {}

         if (playerState === PlayerState.playing) {
           startPlayerAction();
         }
       }

       setCurrentProgress(clampedSeekAmount * songDuration);
     }
   }
 };

 useEffect(() => {
   seekToPlayerAction();
   // eslint-disable-next-line react-hooks/exhaustive-deps
 }, [seekPosition, panMoving, mode, songDuration]);

@dprevost-LMI
Copy link
Contributor Author

dprevost-LMI commented Nov 18, 2024

@nilesh-simform I used what you proposed coupled with await stopPlayerAction() in the catch. It could be a more elegant fix, but it at least auto-corrects the player so that it works on the next play-action.
I repeat the fix when startPlayerAction() also throws an error. It unblocks the user on the second play attempt.

I'm sure there is a better fix for that, but at least this will unblock the user, and later on, it can be fixed better.

@kuldip-simform
Copy link
Contributor

Closing this in favour of #138

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants