add appsettings sync at startup

This commit is contained in:
Simon
2025-01-25 00:54:47 +07:00
parent a8336ed04d
commit 34203b70ae
2 changed files with 82 additions and 28 deletions

View File

@@ -27,22 +27,22 @@ class SubscriptionsConfigType(TypedDict):
class DownloadsConfigType(TypedDict): class DownloadsConfigType(TypedDict):
"""describes downloads config""" """describes downloads config"""
limit_speed: int limit_speed: int | None
sleep_interval: int sleep_interval: int | None
autodelete_days: int autodelete_days: int | None
format: str | bool format: str | None
format_sort: str | bool format_sort: str | None
add_metadata: bool add_metadata: bool
add_thumbnail: bool add_thumbnail: bool
subtitle: str | bool subtitle: str | None
subtitle_source: Literal["user", "auto"] | bool subtitle_source: Literal["user", "auto"] | None
subtitle_index: bool subtitle_index: bool
comment_max: str | bool comment_max: str | None
comment_sort: Literal["top", "new"] comment_sort: Literal["top", "new"] | None
cookie_import: bool cookie_import: bool
potoken: bool potoken: bool
throttledratelimit: int throttledratelimit: int | None
extractor_lang: str | bool extractor_lang: str | None
integrate_ryd: bool integrate_ryd: bool
integrate_sponsorblock: bool integrate_sponsorblock: bool
@@ -65,30 +65,32 @@ class AppConfig:
"""handle application variables""" """handle application variables"""
ES_PATH = "ta_config/_doc/appsettings" ES_PATH = "ta_config/_doc/appsettings"
ES_UPDATE_PATH = "ta_config/_update/appsettings"
CONFIG_DEFAULTS: AppConfigType = { CONFIG_DEFAULTS: AppConfigType = {
"subscriptions": { "subscriptions": {
"channel_size": 50, "channel_size": 50,
"live_channel_size": 50, "live_channel_size": 50,
"shorts_channel_size": 50, "shorts_channel_size": 50,
"auto_start": False, "auto_start": False,
"new_config": 100,
}, },
"downloads": { "downloads": {
"limit_speed": False, "limit_speed": None,
"sleep_interval": 10, "sleep_interval": 10,
"autodelete_days": False, "autodelete_days": None,
"format": False, "format": None,
"format_sort": False, "format_sort": None,
"add_metadata": False, "add_metadata": False,
"add_thumbnail": False, "add_thumbnail": False,
"subtitle": False, "subtitle": None,
"subtitle_source": False, "subtitle_source": None,
"subtitle_index": False, "subtitle_index": False,
"comment_max": False, "comment_max": None,
"comment_sort": "top", "comment_sort": "top",
"cookie_import": False, "cookie_import": False,
"potoken": False, "potoken": False,
"throttledratelimit": False, "throttledratelimit": None,
"extractor_lang": False, "extractor_lang": None,
"integrate_ryd": False, "integrate_ryd": False,
"integrate_sponsorblock": False, "integrate_sponsorblock": False,
}, },
@@ -102,7 +104,7 @@ class AppConfig:
"""get config from ES""" """get config from ES"""
response, status_code = ElasticWrap(self.ES_PATH).get() response, status_code = ElasticWrap(self.ES_PATH).get()
if not status_code == 200: if not status_code == 200:
return self.CONFIG_DEFAULTS raise ValueError(f"no config found at {self.ES_PATH}")
return response["_source"] return response["_source"]
@@ -119,6 +121,13 @@ class AppConfig:
return self.config return self.config
def _update_config_dict(self, to_update) -> None:
"""none validated partial update for defaults sync"""
data = {"doc": to_update}
response, status_code = ElasticWrap(self.ES_UPDATE_PATH).post(data)
if not status_code == 200:
print(f"update failed: {response}, {status_code}")
def _validate_key(self, key_map: list[str]) -> None: def _validate_key(self, key_map: list[str]) -> None:
"""raise valueerror on invalid key""" """raise valueerror on invalid key"""
exists = self.CONFIG_DEFAULTS.get(key_map[0], {}).get(key_map[1]) # type: ignore # noqa: E501 exists = self.CONFIG_DEFAULTS.get(key_map[0], {}).get(key_map[1]) # type: ignore # noqa: E501
@@ -145,6 +154,29 @@ class AppConfig:
} }
RedisArchivist().set_message(key, message=message, expire=True) RedisArchivist().set_message(key, message=message, expire=True)
def sync_defaults(self):
"""sync defaults at startup, needs to be called with __new__"""
return ElasticWrap(self.ES_PATH).post(self.CONFIG_DEFAULTS)
def add_new_defaults(self) -> list[str]:
"""add new default config values to ES, called at startup"""
updated = []
for key, value in self.CONFIG_DEFAULTS.items():
if key not in self.config:
# complete new key
self._update_config_dict({key: value})
updated.append(str({key: value}))
continue
for sub_key, sub_value in value.items(): # type: ignore
if sub_key not in self.config[key]:
# new partial key
to_update = {key: {sub_key: sub_value}}
self._update_config_dict(to_update)
updated.append(str(to_update))
return updated
class ReleaseVersion: class ReleaseVersion:
"""compare local version with remote version""" """compare local version with remote version"""

