From: Marcel van der Veldt Date: Sun, 3 Nov 2024 13:15:42 +0000 (+0100) Subject: Feat: Use dedicated directory for cache files X-Git-Url: https://git.kitaultman.com/?a=commitdiff_plain;h=5ab2d369f1a606b80a2c170df5c3218281c425cf;p=music-assistant-server.git Feat: Use dedicated directory for cache files this makes it easier to exclude it from backups --- diff --git a/music_assistant/controllers/cache.py b/music_assistant/controllers/cache.py index 687b3374..9df242f5 100644 --- a/music_assistant/controllers/cache.py +++ b/music_assistant/controllers/cache.py @@ -210,7 +210,7 @@ class CacheController(CoreController): async def _setup_database(self) -> None: """Initialize database.""" - db_path = os.path.join(self.mass.storage_path, "cache.db") + db_path = os.path.join(self.mass.cache_path, "cache.db") self.database = DatabaseConnection(db_path) await self.database.setup() diff --git a/music_assistant/controllers/metadata.py b/music_assistant/controllers/metadata.py index 9eab843d..1aadabe9 100644 --- a/music_assistant/controllers/metadata.py +++ b/music_assistant/controllers/metadata.py @@ -172,7 +172,7 @@ class MetaDataController(CoreController): # silence PIL logger logging.getLogger("PIL").setLevel(logging.WARNING) # make sure that our directory with collage images exists - self._collage_images_dir = os.path.join(self.mass.storage_path, "collage_images") + self._collage_images_dir = os.path.join(self.mass.cache_path, "collage_images") if not await asyncio.to_thread(os.path.exists, self._collage_images_dir): await asyncio.to_thread(os.mkdir, self._collage_images_dir) self.mass.streams.register_dynamic_route("/imageproxy", self.handle_imageproxy) diff --git a/music_assistant/mass.py b/music_assistant/mass.py index f183c683..5f2174d5 100644 --- a/music_assistant/mass.py +++ b/music_assistant/mass.py @@ -58,6 +58,10 @@ if TYPE_CHECKING: isdir = wrap(os.path.isdir) isfile = wrap(os.path.isfile) +mkdirs = wrap(os.makedirs) +rmfile = wrap(os.remove) +listdir = wrap(os.listdir) +rename = wrap(os.rename) EventCallBackType = Callable[[MassEvent], None] EventSubscriptionType = tuple[ @@ -90,6 +94,7 @@ class MusicAssistant: def __init__(self, storage_path: str, safe_mode: bool = False) -> None: """Initialize the MusicAssistant Server.""" self.storage_path = storage_path + self.cache_path = os.path.join(storage_path, ".cache") self.safe_mode = safe_mode # we dynamically register command handlers which can be consumed by the apis self.command_handlers: dict[str, APICommandHandler] = {} @@ -123,6 +128,8 @@ class MusicAssistant: # setup config controller first and fetch important config values self.config = ConfigController(self) await self.config.setup() + # setup/migrate storage + await self._setup_storage() LOGGER.info( "Starting Music Assistant Server (%s) version %s - HA add-on: %s - Safe mode: %s", self.server_id, @@ -770,3 +777,20 @@ class MusicAssistant: }, } ) + + async def _setup_storage(self) -> None: + """Handle Setup of storage/cache folder(s).""" + if not await isdir(self.storage_path): + await mkdirs(self.storage_path) + if not await isdir(self.cache_path): + await mkdirs(self.cache_path) + # cleanup old cache files from their old locations + # TODO: Remove this code after MA version 2.5+ + old_cache_db = os.path.join(self.storage_path, "cache.db") + if await isfile(old_cache_db): + await rmfile(old_cache_db) + for filename in await listdir(self.storage_path): + if filename.startswith(("spotify", "collage")): + old_loc = os.path.join(self.storage_path, filename) + new_loc = os.path.join(self.cache_path, filename) + await rename(old_loc, new_loc) diff --git a/music_assistant/providers/spotify/__init__.py b/music_assistant/providers/spotify/__init__.py index 1d78f9eb..abc1770a 100644 --- a/music_assistant/providers/spotify/__init__.py +++ b/music_assistant/providers/spotify/__init__.py @@ -90,7 +90,6 @@ SCOPE = [ CALLBACK_REDIRECT_URL = "https://music-assistant.io/callback" -CACHE_DIR = "/tmp/spotify_cache" # noqa: S108 LIKED_SONGS_FAKE_PLAYLIST_ID_PREFIX = "liked_songs" SUPPORTED_FEATURES = ( ProviderFeature.LIBRARY_ARTISTS, @@ -246,7 +245,7 @@ class SpotifyProvider(MusicProvider): async def handle_async_init(self) -> None: """Handle async initialization of the provider.""" - self.config_dir = os.path.join(self.mass.storage_path, self.instance_id) + self.cache_dir = os.path.join(self.mass.cache_path, self.instance_id) self.throttler = ThrottlerManager(rate_limit=1, period=2) if self.config.get_value(CONF_CLIENT_ID): # loosen the throttler a bit when a custom client id is used @@ -558,9 +557,7 @@ class SpotifyProvider(MusicProvider): args = [ librespot, "--cache", - CACHE_DIR, - "--system-cache", - self.config_dir, + self.cache_dir, "--cache-size-limit", "1G", "--passthrough", @@ -824,8 +821,8 @@ class SpotifyProvider(MusicProvider): librespot = await self.get_librespot_binary() args = [ librespot, - "--system-cache", - self.config_dir, + "--cache", + self.cache_dir, "--check-auth", ] ret_code, stdout = await check_output(*args) @@ -833,11 +830,7 @@ class SpotifyProvider(MusicProvider): # cached librespot creds are invalid, re-authenticate # we can use the check-token option to send a new token to librespot # librespot will then get its own token from spotify (somehow) and cache that. - args = [ - librespot, - "--system-cache", - self.config_dir, - "--check-auth", + args += [ "--access-token", auth_info["access_token"], ]