Skip to content

Commit

Permalink
Feat: Use dedicated directory for cache files
Browse files Browse the repository at this point in the history
this makes it easier to exclude it from backups
  • Loading branch information
marcelveldt committed Nov 3, 2024
1 parent cec5e7f commit 5ab2d36
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 14 deletions.
2 changes: 1 addition & 1 deletion music_assistant/controllers/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ async def auto_cleanup(self) -> None:

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()

Expand Down
2 changes: 1 addition & 1 deletion music_assistant/controllers/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ async def setup(self, config: CoreConfig) -> None:
# 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)
Expand Down
24 changes: 24 additions & 0 deletions music_assistant/mass.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@

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[
Expand Down Expand Up @@ -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] = {}
Expand Down Expand Up @@ -123,6 +128,8 @@ async def start(self) -> None:
# 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,
Expand Down Expand Up @@ -770,3 +777,20 @@ async def _update_available_providers_cache(self) -> None:
},
}
)

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)
17 changes: 5 additions & 12 deletions music_assistant/providers/spotify/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@

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,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -558,9 +557,7 @@ async def get_audio_stream(
args = [
librespot,
"--cache",
CACHE_DIR,
"--system-cache",
self.config_dir,
self.cache_dir,
"--cache-size-limit",
"1G",
"--passthrough",
Expand Down Expand Up @@ -824,20 +821,16 @@ async def login(self, force_refresh: bool = False) -> dict:
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)
if ret_code != 0:
# 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"],
]
Expand Down

0 comments on commit 5ab2d36

Please sign in to comment.