mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-08-20 01:49:05 +00:00
fix: address review findings on the low-memory work
Nine CodeRabbit findings, five in code. **Health state (the one that matters).** The non-dict guard did not cover a dict missing fields the callers index directly, which is the shape actually seen in the wild: a record carrying only circuit_state produced `plugin clock-simple operation failed: 'circuit_state'` about fifty times a minute with the panel frozen. The record is now completed against the defaults per field rather than trusted or discarded wholesale. Per field matters: a first pass rejected any incomplete record outright, which reset a tripped breaker and real failure counts to healthy because one optional field was absent -- an existing test caught it. Values of the wrong type (a counter persisted as a string, an unknown circuit_state) fall back individually, valid neighbours survive, and newer fields the schema has grown since (degraded, degraded_reason) are carried through untouched. **Cache ceiling.** MemoryCache.set() accepted entries without bound between cleanup sweeps, which run every 300s by default, so a burst could take the cache far past max_size -- the unbounded growth the limit exists to stop. Eviction now runs under the same lock on every write, sharing one helper with the periodic sweep so the two cannot drift. **Installer, cgroups.** Only cgroup_enable=memory was checked, so a board carrying that without cgroup_memory=1 reported success and got no change, leaving MemoryMax= inert. Each parameter is now checked and appended independently; verified against all four combinations, single line preserved. **Installer, journald.** Persistence was inferred from /var/log/journal being non-empty, which proves neither Storage=persistent nor a size cap -- the directory survives a switch back to volatile. The effective configuration is read instead (systemd-analyze cat-config, falling back to the conf files), and an explicitly configured SystemMaxUse is preserved rather than overwritten. Verified across volatile, persistent-without-cap, persistent-with-user-cap, cap-without-storage, and commented-only configs. **Dependency extras.** _extras_are_satisfied stopped at one level, so a gated dependency that itself requests an extra (requests[socks]) passed on the base distribution's version while the extra's own dependency was missing, and pip was skipped. It now recurses, with a visited (distribution, extras) set so a cycle terminates. Docs: both kernel command-line paths documented (the installer falls back to /boot/cmdline.txt), daemon-reload and restart added after the systemd override example, memory exhaustion added to the SSH summary with its power-cycle-only recovery, and a language on the fenced block for MD040. Tests: five for the health-state repair including the exact wild shape and that record_failure/record_success no longer raise against it, and one for the cache ceiling. Both mutation-checked. Full suite 2927 passed, with the one pre-existing tmpfs failure that also fails on main. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01STMbQE4YctTacQXfbYqKuW
This commit is contained in:
co-authored by
Claude Opus 5
parent
ef1e9e0eee
commit
34a7414275
@@ -458,3 +458,26 @@ class TestDiskCacheWriteEconomy:
|
||||
cache = DiskCache(cache_dir=str(tmp_path))
|
||||
cache.set("k", {"when": datetime(2026, 7, 12, 10, 30)})
|
||||
assert cache.get("k") == {"when": "2026-07-12T10:30:00"}
|
||||
|
||||
|
||||
# --- the ceiling has to hold between cleanup sweeps ---------------------------
|
||||
|
||||
def test_memory_cache_enforces_ceiling_on_every_write():
|
||||
"""_cleanup_memory_cache only runs every cleanup_interval seconds (300 by
|
||||
default). If set() accepted entries without bound in between, a burst could
|
||||
take the cache far past max_size -- which is the unbounded growth the limit
|
||||
exists to prevent, and on a 1GB board the difference between a bounded cache
|
||||
and a Pi that cannot fork.
|
||||
"""
|
||||
from src.cache.memory_cache import MemoryCache
|
||||
|
||||
cache = MemoryCache(max_size=150, cleanup_interval=300.0)
|
||||
for i in range(1000):
|
||||
cache.set(f"k{i}", {"v": i})
|
||||
|
||||
assert len(cache._cache) <= 150
|
||||
# The timestamp map has to be evicted alongside the values, or it becomes
|
||||
# the leak instead.
|
||||
assert len(cache._timestamps) <= 150
|
||||
assert cache.get("k999") is not None, "the newest write must survive"
|
||||
assert cache.get("k0") is None, "the oldest must be the one evicted"
|
||||
|
||||
Reference in New Issue
Block a user