Codebase review fixes: stability, performance, quality improvements

Stability: Add outer try/except/finally with _running=False cleanup to all 6
processing loop methods (live, color_strip, effect, audio, composite, mapped).
Add exponential backoff on consecutive capture errors in live_stream. Move
audio stream.stop() outside lock scope.

Performance: Replace per-pixel Python loop with np.array().tobytes() in
ddp_client. Vectorize pixelate filter with cv2.resize down+up. Vectorize
gradient rendering with np.searchsorted.

Frontend: Add lockBody/unlockBody re-entrancy counter. Add {once:true} to
fetchWithAuth abort listener. Null ws.onclose before ws.close() in LED preview.

Backend: Remove auth token prefix from log messages. Add atomic_write_json
helper (tempfile + os.replace) and update all 10 stores. Add name uniqueness
checks to all update methods. Fix DELETE status codes to 204 in audio_sources
and value_sources. Fix get_source() silent bug in color_strip_sources.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-26 18:23:04 +03:00
parent bafd8b4130
commit 9cfe628cc5
30 changed files with 922 additions and 779 deletions

View File

@@ -11,7 +11,7 @@ from wled_controller.storage.audio_source import (
MonoAudioSource,
MultichannelAudioSource,
)
from wled_controller.utils import get_logger
from wled_controller.utils import atomic_write_json, get_logger
logger = get_logger(__name__)
@@ -57,21 +57,14 @@ class AudioSourceStore:
def _save(self) -> None:
try:
self.file_path.parent.mkdir(parents=True, exist_ok=True)
sources_dict = {
sid: source.to_dict()
for sid, source in self._sources.items()
}
data = {
"version": "1.0.0",
"audio_sources": sources_dict,
"audio_sources": {
sid: source.to_dict()
for sid, source in self._sources.items()
},
}
with open(self.file_path, "w", encoding="utf-8") as f:
json.dump(data, f, indent=2, ensure_ascii=False)
atomic_write_json(self.file_path, data)
except Exception as e:
logger.error(f"Failed to save audio sources to {self.file_path}: {e}")
raise

View File

@@ -8,7 +8,7 @@ from typing import Dict, List, Optional
from wled_controller.core.audio.factory import AudioEngineRegistry
from wled_controller.storage.audio_template import AudioCaptureTemplate
from wled_controller.utils import get_logger
from wled_controller.utils import atomic_write_json, get_logger
logger = get_logger(__name__)
@@ -93,21 +93,14 @@ class AudioTemplateStore:
def _save(self) -> None:
"""Save all templates to file."""
try:
self.file_path.parent.mkdir(parents=True, exist_ok=True)
templates_dict = {
template_id: template.to_dict()
for template_id, template in self._templates.items()
}
data = {
"version": "1.0.0",
"templates": templates_dict,
"templates": {
template_id: template.to_dict()
for template_id, template in self._templates.items()
},
}
with open(self.file_path, "w", encoding="utf-8") as f:
json.dump(data, f, indent=2, ensure_ascii=False)
atomic_write_json(self.file_path, data)
except Exception as e:
logger.error(f"Failed to save audio templates to {self.file_path}: {e}")
raise
@@ -168,6 +161,9 @@ class AudioTemplateStore:
template = self._templates[template_id]
if name is not None:
for tid, t in self._templates.items():
if tid != template_id and t.name == name:
raise ValueError(f"Audio template with name '{name}' already exists")
template.name = name
if engine_type is not None:
template.engine_type = engine_type

View File

@@ -19,7 +19,7 @@ from wled_controller.storage.color_strip_source import (
PictureColorStripSource,
StaticColorStripSource,
)
from wled_controller.utils import get_logger
from wled_controller.utils import atomic_write_json, get_logger
logger = get_logger(__name__)
@@ -62,21 +62,14 @@ class ColorStripStore:
def _save(self) -> None:
try:
self.file_path.parent.mkdir(parents=True, exist_ok=True)
sources_dict = {
sid: source.to_dict()
for sid, source in self._sources.items()
}
data = {
"version": "1.0.0",
"color_strip_sources": sources_dict,
"color_strip_sources": {
sid: source.to_dict()
for sid, source in self._sources.items()
},
}
with open(self.file_path, "w", encoding="utf-8") as f:
json.dump(data, f, indent=2, ensure_ascii=False)
atomic_write_json(self.file_path, data)
except Exception as e:
logger.error(f"Failed to save color strip sources to {self.file_path}: {e}")
raise

View File

