perf: avoid redundant internal state snapshots - #2025
Conversation
|
The first CI run failed in The remaining 11 Prettier errors are in files unchanged by PR #2025:
The branch has been updated so CI can confirm that the focused changes themselves are clean. I have not included unrelated repository-wide formatting changes in this PR. The test jobs were skipped after lint failed; they should run once lint passes or the baseline formatting issue is handled separately. |
85615c2 to
5e574d7
Compare
|
Rebased this branch onto current upstream |
Summary
This is a focused, contract-preserving alternative to the broader performance work in #2011.
The Node-RED integration currently deep-clones the complete Home Assistant state map in
getStates(). Several internal consumers only inspect that map while rendering templates, filtering entities, or checking conditions. This PR avoids those redundant clones without changing the public getter contract.What changes
getStates()andgetState()continue returning independent defensive copies.getStatesReadOnly()accessor is added for internal consumers that only read the state map.Why this differs from #2011
PR #2011 demonstrates a substantial CPU reduction, but it also exposes shared state through
getStatesRef()and includes a broad set of changes. This PR keeps the optimisation narrowly scoped and makes the ownership rule explicit: public APIs remain safe snapshots; only audited internal readers may use the shared map.It does not change the upstream
home-assistant-js-websocketsnapshot behaviour. That behaviour is intentional because listeners may retain old snapshots and compare them with new ones.Testing
Automated
Run the normal project checks:
pnpm test pnpm run lintThe focused tests verify:
getStates()does not alter the websocket cache.getStatesReadOnly()returns the current map for explicitly read-only internal consumers.Manual regression testing
Against a high-update Home Assistant workload, compare the current release with this branch for:
getStates()andgetState()and verify subsequent reads are unchanged.The shared object returned by
getStatesReadOnly()must never be mutated by a caller. A regression in entity counts, stale state, missing removals, reconnect handling, or public snapshot isolation should block adoption.