From c14ec4ba4b769ca61c06919ea39afb06b9aaca28 Mon Sep 17 00:00:00 2001 From: cwilvx Date: Sun, 11 May 2025 14:10:28 +0300 Subject: [PATCH] fix: multiprocessing problems --- app/db/engine.py | 28 ++++++++++++++++++++++++++-- app/lib/artistlib.py | 5 +---- app/lib/tagger.py | 2 +- app/settings.py | 6 +++++- app/setup/sqlite.py | 2 +- main.py | 11 ++++++++--- 6 files changed, 42 insertions(+), 12 deletions(-) diff --git a/app/db/engine.py b/app/db/engine.py index 6ea7d4cf..0ff3a7bc 100644 --- a/app/db/engine.py +++ b/app/db/engine.py @@ -1,7 +1,9 @@ from contextlib import contextmanager -from sqlalchemy import Engine, event +from sqlalchemy import Engine, create_engine, event from sqlalchemy.orm import sessionmaker +from app.settings import DbPaths + @event.listens_for(Engine, "connect") def set_sqlite_pragma(dbapi_connection, connection_record): @@ -14,13 +16,35 @@ def set_sqlite_pragma(dbapi_connection, connection_record): cursor.execute("PRAGMA mmap_size=0") cursor.close() +class classproperty(property): + """ + A class property decorator. + """ + + def __get__(self, owner_self, owner_cls): + if self.fget: + return self.fget(owner_cls) + + class DbEngine: """ The database engine instance. """ - engine: Engine + _engine: Engine | None = None + + @classproperty + def engine(cls) -> Engine: + if not cls._engine: + cls._engine = create_engine( + f"sqlite+pysqlite:///{DbPaths.get_app_db_path()}", + echo=False, + max_overflow=20, + pool_size=10, + ) + + return cls._engine @classmethod @contextmanager diff --git a/app/lib/artistlib.py b/app/lib/artistlib.py index 49662a99..c9d68d92 100644 --- a/app/lib/artistlib.py +++ b/app/lib/artistlib.py @@ -1,9 +1,8 @@ -import math import os import time +import random import urllib import requests -import multiprocessing from io import BytesIO from pathlib import Path @@ -29,8 +28,6 @@ LARGE_ENOUGH_NUMBER = 100 PngImagePlugin.MAX_TEXT_CHUNK = LARGE_ENOUGH_NUMBER * (1024**2) # https://stackoverflow.com/a/61466412 -import random - def get_artist_image_link(artist: str): """ diff --git a/app/lib/tagger.py b/app/lib/tagger.py index 67e71b5d..a3e8e9d0 100644 --- a/app/lib/tagger.py +++ b/app/lib/tagger.py @@ -69,7 +69,7 @@ class IndexTracks: extract_thumb( track["filepath"], track["albumhash"] + ".webp", overwrite=True ) - except FileNotFoundError: + except (FileNotFoundError, KeyError): continue @staticmethod diff --git a/app/settings.py b/app/settings.py index c2f7f984..b3a37f02 100644 --- a/app/settings.py +++ b/app/settings.py @@ -29,7 +29,11 @@ class Paths: @classmethod def get_config_dir(cls): - return cls.XDG_CONFIG_DIR or os.path.realpath(".") + return ( + cls.XDG_CONFIG_DIR + or os.environ.get("SWINGMUSIC_XDG_CONFIG_DIR") + or os.path.realpath(".") + ) @classmethod def get_config_folder(cls): diff --git a/app/setup/sqlite.py b/app/setup/sqlite.py index 3fbb6add..cb5c7f30 100644 --- a/app/setup/sqlite.py +++ b/app/setup/sqlite.py @@ -24,7 +24,7 @@ def setup_sqlite(): """ Create Sqlite databases and tables. """ - DbEngine.engine = create_engine( + DbEngine._engine = create_engine( f"sqlite+pysqlite:///{DbPaths.get_app_db_path()}", echo=False, max_overflow=20, diff --git a/main.py b/main.py index 6b978c8b..20cfb59e 100644 --- a/main.py +++ b/main.py @@ -1,7 +1,8 @@ -import multiprocessing -import pathlib -import click +import os import sys +import click +import pathlib +import multiprocessing from app.arg_handler import handle_build, handle_password_reset from app.utils.filesystem import get_home_res_path from app.utils.xdg_utils import get_xdg_config_dir @@ -66,6 +67,10 @@ def version(*args, **kwargs): is_eager=True, ) def run(*args, **kwargs): + # INFO: Set the config dir as an environment variable + os.environ["SWINGMUSIC_XDG_CONFIG_DIR"] = str( + pathlib.Path(kwargs["config"]).resolve() + ) run_app(kwargs["host"], kwargs["port"], kwargs["config"])