From a564c62d033c90d8f3d4974a86e5500691647df7 Mon Sep 17 00:00:00 2001 From: Marcel van der Veldt Date: Mon, 3 Apr 2023 23:57:44 +0200 Subject: [PATCH] fix race condition --- .../server/controllers/media/albums.py | 50 +++++++++---------- .../server/controllers/media/artists.py | 38 +++++++------- .../server/controllers/media/playlists.py | 41 +++++++-------- .../server/controllers/media/radio.py | 37 +++++++------- .../server/controllers/media/tracks.py | 47 ++++++++--------- 5 files changed, 108 insertions(+), 105 deletions(-) diff --git a/music_assistant/server/controllers/media/albums.py b/music_assistant/server/controllers/media/albums.py index f9e57856..f9a76170 100644 --- a/music_assistant/server/controllers/media/albums.py +++ b/music_assistant/server/controllers/media/albums.py @@ -236,9 +236,9 @@ class AlbumsController(MediaControllerBase[Album]): }, ) item_id = new_item["item_id"] - # update/set provider_mappings table - await self._set_provider_mappings(item_id, item.provider_mappings) - self.logger.debug("added %s to database", item.name) + # update/set provider_mappings table + await self._set_provider_mappings(item_id, item.provider_mappings) + self.logger.debug("added %s to database", item.name) # return created object return await self.get_db_item(item_id) @@ -257,28 +257,28 @@ class AlbumsController(MediaControllerBase[Album]): else: album_type = cur_item.album_type sort_artist = album_artists[0].sort_name if album_artists else "" - - await self.mass.music.database.update( - self.db_table, - {"item_id": item_id}, - { - "name": item.name if overwrite else cur_item.name, - "sort_name": item.sort_name if overwrite else cur_item.sort_name, - "sort_artist": sort_artist, - "version": item.version if overwrite else cur_item.version, - "year": item.year if overwrite else cur_item.year or item.year, - "barcode": ";".join(cur_item.barcode), - "album_type": album_type.value, - "artists": serialize_to_json(album_artists) or None, - "metadata": serialize_to_json(metadata), - "provider_mappings": serialize_to_json(provider_mappings), - "musicbrainz_id": item.musicbrainz_id or cur_item.musicbrainz_id, - "timestamp_modified": int(utc_timestamp()), - }, - ) - # update/set provider_mappings table - await self._set_provider_mappings(item_id, provider_mappings) - self.logger.debug("updated %s in database: %s", item.name, item_id) + async with self._db_add_lock: + await self.mass.music.database.update( + self.db_table, + {"item_id": item_id}, + { + "name": item.name if overwrite else cur_item.name, + "sort_name": item.sort_name if overwrite else cur_item.sort_name, + "sort_artist": sort_artist, + "version": item.version if overwrite else cur_item.version, + "year": item.year if overwrite else cur_item.year or item.year, + "barcode": ";".join(cur_item.barcode), + "album_type": album_type.value, + "artists": serialize_to_json(album_artists) or None, + "metadata": serialize_to_json(metadata), + "provider_mappings": serialize_to_json(provider_mappings), + "musicbrainz_id": item.musicbrainz_id or cur_item.musicbrainz_id, + "timestamp_modified": int(utc_timestamp()), + }, + ) + # update/set provider_mappings table + await self._set_provider_mappings(item_id, provider_mappings) + self.logger.debug("updated %s in database: %s", item.name, item_id) return await self.get_db_item(item_id) async def _get_provider_album_tracks( diff --git a/music_assistant/server/controllers/media/artists.py b/music_assistant/server/controllers/media/artists.py index d0ddc7ba..d88831e0 100644 --- a/music_assistant/server/controllers/media/artists.py +++ b/music_assistant/server/controllers/media/artists.py @@ -315,9 +315,9 @@ class ArtistsController(MediaControllerBase[Artist]): async with self._db_add_lock: new_item = await self.mass.music.database.insert(self.db_table, item.to_db_row()) item_id = new_item["item_id"] - # update/set provider_mappings table - await self._set_provider_mappings(item_id, item.provider_mappings) - self.logger.debug("added %s to database", item.name) + # update/set provider_mappings table + await self._set_provider_mappings(item_id, item.provider_mappings) + self.logger.debug("added %s to database", item.name) # return created object return await self.get_db_item(item_id) @@ -336,22 +336,22 @@ class ArtistsController(MediaControllerBase[Artist]): item.musicbrainz_id = VARIOUS_ARTISTS_ID if item.musicbrainz_id == VARIOUS_ARTISTS_ID: item.name = VARIOUS_ARTISTS - - await self.mass.music.database.update( - self.db_table, - {"item_id": item_id}, - { - "name": item.name if overwrite else cur_item.name, - "sort_name": item.sort_name if overwrite else cur_item.sort_name, - "musicbrainz_id": musicbrainz_id, - "metadata": serialize_to_json(metadata), - "provider_mappings": serialize_to_json(provider_mappings), - "timestamp_modified": int(utc_timestamp()), - }, - ) - # update/set provider_mappings table - await self._set_provider_mappings(item_id, provider_mappings) - self.logger.debug("updated %s in database: %s", item.name, item_id) + async with self._db_add_lock: + await self.mass.music.database.update( + self.db_table, + {"item_id": item_id}, + { + "name": item.name if overwrite else cur_item.name, + "sort_name": item.sort_name if overwrite else cur_item.sort_name, + "musicbrainz_id": musicbrainz_id, + "metadata": serialize_to_json(metadata), + "provider_mappings": serialize_to_json(provider_mappings), + "timestamp_modified": int(utc_timestamp()), + }, + ) + # update/set provider_mappings table + await self._set_provider_mappings(item_id, provider_mappings) + self.logger.debug("updated %s in database: %s", item.name, item_id) return await self.get_db_item(item_id) async def _get_provider_dynamic_tracks( diff --git a/music_assistant/server/controllers/media/playlists.py b/music_assistant/server/controllers/media/playlists.py index cd3b1a91..007aded0 100644 --- a/music_assistant/server/controllers/media/playlists.py +++ b/music_assistant/server/controllers/media/playlists.py @@ -203,9 +203,9 @@ class PlaylistController(MediaControllerBase[Playlist]): async with self._db_add_lock: new_item = await self.mass.music.database.insert(self.db_table, item.to_db_row()) item_id = new_item["item_id"] - # update/set provider_mappings table - await self._set_provider_mappings(item_id, item.provider_mappings) - self.logger.debug("added %s to database", item.name) + # update/set provider_mappings table + await self._set_provider_mappings(item_id, item.provider_mappings) + self.logger.debug("added %s to database", item.name) # return created object return await self.get_db_item(item_id) @@ -216,23 +216,24 @@ class PlaylistController(MediaControllerBase[Playlist]): cur_item = await self.get_db_item(item_id) metadata = cur_item.metadata.update(getattr(item, "metadata", None), overwrite) provider_mappings = self._get_provider_mappings(cur_item, item, overwrite) - await self.mass.music.database.update( - self.db_table, - {"item_id": item_id}, - { - # always prefer name/owner from updated item here - "name": item.name or cur_item.name, - "sort_name": item.sort_name or cur_item.sort_name, - "owner": item.owner or cur_item.sort_name, - "is_editable": item.is_editable, - "metadata": serialize_to_json(metadata), - "provider_mappings": serialize_to_json(provider_mappings), - "timestamp_modified": int(utc_timestamp()), - }, - ) - # update/set provider_mappings table - await self._set_provider_mappings(item_id, provider_mappings) - self.logger.debug("updated %s in database: %s", item.name, item_id) + async with self._db_add_lock: + await self.mass.music.database.update( + self.db_table, + {"item_id": item_id}, + { + # always prefer name/owner from updated item here + "name": item.name or cur_item.name, + "sort_name": item.sort_name or cur_item.sort_name, + "owner": item.owner or cur_item.sort_name, + "is_editable": item.is_editable, + "metadata": serialize_to_json(metadata), + "provider_mappings": serialize_to_json(provider_mappings), + "timestamp_modified": int(utc_timestamp()), + }, + ) + # update/set provider_mappings table + await self._set_provider_mappings(item_id, provider_mappings) + self.logger.debug("updated %s in database: %s", item.name, item_id) return await self.get_db_item(item_id) async def _get_provider_playlist_tracks( diff --git a/music_assistant/server/controllers/media/radio.py b/music_assistant/server/controllers/media/radio.py index 4ab86782..2779298b 100644 --- a/music_assistant/server/controllers/media/radio.py +++ b/music_assistant/server/controllers/media/radio.py @@ -89,9 +89,9 @@ class RadioController(MediaControllerBase[Radio]): async with self._db_add_lock: new_item = await self.mass.music.database.insert(self.db_table, item.to_db_row()) item_id = new_item["item_id"] - # update/set provider_mappings table - await self._set_provider_mappings(item_id, item.provider_mappings) - self.logger.debug("added %s to database", item.name) + # update/set provider_mappings table + await self._set_provider_mappings(item_id, item.provider_mappings) + self.logger.debug("added %s to database", item.name) # return created object return await self.get_db_item(item_id) @@ -101,21 +101,22 @@ class RadioController(MediaControllerBase[Radio]): metadata = cur_item.metadata.update(getattr(item, "metadata", None), overwrite) provider_mappings = self._get_provider_mappings(cur_item, item, overwrite) match = {"item_id": item_id} - await self.mass.music.database.update( - self.db_table, - match, - { - # always prefer name from updated item here - "name": item.name or cur_item.name, - "sort_name": item.sort_name or cur_item.sort_name, - "metadata": serialize_to_json(metadata), - "provider_mappings": serialize_to_json(provider_mappings), - "timestamp_modified": int(utc_timestamp()), - }, - ) - # update/set provider_mappings table - await self._set_provider_mappings(item_id, provider_mappings) - self.logger.debug("updated %s in database: %s", item.name, item_id) + async with self._db_add_lock: + await self.mass.music.database.update( + self.db_table, + match, + { + # always prefer name from updated item here + "name": item.name or cur_item.name, + "sort_name": item.sort_name or cur_item.sort_name, + "metadata": serialize_to_json(metadata), + "provider_mappings": serialize_to_json(provider_mappings), + "timestamp_modified": int(utc_timestamp()), + }, + ) + # update/set provider_mappings table + await self._set_provider_mappings(item_id, provider_mappings) + self.logger.debug("updated %s in database: %s", item.name, item_id) return await self.get_db_item(item_id) async def _get_provider_dynamic_tracks( diff --git a/music_assistant/server/controllers/media/tracks.py b/music_assistant/server/controllers/media/tracks.py index 47d982f0..571f15fb 100644 --- a/music_assistant/server/controllers/media/tracks.py +++ b/music_assistant/server/controllers/media/tracks.py @@ -319,10 +319,10 @@ class TracksController(MediaControllerBase[Track]): }, ) item_id = new_item["item_id"] - # update/set provider_mappings table - await self._set_provider_mappings(item_id, item.provider_mappings) - # return created object - self.logger.debug("added %s to database: %s", item.name, item_id) + # update/set provider_mappings table + await self._set_provider_mappings(item_id, item.provider_mappings) + # return created object + self.logger.debug("added %s to database: %s", item.name, item_id) return await self.get_db_item(item_id) async def _update_db_item( @@ -336,25 +336,26 @@ class TracksController(MediaControllerBase[Track]): cur_item.isrc.update(item.isrc) track_artists = await self._get_artist_mappings(cur_item, item) track_albums = await self._get_track_albums(cur_item, item) - await self.mass.music.database.update( - self.db_table, - {"item_id": item_id}, - { - "name": item.name or cur_item.name, - "sort_name": item.sort_name or cur_item.sort_name, - "version": item.version or cur_item.version, - "duration": getattr(item, "duration", None) or cur_item.duration, - "artists": serialize_to_json(track_artists), - "albums": serialize_to_json(track_albums), - "metadata": serialize_to_json(metadata), - "provider_mappings": serialize_to_json(provider_mappings), - "isrc": ";".join(cur_item.isrc), - "timestamp_modified": int(utc_timestamp()), - }, - ) - # update/set provider_mappings table - await self._set_provider_mappings(item_id, provider_mappings) - self.logger.debug("updated %s in database: %s", item.name, item_id) + async with self._db_add_lock: + await self.mass.music.database.update( + self.db_table, + {"item_id": item_id}, + { + "name": item.name or cur_item.name, + "sort_name": item.sort_name or cur_item.sort_name, + "version": item.version or cur_item.version, + "duration": getattr(item, "duration", None) or cur_item.duration, + "artists": serialize_to_json(track_artists), + "albums": serialize_to_json(track_albums), + "metadata": serialize_to_json(metadata), + "provider_mappings": serialize_to_json(provider_mappings), + "isrc": ";".join(cur_item.isrc), + "timestamp_modified": int(utc_timestamp()), + }, + ) + # update/set provider_mappings table + await self._set_provider_mappings(item_id, provider_mappings) + self.logger.debug("updated %s in database: %s", item.name, item_id) return await self.get_db_item(item_id) async def _get_track_albums( -- 2.34.1