View File

@@ -9,7 +9,7 @@ from datetime import datetime
from random import randint from random import randint
from time import sleep from time import sleep
from appsettings.src.config import ReleaseVersion from appsettings.src.config import AppConfig, ReleaseVersion
from appsettings.src.index_setup import ElasitIndexWrap from appsettings.src.index_setup import ElasitIndexWrap
from appsettings.src.snapshot import ElasticSnapshot from appsettings.src.snapshot import ElasticSnapshot
from common.src.env_settings import EnvironmentSettings from common.src.env_settings import EnvironmentSettings
@@ -51,9 +51,10 @@ class Command(BaseCommand):
self._snapshot_check() self._snapshot_check()
self._create_default_schedules() self._create_default_schedules()
self._update_schedule_tz() self._update_schedule_tz()
self._init_app_config()
def _mig_app_settings(self) -> None: def _mig_app_settings(self) -> None:
"""update from v0.4.10 to v0.5.0, migrate application settings""" """update from v0.4.13 to v0.5.0, migrate application settings"""
self.stdout.write("[MIGRATION] move appconfig to ES") self.stdout.write("[MIGRATION] move appconfig to ES")
try: try:
config = RedisArchivist().get_message("config") config = RedisArchivist().get_message("config")
@@ -187,10 +188,7 @@ class Command(BaseCommand):
ElasticSnapshot().setup() ElasticSnapshot().setup()
def _create_default_schedules(self) -> None: def _create_default_schedules(self) -> None:
""" """create default schedules for new installations"""
create default schedules for new installations
needs to be called after _mig_schedule_store
"""
self.stdout.write("[9] create initial schedules") self.stdout.write("[9] create initial schedules")
init_has_run = CustomPeriodicTask.objects.filter( init_has_run = CustomPeriodicTask.objects.filter(
name="version_check" name="version_check"
@@ -242,7 +240,7 @@ class Command(BaseCommand):
def _update_schedule_tz(self) -> None: def _update_schedule_tz(self) -> None:
"""update timezone for Schedule instances""" """update timezone for Schedule instances"""
self.stdout.write("[9] validate schedules TZ") self.stdout.write("[10] validate schedules TZ")
tz = EnvironmentSettings.TZ tz = EnvironmentSettings.TZ
to_update = CrontabSchedule.objects.exclude(timezone=tz) to_update = CrontabSchedule.objects.exclude(timezone=tz)
@@ -257,3 +255,27 @@ class Command(BaseCommand):
self.style.SUCCESS(f" ✓ updated {updated} schedules to {tz}.") self.style.SUCCESS(f" ✓ updated {updated} schedules to {tz}.")
) )
PeriodicTasks.update_changed() PeriodicTasks.update_changed()
def _init_app_config(self) -> None:
"""init default app config to ES"""
self.stdout.write("[11] Check AppConfig")
try:
_ = AppConfig().config
self.stdout.write(
self.style.SUCCESS(" skip completed appsettings init")
)
updated_defaults = AppConfig().add_new_defaults()
for new_default in updated_defaults:
self.stdout.write(
self.style.SUCCESS(f" added new default: {new_default}")
)
except ValueError:
handler = AppConfig.__new__(AppConfig)
_, status_code = handler.sync_defaults()
self.stdout.write(
self.style.SUCCESS(" ✓ Created default appsettings.")
)
self.stdout.write(
self.style.SUCCESS(f" Status code: {status_code}")
)