This commit is contained in:
2026-03-21 17:23:26 -07:00
parent 4160e1cca4
commit f09f66ff9a
2 changed files with 156 additions and 37 deletions

View File

@@ -63,7 +63,7 @@ if _ROOT not in sys.path:
sys.path.insert(0, _ROOT)
from MPV.mpv_ipc import MPVIPCClient # noqa: E402
from SYS.config import load_config # noqa: E402
from SYS.config import load_config, reload_config # noqa: E402
from SYS.logger import set_debug, debug, set_thread_stream # noqa: E402
from SYS.repl_queue import enqueue_repl_command # noqa: E402
from SYS.utils import format_bytes # noqa: E402
@@ -80,6 +80,73 @@ _HELPER_LOG_BACKLOG_LIMIT = 200
_ASYNC_PIPELINE_JOBS: Dict[str, Dict[str, Any]] = {}
_ASYNC_PIPELINE_JOBS_LOCK = threading.Lock()
_ASYNC_PIPELINE_JOB_TTL_SECONDS = 900.0
_STORE_CHOICES_CACHE: list[str] = []
_STORE_CHOICES_CACHE_LOCK = threading.Lock()
def _normalize_store_choices(values: Any) -> list[str]:
out: list[str] = []
seen: set[str] = set()
if not isinstance(values, (list, tuple, set)):
return out
for item in values:
text = str(item or "").strip()
if not text:
continue
key = text.casefold()
if key in seen:
continue
seen.add(key)
out.append(text)
return sorted(out, key=str.casefold)
def _get_cached_store_choices() -> list[str]:
with _STORE_CHOICES_CACHE_LOCK:
return list(_STORE_CHOICES_CACHE)
def _set_cached_store_choices(choices: Any) -> list[str]:
normalized = _normalize_store_choices(choices)
with _STORE_CHOICES_CACHE_LOCK:
_STORE_CHOICES_CACHE[:] = normalized
return list(_STORE_CHOICES_CACHE)
def _publish_store_choices_cache(ipc_path: str, choices: Any) -> None:
cached = _normalize_store_choices(choices)
if not ipc_path or not cached:
return
payload = json.dumps(
{
"success": True,
"choices": cached,
},
ensure_ascii=False,
)
client = MPVIPCClient(socket_path=ipc_path, timeout=0.75, silent=True)
try:
client.send_command_no_wait(
[
"set_property_string",
"user-data/medeia-store-choices-cached",
payload,
]
)
finally:
try:
client.disconnect()
except Exception:
pass
def _load_store_choices_from_config(*, force_reload: bool = False) -> list[str]:
from Store.registry import list_configured_backend_names # noqa: WPS433
cfg = reload_config() if force_reload else load_config()
return _normalize_store_choices(list_configured_backend_names(cfg or {}))
def _prune_async_pipeline_jobs(now: Optional[float] = None) -> None:
@@ -632,17 +699,42 @@ def _run_op(op: str, data: Any) -> Dict[str, Any]:
"store_choices",
"get-store-choices",
"get_store_choices"}:
cached_choices = _get_cached_store_choices()
refresh = False
if isinstance(data, dict):
refresh = bool(data.get("refresh") or data.get("reload"))
if cached_choices and not refresh:
try:
_publish_store_choices_cache(os.environ.get("MEDEIA_MPV_IPC", ""), cached_choices)
except Exception:
pass
debug(f"[store-choices] using cached choices={len(cached_choices)}")
return {
"success": True,
"stdout": "",
"stderr": "",
"error": None,
"table": None,
"choices": cached_choices,
}
try:
from SYS.config import reload_config # noqa: WPS433
from Store import Store # noqa: WPS433
config_root = _runtime_config_root()
cfg = reload_config()
choices = _load_store_choices_from_config(force_reload=refresh)
storage = Store(config=cfg, suppress_debug=True)
backends = storage.list_backends() or []
choices = sorted({str(n)
for n in backends if str(n).strip()})
if not choices and cached_choices:
choices = cached_choices
debug(
f"[store-choices] config returned empty; falling back to cached choices={len(choices)}"
)
if choices:
choices = _set_cached_store_choices(choices)
try:
_publish_store_choices_cache(os.environ.get("MEDEIA_MPV_IPC", ""), choices)
except Exception:
pass
debug(f"[store-choices] config_dir={config_root} choices={len(choices)}")
@@ -655,6 +747,22 @@ def _run_op(op: str, data: Any) -> Dict[str, Any]:
"choices": choices,
}
except Exception as exc:
if cached_choices:
debug(
f"[store-choices] refresh failed; returning cached choices={len(cached_choices)} error={type(exc).__name__}: {exc}"
)
try:
_publish_store_choices_cache(os.environ.get("MEDEIA_MPV_IPC", ""), cached_choices)
except Exception:
pass
return {
"success": True,
"stdout": "",
"stderr": "",
"error": None,
"table": None,
"choices": cached_choices,
}
return {
"success": False,
"stdout": "",
@@ -1529,6 +1637,7 @@ def main(argv: Optional[list[str]] = None) -> int:
dict) else None
)
if isinstance(startup_choices, list):
startup_choices = _set_cached_store_choices(startup_choices)
preview = ", ".join(str(x) for x in startup_choices[:50])
_append_helper_log(
f"[helper] startup store-choices count={len(startup_choices)} items={preview}"
@@ -1536,20 +1645,7 @@ def main(argv: Optional[list[str]] = None) -> int:
# Publish to a cached property for Lua to read without IPC request.
try:
cached_json = json.dumps(
{
"success": True,
"choices": startup_choices
},
ensure_ascii=False
)
client.send_command_no_wait(
[
"set_property_string",
"user-data/medeia-store-choices-cached",
cached_json
]
)
_publish_store_choices_cache(str(args.ipc), startup_choices)
_append_helper_log(
"[helper] published store-choices to user-data/medeia-store-choices-cached"
)