diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 393f47d..0fd9451 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1 +1 @@ -custom: ["https://flattr.com/@Krateng", "https://paypal.me/krateng", "bitcoin:1krat8JMniJBTiHftMfR1LtF3Y1w5DAxx"] +custom: ["https://flattr.com/@Krateng", "https://paypal.me/krateng"] diff --git a/maloja/__main__.py b/maloja/__main__.py index c7a57b8..ff24c60 100644 --- a/maloja/__main__.py +++ b/maloja/__main__.py @@ -151,14 +151,13 @@ def main(*args,**kwargs): if "version" in kwargs: print(info.VERSION) + return True else: try: action, *args = args action = actions[action] except (ValueError, KeyError): print("Valid commands: " + " ".join(a for a in actions)) - return + return False return action(*args,**kwargs) - - return True diff --git a/maloja/__pkginfo__.py b/maloja/__pkginfo__.py index f772f7e..ab4d615 100644 --- a/maloja/__pkginfo__.py +++ b/maloja/__pkginfo__.py @@ -4,7 +4,7 @@ # you know what f*ck it # this is hardcoded for now because of that damn project / package name discrepancy # i'll fix it one day -VERSION = "3.0.0" +VERSION = "3.0.2" HOMEPAGE = "https://github.com/krateng/maloja" diff --git a/maloja/apis/native_v1.py b/maloja/apis/native_v1.py index 16cc27d..a03bf90 100644 --- a/maloja/apis/native_v1.py +++ b/maloja/apis/native_v1.py @@ -1,4 +1,5 @@ import os +import math from bottle import response, static_file, request, FormsDict diff --git a/maloja/database/__init__.py b/maloja/database/__init__.py index 61fc8bf..1526f20 100644 --- a/maloja/database/__init__.py +++ b/maloja/database/__init__.py @@ -46,7 +46,7 @@ class DatabaseNotBuilt(HTTPError): def __init__(self): super().__init__( status=503, - body="The Maloja Database is being upgraded to Version 3. This could take several minutes.", + body="The Maloja Database is being upgraded to Version 3. This could take quite a long time! (~ 2-5 minutes per 10 000 scrobbles)", headers={"Retry-After":120} ) diff --git a/maloja/dev/profiler.py b/maloja/dev/profiler.py index e1e041b..7fb3355 100644 --- a/maloja/dev/profiler.py +++ b/maloja/dev/profiler.py @@ -10,24 +10,30 @@ from ..pkg_global.conf import data_dir profiler = cProfile.Profile() +FULL_PROFILE = False + def profile(func): def newfunc(*args,**kwargs): - benchmarkfolder = data_dir['logs']("benchmarks") - os.makedirs(benchmarkfolder,exist_ok=True) + if FULL_PROFILE: + benchmarkfolder = data_dir['logs']("benchmarks") + os.makedirs(benchmarkfolder,exist_ok=True) clock = Clock() clock.start() - profiler.enable() + if FULL_PROFILE: + profiler.enable() result = func(*args,**kwargs) - profiler.disable() + if FULL_PROFILE: + profiler.disable() log(f"Executed {func.__name__} ({args}, {kwargs}) in {clock.stop():.2f}s",module="debug_performance") - try: - pstats.Stats(profiler).dump_stats(os.path.join(benchmarkfolder,f"{func.__name__}.stats")) - except: - pass + if FULL_PROFILE: + try: + pstats.Stats(profiler).dump_stats(os.path.join(benchmarkfolder,f"{func.__name__}.stats")) + except: + pass return result diff --git a/maloja/server.py b/maloja/server.py index 9685148..950cc69 100644 --- a/maloja/server.py +++ b/maloja/server.py @@ -5,6 +5,7 @@ from threading import Thread from importlib import resources from css_html_js_minify import html_minify, css_minify import datauri +import time # server stuff @@ -34,7 +35,7 @@ from .dev.profiler import profile PORT = malojaconfig["PORT"] HOST = malojaconfig["HOST"] -THREADS = 12 +THREADS = 16 BaseRequest.MEMFILE_MAX = 15 * 1024 * 1024 #STATICFOLDER = importlib.resources.path(__name__,"web/static") @@ -233,6 +234,7 @@ def static(path): ### DYNAMIC +@profile def jinja_page(name): if name in aliases: redirect(aliases[name]) keys = remove_identical(FormsDict.decode(request.query)) @@ -292,6 +294,31 @@ def redirect_track(artists,title): ##### +# warning interception +import logging + +class WaitressLogHandler(): + def __init__(self): + self.lastwarned = 0 + self.barrier = 5 + self.level = 20 + self.filters = [] + def handle(self,record): + if record.name == 'waitress.queue': + now = time.time() + depth = record.args[0] + + if depth > self.barrier: + log(f"Waitress Task Queue Depth at {depth}") + self.lastwarned = now + self.barrier = max(depth,self.barrier+5) + elif now - self.lastwarned > 5: + self.barrier = max(5,self.barrier-5) + else: + log(f"Waitress: {record.msg % record.args}") +logging.getLogger().addHandler(WaitressLogHandler()) + + def run_server(): log("Starting up Maloja server...") @@ -299,6 +326,7 @@ def run_server(): Thread(target=database.start_db).start() + try: #run(webserver, host=HOST, port=MAIN_PORT, server='waitress') log(f"Listening on {HOST}:{PORT}") diff --git a/maloja/upgrade.py b/maloja/upgrade.py index 825b41c..75213da 100644 --- a/maloja/upgrade.py +++ b/maloja/upgrade.py @@ -44,7 +44,7 @@ def upgrade_apikeys(): def upgrade_db(callback_add_scrobbles): oldfolder = os.path.join(dir_settings['state'],"scrobbles") - newfolder = os.path.join(dir_settings['state'],".oldscrobbles") + newfolder = os.path.join(dir_settings['state'],".v2scrobbles") os.makedirs(newfolder,exist_ok=True) if os.path.exists(oldfolder): scrobblefiles = [f for f in os.listdir(oldfolder) if f.endswith(".tsv")] @@ -67,7 +67,7 @@ def upgrade_db(callback_add_scrobbles): scrobblelist = [] log(f"\tImporting from {sf} ({idx}/{len(scrobblefiles)}) - {len(scrobbles)} Scrobbles") for scrobble in scrobbles: - timestamp, artists, title, album, duration = scrobble + timestamp, artists, title, album, duration, *_ = scrobble + [None,None] if album in ('-',''): album = None if duration in ('-',''): duration = None scrobblelist.append({ diff --git a/maloja/web/jinja/abstracts/base.jinja b/maloja/web/jinja/abstracts/base.jinja index 29cb70d..8e1645c 100644 --- a/maloja/web/jinja/abstracts/base.jinja +++ b/maloja/web/jinja/abstracts/base.jinja @@ -3,8 +3,10 @@ - {% block title %}{% endblock %} + + + {% block title %}{% endblock %} diff --git a/maloja/web/jinja/admin_overview.jinja b/maloja/web/jinja/admin_overview.jinja index a0fc2f8..36993a6 100644 --- a/maloja/web/jinja/admin_overview.jinja +++ b/maloja/web/jinja/admin_overview.jinja @@ -65,6 +65,7 @@ With Admin Mode activated, you can: diff --git a/maloja/web/jinja/snippets/entityrow.jinja b/maloja/web/jinja/snippets/entityrow.jinja index e44f7fd..58fc46c 100644 --- a/maloja/web/jinja/snippets/entityrow.jinja +++ b/maloja/web/jinja/snippets/entityrow.jinja @@ -2,14 +2,14 @@ {% import 'snippets/links.jinja' as links %} -{% if 'artists' in entity %} +{% if entity is mapping and 'artists' in entity %} {% set img = images.get_track_image(entity) %} {% else %} {% set img = images.get_artist_image(entity) %} {% endif %}
-{% if "artists" in entity %} +{% if entity is mapping and 'artists' in entity %} {% if settings['TRACK_SEARCH_PROVIDER'] %} {{ links.link_search(entity) }} {% endif %} diff --git a/maloja/web/jinja/snippets/links.jinja b/maloja/web/jinja/snippets/links.jinja index f66bd3b..bb014e1 100644 --- a/maloja/web/jinja/snippets/links.jinja +++ b/maloja/web/jinja/snippets/links.jinja @@ -1,5 +1,5 @@ {% macro link(entity) -%} - {% if 'artists' in entity %} + {% if entity is mapping and 'artists' in entity %} {% set name = entity.title %} {% else %} {% set name = entity %} @@ -17,7 +17,7 @@ {% macro url(entity) %} - {% if 'artists' in entity -%} + {% if entity is mapping and 'artists' in entity -%} {{ mlj_uri.create_uri("/track",{'track':entity}) }} {%- else -%} {{ mlj_uri.create_uri("/artist",{'artist':entity}) }} diff --git a/pyproject.toml b/pyproject.toml index a007378..5d516e2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "malojaserver" -version = "3.0.0" +version = "3.0.2" description = "Self-hosted music scrobble database" readme = "./README.md" requires-python = ">=3.6" @@ -21,7 +21,7 @@ classifiers = [ dependencies = [ "bottle>=0.12.16", "waitress>=1.3", - "doreah>=1.9.0, <2", + "doreah>=1.9.1, <2", "nimrodel>=0.8.0", "setproctitle>=1.1.10", #"pyvips>=2.1.16",