@@ -8,7 +8,7 @@ from typing import Dict, List, Optional
from wled_controller.storage.key_colors_picture_target import KeyColorRectangle
from wled_controller.storage.pattern_template import PatternTemplate
from wled_controller.utils import get_logger
from wled_controller.utils import atomic_write_json, get_logger
logger = get_logger(__name__)
@@ -88,21 +88,14 @@ class PatternTemplateStore:
def _save(self) -> None:
"""Save all templates to file."""
try:
self.file_path.parent.mkdir(parents=True, exist_ok=True)
templates_dict = {
template_id: template.to_dict()
for template_id, template in self._templates.items()
}
data = {
"version": "1.0.0",
"pattern_templates": templates_dict,
"pattern_templates": {
template_id: template.to_dict()
for template_id, template in self._templates.items()
},
}
with open(self.file_path, "w", encoding="utf-8") as f:
json.dump(data, f, indent=2, ensure_ascii=False)
atomic_write_json(self.file_path, data)
except Exception as e:
logger.error(f"Failed to save pattern templates to {self.file_path}: {e}")
raise
@@ -180,6 +173,9 @@ class PatternTemplateStore:
template = self._templates[template_id]
if name is not None:
for tid, t in self._templates.items():
if tid != template_id and t.name == name:
raise ValueError(f"Pattern template with name '{name}' already exists")
template.name = name
if rectangles is not None:
template.rectangles = rectangles

View File

@@ -12,7 +12,7 @@ from wled_controller.storage.picture_source import (
ProcessedPictureSource,
StaticImagePictureSource,
)
from wled_controller.utils import get_logger
from wled_controller.utils import atomic_write_json, get_logger
logger = get_logger(__name__)
@@ -68,21 +68,14 @@ class PictureSourceStore:
def _save(self) -> None:
"""Save all streams to file."""
try:
self.file_path.parent.mkdir(parents=True, exist_ok=True)
streams_dict = {
stream_id: stream.to_dict()
for stream_id, stream in self._streams.items()
}
data = {
"version": "1.0.0",
"picture_sources": streams_dict,
"picture_sources": {
stream_id: stream.to_dict()
for stream_id, stream in self._streams.items()
},
}
with open(self.file_path, "w", encoding="utf-8") as f:
json.dump(data, f, indent=2, ensure_ascii=False)
atomic_write_json(self.file_path, data)
except Exception as e:
logger.error(f"Failed to save picture sources to {self.file_path}: {e}")
raise

View File

@@ -12,7 +12,7 @@ from wled_controller.storage.key_colors_picture_target import (
KeyColorsSettings,
KeyColorsPictureTarget,
)
from wled_controller.utils import get_logger
from wled_controller.utils import atomic_write_json, get_logger
logger = get_logger(__name__)
@@ -63,21 +63,14 @@ class PictureTargetStore:
def _save(self) -> None:
"""Save all targets to file."""
try:
self.file_path.parent.mkdir(parents=True, exist_ok=True)
targets_dict = {
target_id: target.to_dict()
for target_id, target in self._targets.items()
}
data = {
"version": "1.0.0",
"picture_targets": targets_dict,
"picture_targets": {
target_id: target.to_dict()
for target_id, target in self._targets.items()
},
}
with open(self.file_path, "w", encoding="utf-8") as f:
json.dump(data, f, indent=2, ensure_ascii=False)
atomic_write_json(self.file_path, data)
except Exception as e:
logger.error(f"Failed to save picture targets to {self.file_path}: {e}")
raise

View File

@@ -10,7 +10,7 @@ from wled_controller.core.filters.filter_instance import FilterInstance
from wled_controller.core.filters.registry import FilterRegistry
from wled_controller.storage.picture_source import ProcessedPictureSource
from wled_controller.storage.postprocessing_template import PostprocessingTemplate
from wled_controller.utils import get_logger
from wled_controller.utils import atomic_write_json, get_logger
logger = get_logger(__name__)
@@ -92,21 +92,14 @@ class PostprocessingTemplateStore:
def _save(self) -> None:
"""Save all templates to file."""
try:
self.file_path.parent.mkdir(parents=True, exist_ok=True)
templates_dict = {
template_id: template.to_dict()
for template_id, template in self._templates.items()
}
data = {
"version": "2.0.0",
"postprocessing_templates": templates_dict,
"postprocessing_templates": {
template_id: template.to_dict()
for template_id, template in self._templates.items()
},
}
with open(self.file_path, "w", encoding="utf-8") as f:
json.dump(data, f, indent=2, ensure_ascii=False)
atomic_write_json(self.file_path, data)
except Exception as e:
logger.error(f"Failed to save postprocessing templates to {self.file_path}: {e}")
raise
@@ -189,6 +182,9 @@ class PostprocessingTemplateStore:
template = self._templates[template_id]
if name is not None:
for tid, t in self._templates.items():
if tid != template_id and t.name == name:
raise ValueError(f"Postprocessing template with name '{name}' already exists")
template.name = name
if filters is not None:
# Validate filter IDs

