mirror of
https://github.com/Dvorinka/swingmusic-extended.git
synced 2026-06-03 20:13:02 +00:00
4a9f804e70
+ port populate to new db interface
+ add genrehashes and hash info to tracks
+ properly structure new db table files
+ move helpers to dedicated utils file
+ move settings from db to config file
+ move artists, albums, auth and favorites endpoint to new db interface
+ use folder store to index filepaths
+ paginate favorite pages
+ 56 moretiny changes 😅
96 lines
2.6 KiB
Python
96 lines
2.6 KiB
Python
from sortedcontainers import SortedSet
|
|
from concurrent.futures import ThreadPoolExecutor
|
|
|
|
from app.db.libdata import TrackTable
|
|
|
|
|
|
class FolderStore:
|
|
"""
|
|
The Folder store is used to hold all the indexed tracks filepaths in memory
|
|
for fast count operations when browsing the folder page.
|
|
|
|
Counting from the database is super slow, even with a small number of folders to get the count for. Up to 700ms for 10 folders. By using this store, we are able to reduce that to less than 10ms.
|
|
"""
|
|
|
|
filepaths: SortedSet = SortedSet()
|
|
|
|
@classmethod
|
|
def load_filepaths(cls):
|
|
"""
|
|
Load all the filepaths from the database into memory.
|
|
|
|
This is needed to speed up the process of counting the number of tracks in the folder page.
|
|
"""
|
|
cls.filepaths.clear()
|
|
|
|
tracks = TrackTable.get_all()
|
|
for track in tracks:
|
|
cls.filepaths.add(track.filepath)
|
|
|
|
|
|
@classmethod
|
|
def count_tracks_containing_paths(cls, paths: list[str]):
|
|
"""
|
|
Count the number of tracks in each directory.
|
|
|
|
Uses a ThreadPoolExecutor to count the number of tracks
|
|
in each directory for fast execution time.
|
|
"""
|
|
results: list[dict[str, int | str]] = []
|
|
|
|
with ThreadPoolExecutor() as executor:
|
|
res = executor.map(countFilepathsInDir, paths)
|
|
results = [
|
|
{"path": path, "trackcount": count} for path, count in zip(paths, res)
|
|
]
|
|
|
|
return results
|
|
|
|
|
|
def getIndexOfFirstMatch(strings: list[str], prefix: str):
|
|
"""
|
|
Find the index of the first path that starts with the given path.
|
|
|
|
Uses a binary search algorithm to find the index.
|
|
"""
|
|
|
|
left = 0
|
|
right = len(strings) - 1
|
|
|
|
while left <= right:
|
|
mid = (left + right) // 2
|
|
|
|
if strings[mid].startswith(prefix):
|
|
if mid == 0 or not strings[mid - 1].startswith(prefix):
|
|
return mid
|
|
right = mid - 1
|
|
elif strings[mid] < prefix:
|
|
left = mid + 1
|
|
else:
|
|
right = mid - 1
|
|
|
|
return -1
|
|
|
|
|
|
def countFilepathsInDir(dirpath: str):
|
|
"""
|
|
Counts the number of filepaths that start with the given directory path.
|
|
|
|
Gets the index of the first path that starts with the given directory path,
|
|
then checks each path after that to see if it starts with the given directory path.
|
|
"""
|
|
index = getIndexOfFirstMatch(FolderStore.filepaths, dirpath)
|
|
|
|
if index == -1:
|
|
return 0
|
|
|
|
paths: list[str] = []
|
|
|
|
for path in FolderStore.filepaths[index:]:
|
|
if path.startswith(dirpath):
|
|
paths.append(path)
|
|
else:
|
|
break
|
|
|
|
return len(paths)
|