mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-10-04 14:25:08 +00:00
refactor(plugins): the display publishes plugin runtime state; retire plugin_state.json (#690)
Stage 2 of the web plugin catalog, after #688. - The display publishes a plugin runtime snapshot (plugin_runtime.py) to the shared cache: per plugin loaded, lifecycle state, a short redacted error summary, the version it loaded and when, plus published_at / stale_after / running. Written on change (throttled to 10 s; the RUNNING/ENABLED flip of an ordinary update is not a change) and once a minute otherwise; cleanup() publishes running: false. - The web reads it back and restores loaded / state / error_info in /api/v3/plugins/installed (plus loaded_version, loaded_at and data.runtime). Only a live snapshot counts; stale, stopped or missing answers null and says which. - data/plugin_state.json is retired: every reader and writer moved to config + disk (desired) or the snapshot (observed). Nothing in it was non-derivable, so nothing is migrated and an existing file is left unread. The web-side PluginStateManager (state_manager.py) is removed; the display's plugin_state.PluginStateManager is the only state machine. - StateReconciliation compares config + disk with the snapshot, reporting enabled-but-not-loaded and older-version-loaded as no_action findings. - Backups list installed manifests with enabled from config.json. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
"""Plugin-system JSON files are read as UTF-8, whatever the locale says.
|
||||
|
||||
store_manager (install_from_url's manifest, the secrets file) and
|
||||
state_manager (plugin_state.json) opened text files without an encoding, so
|
||||
the platform default applied. A manifest written in UTF-8 with a non-ASCII
|
||||
store_manager (install_from_url's manifest, the secrets file) opened text
|
||||
files without an encoding, so the platform default applied. (So did the
|
||||
retired plugin_state.json reader.) A manifest written in UTF-8 with a non-ASCII
|
||||
name then read as mojibake -- or raised UnicodeDecodeError -- on a host
|
||||
whose locale encoding is not UTF-8 (Windows' cp1252; a Pi with LANG=C).
|
||||
On a UTF-8 host these pass either way; they fail on old code where the
|
||||
@@ -13,7 +13,6 @@ import json
|
||||
|
||||
import pytest
|
||||
|
||||
from src.plugin_system.state_manager import PluginStateManager
|
||||
from src.plugin_system.store_manager import PluginStoreManager
|
||||
|
||||
NAME = "Météo Á" # "Á" is C3 81 in UTF-8; 0x81 is undefined in cp1252
|
||||
@@ -48,15 +47,3 @@ def test_install_from_url_reads_a_utf8_manifest(store):
|
||||
written = json.loads(
|
||||
(store.plugins_dir / "meteo" / "manifest.json").read_bytes().decode("utf-8"))
|
||||
assert written["name"] == NAME
|
||||
|
||||
|
||||
def test_state_manager_loads_a_utf8_state_file(tmp_path):
|
||||
state_file = tmp_path / "plugin_state.json"
|
||||
state_file.write_bytes(json.dumps({
|
||||
"version": 1,
|
||||
"states": {"meteo": {"plugin_id": "meteo", "status": "installed",
|
||||
"enabled": True, "metadata": {"label": NAME}}},
|
||||
}, ensure_ascii=False).encode("utf-8"))
|
||||
|
||||
mgr = PluginStateManager(state_file=str(state_file))
|
||||
assert mgr.get_plugin_state("meteo").metadata["label"] == NAME
|
||||
|
||||
Reference in New Issue
Block a user