View File

@@ -7,7 +7,7 @@ from pathlib import Path
from typing import Dict, List, Optional
from wled_controller.storage.profile import Condition, Profile
from wled_controller.utils import get_logger
from wled_controller.utils import atomic_write_json, get_logger
logger = get_logger(__name__)
@@ -49,18 +49,13 @@ class ProfileStore:
def _save(self) -> None:
try:
self.file_path.parent.mkdir(parents=True, exist_ok=True)
data = {
"version": "1.0.0",
"profiles": {
pid: p.to_dict() for pid, p in self._profiles.items()
},
}
with open(self.file_path, "w", encoding="utf-8") as f:
json.dump(data, f, indent=2, ensure_ascii=False)
atomic_write_json(self.file_path, data)
except Exception as e:
logger.error(f"Failed to save profiles to {self.file_path}: {e}")
raise
@@ -81,6 +76,10 @@ class ProfileStore:
conditions: Optional[List[Condition]] = None,
target_ids: Optional[List[str]] = None,
) -> Profile:
for p in self._profiles.values():
if p.name == name:
raise ValueError(f"Profile with name '{name}' already exists")
profile_id = f"prof_{uuid.uuid4().hex[:8]}"
now = datetime.utcnow()
@@ -116,6 +115,9 @@ class ProfileStore:
profile = self._profiles[profile_id]
if name is not None:
for pid, p in self._profiles.items():
if pid != profile_id and p.name == name:
raise ValueError(f"Profile with name '{name}' already exists")
profile.name = name
if enabled is not None:
profile.enabled = enabled

View File

@@ -8,7 +8,7 @@ from typing import Dict, List, Optional
from wled_controller.core.capture_engines.factory import EngineRegistry
from wled_controller.storage.template import CaptureTemplate
from wled_controller.utils import get_logger
from wled_controller.utils import atomic_write_json, get_logger
logger = get_logger(__name__)
@@ -95,23 +95,14 @@ class TemplateStore:
def _save(self) -> None:
"""Save all templates to file."""
try:
# Ensure directory exists
self.file_path.parent.mkdir(parents=True, exist_ok=True)
templates_dict = {
template_id: template.to_dict()
for template_id, template in self._templates.items()
}
data = {
"version": "1.0.0",
"templates": templates_dict,
"templates": {
template_id: template.to_dict()
for template_id, template in self._templates.items()
},
}
# Write to file
with open(self.file_path, "w", encoding="utf-8") as f:
json.dump(data, f, indent=2, ensure_ascii=False)
atomic_write_json(self.file_path, data)
except Exception as e:
logger.error(f"Failed to save templates to {self.file_path}: {e}")
raise
@@ -218,6 +209,9 @@ class TemplateStore:
# Update fields
if name is not None:
for tid, t in self._templates.items():
if tid != template_id and t.name == name:
raise ValueError(f"Template with name '{name}' already exists")
template.name = name
if engine_type is not None:
template.engine_type = engine_type

View File

@@ -13,7 +13,7 @@ from wled_controller.storage.value_source import (
StaticValueSource,
ValueSource,
)
from wled_controller.utils import get_logger
from wled_controller.utils import atomic_write_json, get_logger
logger = get_logger(__name__)
@@ -59,21 +59,14 @@ class ValueSourceStore:
def _save(self) -> None:
try:
self.file_path.parent.mkdir(parents=True, exist_ok=True)
sources_dict = {
sid: source.to_dict()
for sid, source in self._sources.items()
}
data = {
"version": "1.0.0",
"value_sources": sources_dict,
"value_sources": {
sid: source.to_dict()
for sid, source in self._sources.items()
},
}
with open(self.file_path, "w", encoding="utf-8") as f:
json.dump(data, f, indent=2, ensure_ascii=False)
atomic_write_json(self.file_path, data)
except Exception as e:
logger.error(f"Failed to save value sources to {self.file_path}: {e}")
raise