From 65a93b74fc9ef8e697ed5e8aabd0e0848c14880c Mon Sep 17 00:00:00 2001 From: Marcel van der Veldt Date: Fri, 5 Mar 2021 12:03:49 +0100 Subject: [PATCH] fix race condition in adding players --- music_assistant/constants.py | 2 +- music_assistant/managers/library.py | 4 +- music_assistant/managers/players.py | 47 +++++++++++-------- music_assistant/mass.py | 7 ++- music_assistant/models/player_queue.py | 2 +- .../providers/chromecast/__init__.py | 4 +- 6 files changed, 40 insertions(+), 26 deletions(-) diff --git a/music_assistant/constants.py b/music_assistant/constants.py index f218ece1..c6b19ee2 100755 --- a/music_assistant/constants.py +++ b/music_assistant/constants.py @@ -1,6 +1,6 @@ """All constants for Music Assistant.""" -__version__ = "0.1.7" +__version__ = "0.1.8" REQUIRED_PYTHON_VER = "3.8" # configuration keys/attributes diff --git a/music_assistant/managers/library.py b/music_assistant/managers/library.py index 2e36addd..ade46ab4 100755 --- a/music_assistant/managers/library.py +++ b/music_assistant/managers/library.py @@ -37,14 +37,14 @@ def sync_task(desc): "Syncjob %s for provider %s is already running!", desc, prov_id ) return - LOGGER.debug("Start syncjob %s for provider %s.", desc, prov_id) + LOGGER.info("Start syncjob %s for provider %s.", desc, prov_id) sync_job = (prov_id, desc) method_class.running_sync_jobs.add(sync_job) method_class.mass.signal_event( EVENT_MUSIC_SYNC_STATUS, method_class.running_sync_jobs ) await func(*args) - LOGGER.debug("Finished syncing %s for provider %s", desc, prov_id) + LOGGER.info("Finished syncing %s for provider %s", desc, prov_id) method_class.running_sync_jobs.remove(sync_job) method_class.mass.signal_event( EVENT_MUSIC_SYNC_STATUS, method_class.running_sync_jobs diff --git a/music_assistant/managers/players.py b/music_assistant/managers/players.py index bcb964c4..71bd79dd 100755 --- a/music_assistant/managers/players.py +++ b/music_assistant/managers/players.py @@ -163,37 +163,46 @@ class PlayerManager: async def add_player(self, player: Player) -> None: """Register a new player or update an existing one.""" + player_id = player.player_id + # guard for invalid data or exit in progress if not player or self.mass.exit: return + # redirect to update if player is already added - if player.added_to_mass: - return await self.trigger_player_update(player.player_id) - # make sure that the mass instance is set on the player - player.mass = self.mass - self._players[player.player_id] = player + if player_id in self._players: + player = self._players[player_id] + if player.added_to_mass: + await self.trigger_player_update(player_id) + return + else: + self._players[player.player_id] = player + # make sure that the mass instance is set on the player + player.mass = self.mass + # make sure that the player state is created/updated player.player_state.update(player.create_state()) + # Fully initialize only if player is enabled - if player.enabled: - await player.on_add() - player.added_to_mass = True - # create playerqueue instance - self._player_queues[player.player_id] = PlayerQueue( - self.mass, player.player_id - ) - LOGGER.info( - "Player added: %s/%s", - player.provider_id, - player.name, - ) - self.mass.signal_event(EVENT_PLAYER_ADDED, player) - else: + if not player.enabled: LOGGER.debug( "Ignoring player: %s/%s because it's disabled", player.provider_id, player.name, ) + return + + # new player + player.added_to_mass = True + await player.on_add() + # create playerqueue instance + self._player_queues[player.player_id] = PlayerQueue(self.mass, player.player_id) + LOGGER.info( + "Player added: %s/%s", + player.provider_id, + player.name, + ) + self.mass.signal_event(EVENT_PLAYER_ADDED, player) async def remove_player(self, player_id: str): """Remove a player from the registry.""" diff --git a/music_assistant/mass.py b/music_assistant/mass.py index d554d348..49c50e36 100644 --- a/music_assistant/mass.py +++ b/music_assistant/mass.py @@ -317,7 +317,12 @@ class MusicAssistant: while not self.exit: task = await self._background_tasks.get() await task - await asyncio.sleep(1) + if self._background_tasks.qsize() > 200: + await asyncio.sleep(0.5) + elif self._background_tasks.qsize() == 0: + await asyncio.sleep(10) + else: + await asyncio.sleep(1) async def setup_discovery(self) -> None: """Make this Music Assistant instance discoverable on the network.""" diff --git a/music_assistant/models/player_queue.py b/music_assistant/models/player_queue.py index 83e0496c..f538cc57 100755 --- a/music_assistant/models/player_queue.py +++ b/music_assistant/models/player_queue.py @@ -611,4 +611,4 @@ class PlayerQueue: "cur_index": self._cur_index, } await self.mass.cache.set(cache_str, cache_data) - LOGGER.info("queue state saved to file for player %s", self.queue_id) + LOGGER.debug("queue state saved to file for player %s", self.queue_id) diff --git a/music_assistant/providers/chromecast/__init__.py b/music_assistant/providers/chromecast/__init__.py index a0041392..155b503e 100644 --- a/music_assistant/providers/chromecast/__init__.py +++ b/music_assistant/providers/chromecast/__init__.py @@ -90,8 +90,8 @@ class ChromecastProvider(PlayerProvider): "Chromecast discovered: %s (%s)", cast_info.friendly_name, player_id ) player = self.mass.players.get_player(player_id) - if not player and cast_info.is_audio_group: - # audio groups may reappear with new uuid, try to handle that + if not player: + # cast players may reappear with new uuid, try to handle that player = self.mass.players.get_player_by_name( cast_info.friendly_name, PROV_ID ) -- 2.34.1