Continued converting the CacheManager results to give the result immediately when cached

This commit is contained in:
Sumner Evans
2019-12-27 21:00:47 -07:00
parent 3a355072e9
commit bb46eadd49
2 changed files with 100 additions and 83 deletions

View File

@@ -7,7 +7,7 @@ import hashlib
from collections import defaultdict
from time import sleep
from concurrent.futures import ThreadPoolExecutor, Future
from concurrent.futures import ThreadPoolExecutor, Future, as_completed
from enum import EnumMeta, Enum
from datetime import datetime
from pathlib import Path
@@ -176,7 +176,7 @@ class CacheManager(metaclass=Singleton):
# TODO need to split out the song downloads and make them higher
# priority I think. Maybe even need to just make this a priority queue.
download_set_lock = threading.Lock()
current_downloads: Set[Path] = set()
current_downloads: Set[str] = set()
def __init__(
self,
@@ -298,7 +298,7 @@ class CacheManager(metaclass=Singleton):
return CacheManager.Result.from_data(abs_path_str)
if not allow_download:
return CacheManager.Result.from_data(None)
return CacheManager.Result.from_data('')
def do_download() -> str:
# TODO
@@ -332,7 +332,7 @@ class CacheManager(metaclass=Singleton):
print(abs_path, 'downloaded. Returning.')
return abs_path_str
def after_download(path):
def after_download(path: str):
with self.download_set_lock:
self.current_downloads.discard(path)
@@ -570,45 +570,52 @@ class CacheManager(metaclass=Singleton):
force: bool = False,
# Look at documentation for get_album_list in server.py:
**params,
) -> Future:
) -> 'CacheManager.Result[List[Union[Child, AlbumWithSongsID3]]]':
cache_name = self.id3ify('albums')
if (len(self.cache.get(cache_name, {}).get(type_, [])) > 0
and not force):
return CacheManager.Result.from_data(
self.cache[cache_name][type_])
server_fn = (
self.server.get_album_list2
if self.browse_by_tags else self.server.get_album_list)
def get_page(offset, page_size=500):
return server_fn(
type_,
size=page_size,
offset=offset,
**params,
).album or []
def do_get_album_list() -> List[Union[Child, AlbumWithSongsID3]]:
if not self.cache.get(cache_name, {}).get(type_, []) or force:
before_download()
def get_page(offset, page_size=500):
return server_fn(
type_,
size=page_size,
offset=offset,
**params,
).album or []
page_size = 40 if type_ == 'random' else 500
offset = 0
page_size = 40 if type_ == 'random' else 500
offset = 0
next_page = get_page(offset, page_size=page_size)
albums = next_page
next_page = get_page(offset, page_size=page_size)
albums = next_page
# If it returns 500 things, then there's more leftover.
while len(next_page) == 500:
next_page = get_page(offset)
albums.extend(next_page)
# If it returns 500 things, then there's more leftover.
while len(next_page) == 500:
next_page = get_page(offset)
albums.extend(next_page)
# Update the cache.
with self.cache_lock:
if not self.cache[cache_name].get(type_):
self.cache[cache_name][type_] = []
self.cache[cache_name][type_] = albums
self.save_cache_info()
return albums
return self.cache[cache_name][type_]
def after_download(albums):
with self.cache_lock:
if not self.cache[cache_name].get(type_):
self.cache[cache_name][type_] = []
self.cache[cache_name][type_] = albums
self.save_cache_info()
return CacheManager.create_future(do_get_album_list)
return CacheManager.Result.from_server(
do_get_album_list,
before_download=before_download,
after_download=after_download,
)
def invalidate_album_list(self, type_):
# TODO make this invalidate instead of delete
@@ -624,25 +631,27 @@ class CacheManager(metaclass=Singleton):
album_id,
before_download: Callable[[], None] = lambda: None,
force: bool = False,
) -> Future:
def do_get_album() -> Union[AlbumWithSongsID3, Child]:
cache_name = self.id3ify('album_details')
server_fn = (
self.server.get_album if self.browse_by_tags else
self.server.get_music_directory)
) -> 'CacheManager.Result[Union[AlbumWithSongsID3, Child]]':
cache_name = self.id3ify('album_details')
if album_id not in self.cache.get(cache_name, {}) or force:
before_download()
album = server_fn(album_id)
if album_id in self.cache.get(cache_name, {}) and not force:
return CacheManager.Result.from_data(
self.cache[cache_name][album_id])
with self.cache_lock:
self.cache[cache_name][album_id] = album
server_fn = (
self.server.get_album
if self.browse_by_tags else self.server.get_music_directory)
self.save_cache_info()
def after_download(album):
with self.cache_lock:
self.cache[cache_name][album_id] = album
self.save_cache_info()
return self.cache[cache_name][album_id]
return CacheManager.create_future(do_get_album)
return CacheManager.Result.from_server(
lambda: server_fn(album_id),
before_download=before_download,
after_download=after_download,
)
def batch_delete_cached_songs(
self,
@@ -651,18 +660,13 @@ class CacheManager(metaclass=Singleton):
) -> Future:
def do_delete_cached_songs():
# Do the actual download.
for song_id in song_ids:
song_details_future = CacheManager.get_song_details(
song_id)
def filename_future_done(f):
relative_path = f.result().path
abs_path = self.calculate_abs_path(relative_path)
if abs_path.exists():
abs_path.unlink()
on_song_delete()
song_details_future.add_done_callback(filename_future_done)
for f in as_completed(map(CacheManager.get_song_details,
song_ids)):
relative_path = f.result().path
abs_path = self.calculate_abs_path(relative_path)
if abs_path.exists():
abs_path.unlink()
on_song_delete()
return CacheManager.create_future(do_delete_cached_songs)
@@ -692,8 +696,6 @@ class CacheManager(metaclass=Singleton):
on_song_download_complete(song_id)
def do_batch_download_songs():
self.current_downloads = self.current_downloads.union(
set(song_ids))
for song_id in song_ids:
# Only allow a certain number of songs ot be downloaded
# simultaneously.
@@ -728,18 +730,21 @@ class CacheManager(metaclass=Singleton):
song_id: int,
before_download: Callable[[], None] = lambda: None,
force: bool = False,
) -> Future:
def do_get_song_details() -> Child:
if not self.cache['song_details'].get(song_id) or force:
before_download()
song_details = self.server.get_song(song_id)
with self.cache_lock:
self.cache['song_details'][song_id] = song_details
self.save_cache_info()
) -> 'CacheManager.Result[Child]':
if self.cache['song_details'].get(song_id) and not force:
return CacheManager.Result.from_data(
self.cache['song_details'][song_id])
return self.cache['song_details'][song_id]
def after_download(song_details):
with self.cache_lock:
self.cache['song_details'][song_id] = song_details
self.save_cache_info()
return CacheManager.create_future(do_get_song_details)
return CacheManager.Result.from_server(
lambda: self.server.get_song(song_id),
before_download=before_download,
after_download=after_download,
)
def get_play_queue(self) -> Future:
return CacheManager.create_future(self.server.get_play_queue)
@@ -778,18 +783,20 @@ class CacheManager(metaclass=Singleton):
self,
before_download: Callable[[], None] = lambda: None,
force: bool = False,
) -> Future:
def do_get_genres() -> List[Genre]:
if not self.cache['genres'] or force:
before_download()
genres = self.server.get_genres().genre
with self.cache_lock:
self.cache['genres'] = genres
self.save_cache_info()
) -> 'CacheManager.Result[List[Genre]]':
if self.cache.get('genres') and not force:
return CacheManager.Result.from_data(self.cache['genres'])
return self.cache['genres']
def after_download(genres):
with self.cache_lock:
self.cache['genres'] = genres
self.save_cache_info()
return CacheManager.create_future(do_get_genres)
return CacheManager.Result.from_server(
lambda: self.server.get_genres().genre,
before_download=before_download,
after_download=after_download,
)
def get_cached_status(self, song: Child) -> SongCacheStatus:
cache_path = self.calculate_abs_path(song.path)
@@ -798,7 +805,7 @@ class CacheManager(metaclass=Singleton):
return SongCacheStatus.PERMANENTLY_CACHED
else:
return SongCacheStatus.CACHED
elif cache_path in self.current_downloads:
elif str(cache_path) in self.current_downloads:
return SongCacheStatus.DOWNLOADING
else:
return SongCacheStatus.NOT_CACHED
@@ -814,4 +821,6 @@ class CacheManager(metaclass=Singleton):
@classmethod
def reset(cls, app_config, server_config):
CacheManager._instance = CacheManager.__CacheManagerInternal(
app_config, server_config)
app_config,
server_config,
)

View File

@@ -1,4 +1,6 @@
import math
import os
from time import sleep
from urllib.parse import urlencode
from deprecated import deprecated
@@ -92,7 +94,13 @@ class Server:
def _get(self, url, **params):
params = {**self._get_params(), **params}
print(f'[START] get: {url}')
sleep(1)
if os.environ.get('SUBLIME_MUSIC_DEBUG_DELAY'):
print(
"SUBLIME_MUSIC_DEBUG_DELAY enabled. Pausing for",
"{os.environ['SUBLIME_MUSIC_DEBUG_DELAY']} seconds.",
)
sleep(int(os.environ['SUBLIME_MUSIC_DEBUG_DELAY']))
# Deal with datetime parameters (convert to milliseconds since 1970)
for k, v in params.items():