From bcec245d876bd1c3239ee7523ffedf7f72d763ba Mon Sep 17 00:00:00 2001 From: Marcel van der Veldt Date: Tue, 16 Apr 2024 09:53:28 +0200 Subject: [PATCH] fix migration of url provider --- music_assistant/constants.py | 2 +- music_assistant/server/controllers/music.py | 32 +------------- .../server/providers/builtin/__init__.py | 42 ++++++++++++++++--- .../providers/filesystem_local/__init__.py | 2 +- 4 files changed, 41 insertions(+), 37 deletions(-) diff --git a/music_assistant/constants.py b/music_assistant/constants.py index 6ba1e210..52a6272e 100644 --- a/music_assistant/constants.py +++ b/music_assistant/constants.py @@ -5,7 +5,7 @@ from typing import Final API_SCHEMA_VERSION: Final[int] = 24 MIN_SCHEMA_VERSION: Final[int] = 24 -DB_SCHEMA_VERSION: Final[int] = 30 +DB_SCHEMA_VERSION: Final[int] = 29 MASS_LOGGER_NAME: Final[str] = "music_assistant" diff --git a/music_assistant/server/controllers/music.py b/music_assistant/server/controllers/music.py index 48f12474..02d3da99 100644 --- a/music_assistant/server/controllers/music.py +++ b/music_assistant/server/controllers/music.py @@ -27,12 +27,7 @@ from music_assistant.common.models.errors import ( MusicAssistantError, ProviderUnavailableError, ) -from music_assistant.common.models.media_items import ( - BrowseFolder, - MediaItemType, - ProviderMapping, - SearchResults, -) +from music_assistant.common.models.media_items import BrowseFolder, MediaItemType, SearchResults from music_assistant.common.models.provider import SyncTask from music_assistant.common.models.streamdetails import LoudnessMeasurement from music_assistant.constants import ( @@ -750,31 +745,8 @@ class MusicController(CoreController): db_path_backup = db_path + ".backup" await asyncio.to_thread(shutil.copyfile, db_path, db_path_backup) - # handle db migration to 30: uri provider --> builtin provider - if prev_version < 30: - await self.mass.cache.clear("url") - for ctrl in ( - self.mass.music.radio, - self.mass.music.tracks, - self.mass.music.artists, - ): - prov_items = await ctrl.get_library_items_by_prov_id("url") - for item in prov_items: - try: - await ctrl.add_provider_mapping( - item.item_id, - ProviderMapping( - item_id=item.item_id, - provider_domain="builtin", - provider_instance="builtin", # yeah, we're cheating here - ), - ) - await ctrl.remove_provider_mappings(item.item_id, "url") - except Exception as err: - self.logger.exception(err) - # handle db migration from previous schema to this one - if prev_version in (27, 28, 29): + if prev_version in (27, 28): self.logger.info( "Performing database migration from %s to %s", prev_version, diff --git a/music_assistant/server/providers/builtin/__init__.py b/music_assistant/server/providers/builtin/__init__.py index 320c22bb..217a49a9 100644 --- a/music_assistant/server/providers/builtin/__init__.py +++ b/music_assistant/server/providers/builtin/__init__.py @@ -131,11 +131,43 @@ async def get_config_entries( class BuiltinProvider(MusicProvider): """Built-in/generic provider to handle (manually added) media from files and (remote) urls.""" - def __init__( - self, mass: MusicAssistant, manifest: ProviderManifest, config: ProviderConfig - ) -> None: - """Initialize MusicProvider.""" - super().__init__(mass, manifest, config) + async def loaded_in_mass(self) -> None: + """Call after the provider has been loaded.""" + # TEMP: Migrate URL provider entries to builtin + # TODO: Remove this once 2.0 is released! + cache_key = f"{self.instance_id}.url_migration_done" + if await self.mass.cache.get(cache_key): + return + self.logger.info("Starting migration...") + url_instance_id: str | None = None + for ctrl in ( + self.mass.music.radio, + self.mass.music.tracks, + self.mass.music.artists, + ): + prov_items = await ctrl.get_library_items_by_prov_id("url") + for item in prov_items: + try: + existing_mapping = next( + x for x in item.provider_mappings if x.provider_domain == "url" + ) + # add new prov mapping for the builtin provider + new_mapping = ProviderMapping.from_dict(existing_mapping.to_dict()) + new_mapping.provider_instance = self.instance_id + new_mapping.provider_domain = self.domain + new_mapping.available = True + await ctrl.add_provider_mapping(item.item_id, new_mapping) + await self.library_add(item) + # lookup instance id of the url provider if we dont have it yet + url_instance_id = existing_mapping.provider_instance + # remove the old provider mapping for url provider + await ctrl.remove_provider_mappings(item.item_id, url_instance_id) + self.logger.info("Migrated item %s", item.name) + except Exception as err: + self.logger.exception(err) + if url_instance_id: + await self.mass.cache.clear(url_instance_id) + await self.mass.cache.set(cache_key, True, expiration=365 * 86400) @property def is_streaming_provider(self) -> bool: diff --git a/music_assistant/server/providers/filesystem_local/__init__.py b/music_assistant/server/providers/filesystem_local/__init__.py index c00eaf9a..32e5fafd 100644 --- a/music_assistant/server/providers/filesystem_local/__init__.py +++ b/music_assistant/server/providers/filesystem_local/__init__.py @@ -212,7 +212,7 @@ class LocalFileSystemProvider(FileSystemProviderBase): # so the filesystem is not longer polluted/abused for this. # this code hunts these playlists, migrates them to the universal provider # and cleans up the files. - cache_key = f"{self.instance_id}.playlist_migrattion_done" + cache_key = f"{self.instance_id}.playlist_migration_done" if await self.mass.cache.get(cache_key): return self.logger.info("Starting playlist migration...") -- 2.34.1