@@ -22,11 +22,12 @@ import com.lasthopesoftware.bluewater.client.playback.nowplaying.storage.ManageN
2222import com.lasthopesoftware.bluewater.client.playback.nowplaying.storage.NowPlaying
2323import com.lasthopesoftware.bluewater.client.playback.playlist.ManagePlaylistPlayback
2424import com.lasthopesoftware.bluewater.shared.lazyLogger
25- import com.lasthopesoftware.policies.ratelimiting.PromisingRateLimiter
25+ import com.lasthopesoftware.bluewater.shared.tryUpdate
2626import com.lasthopesoftware.promises.ContinuingResult
2727import com.lasthopesoftware.promises.extensions.ProgressingPromise
2828import com.lasthopesoftware.promises.extensions.keepPromise
2929import com.lasthopesoftware.promises.extensions.onEachEventually
30+ import com.lasthopesoftware.promises.extensions.regardless
3031import com.lasthopesoftware.promises.extensions.toPromise
3132import com.lasthopesoftware.promises.extensions.unitResponse
3233import com.namehillsoftware.handoff.errors.RejectionDropper
@@ -69,7 +70,7 @@ class PlaybackEngine(
6970
7071 private val activeLibraryId = AtomicReference (markerLibraryId)
7172
72- private val nowPlayingStateSync = PromisingRateLimiter <NowPlaying ?>(1 )
73+ private val promisedNowPlayingState = AtomicReference ( Promise .empty <NowPlaying ?>() )
7374
7475 private val promisedPlayback = AtomicReference <ProgressingPromise <PositionedPlayingFile , Unit >? > (null )
7576
@@ -480,13 +481,9 @@ class PlaybackEngine(
480481 return playlistPlayback.resume()
481482 }
482483
483- private fun serializedPlayerUpdate () = nowPlayingStateSync.limit {
484- playbackBootstrapper.updateFromState(activeLibraryId.get())
485- }
484+ private fun serializedPlayerUpdate () = updateStateSynchronously { playbackBootstrapper.updateFromState(activeLibraryId.get()) }
486485
487- private fun promiseActiveNowPlaying () = nowPlayingStateSync.limit {
488- nowPlayingRepository.promiseNowPlaying(activeLibraryId.get())
489- }
486+ private fun promiseActiveNowPlaying () = updateStateSynchronously { nowPlayingRepository.promiseNowPlaying(activeLibraryId.get()) }
490487
491488 private fun saveState (
492489 libraryId : LibraryId ,
@@ -508,7 +505,7 @@ class PlaybackEngine(
508505 private inline fun saveState (
509506 libraryId : LibraryId ,
510507 crossinline updateFunc : NowPlaying .() -> NowPlaying
511- ): Promise <NowPlaying ?> = nowPlayingStateSync.limit {
508+ ): Promise <NowPlaying ?> = updateStateSynchronously {
512509 nowPlayingRepository.promiseNowPlaying(libraryId).eventually {
513510 it?.let { np ->
514511 val updatedNowPlaying = updateFunc(np)
@@ -519,7 +516,24 @@ class PlaybackEngine(
519516 }
520517
521518 @Suppress(" UNCHECKED_CAST" )
522- private fun saveState (nowPlaying : NowPlaying ): Promise <NowPlaying ?> = nowPlayingStateSync.limit {
519+ private fun saveState (nowPlaying : NowPlaying ): Promise <NowPlaying ?> = updateStateSynchronously {
523520 nowPlayingRepository.updateNowPlaying(nowPlaying) as Promise <NowPlaying ?>
524521 }
522+
523+ /* *
524+ * Updates the `promisedNowPlayingState` with the result of the provided `updateFunc`.
525+ *
526+ * This function ensures that the `promisedNowPlayingState` is updated synchronously.
527+ * Each new update is chained to the previous promise, guaranteeing that state
528+ * updates are applied in the order they are initiated.
529+ *
530+ * @param updateFunc A function that returns a [Promise] for a nullable [NowPlaying] state.
531+ * This function is responsible for fetching or modifying the state.
532+ * @return A [Promise] that resolves with the current [NowPlaying] state after the update
533+ * function has been scheduled. To wait for the update to complete, chain to the returned promise.
534+ */
535+ private inline fun updateStateSynchronously (crossinline updateFunc : () -> Promise <NowPlaying ?>): Promise <NowPlaying ?> {
536+ promisedNowPlayingState.tryUpdate { prev -> prev.regardless { updateFunc() } }
537+ return promisedNowPlayingState.get()
538+ }
525539}
0 commit comments