mirror of
https://github.com/Matysh/houseplan-card
synced 2026-07-31 08:28:31 +00:00
v1.45.2: hardening from the v1.45.1 review — R4-1, R4-2
R4-1: collecting superseded plan files runs after the configuration is already durable, but an error listing the directory propagated out of config/set. The client saw a failure for a revision the server had committed, and its retry came back as a conflict. collect_plans now reports 0 instead of raising, and config/set logs and proceeds — the event fires, the revision is returned. R4-2: the pending set was cleared when a batch went out, not when it came back, so every render during an in-flight content/sign queued another request: six calls where one was needed, and unbounded on a socket that is slow rather than busy. Queued and in-flight are separate states now; a failure backs off (2 s doubling to 60 s) instead of retrying on the next frame; an in-flight entry expires after 15 s so a promise that never settles cannot wedge retries; a late answer after dispose() no longer renders. Tests: test/signing.test.mjs — eight cases with hand-settled promises, verified against a v1.45.1 checkout where four of them fail (2 sign calls instead of 1, no backoff, a late answer rendering after teardown). Backend: a broken collector still yields a successful save whose revision the next CAS accepts. Pure collector: a disappearing directory returns 0. Docs: CHANGELOG.md + CHANGELOG.ru.md + ARCHITECTURE.md + TESTING.md + STATUS.md.
This commit is contained in:
@@ -396,6 +396,47 @@ async def test_collection_ignores_files_that_are_not_plans(
|
||||
assert (plans / "readme").is_file()
|
||||
|
||||
|
||||
async def test_a_failing_collector_does_not_undo_an_accepted_save(
|
||||
hass: HomeAssistant, hass_ws_client: WebSocketGenerator, monkeypatch
|
||||
) -> None:
|
||||
"""review R4-1: garbage collection runs behind an already durable write.
|
||||
|
||||
If it raised, the client got an error for a revision the store had already
|
||||
accepted — and its retry then failed with `conflict`, because the server had
|
||||
moved on. The commit stands and the event fires regardless.
|
||||
"""
|
||||
from custom_components.houseplan import websocket_api as wsapi
|
||||
|
||||
await _setup(hass)
|
||||
client = await hass_ws_client(hass)
|
||||
|
||||
events = []
|
||||
hass.bus.async_listen("houseplan_config_updated", lambda ev: events.append(ev.data))
|
||||
|
||||
def _boom(*_a, **_k):
|
||||
raise OSError("the plans directory is on fire")
|
||||
|
||||
monkeypatch.setattr(wsapi, "collect_plans", _boom)
|
||||
|
||||
cfg = await _cfg([{"id": "r5", "plan_url": None}])
|
||||
ok = await _save(client, cfg, 0)
|
||||
assert ok["success"], "an accepted revision must be reported as accepted"
|
||||
rev = ok["result"]["rev"]
|
||||
|
||||
await hass.async_block_till_done()
|
||||
assert events and events[-1]["rev"] == rev, "the update event still fires"
|
||||
|
||||
# the store really holds the new revision, and the reported rev is usable
|
||||
await client.send_json_auto_id({"type": "houseplan/config/get"})
|
||||
got = await client.receive_json()
|
||||
assert got["result"]["rev"] == rev
|
||||
assert [sp["id"] for sp in got["result"]["config"]["spaces"]] == ["r5"]
|
||||
|
||||
monkeypatch.undo()
|
||||
again = await _save(client, cfg, rev)
|
||||
assert again["success"], "the next CAS on the reported revision goes through"
|
||||
|
||||
|
||||
async def test_content_signed_path_opens_without_a_bearer_header(
|
||||
hass: HomeAssistant, hass_ws_client: WebSocketGenerator, hass_client_no_auth
|
||||
) -> None:
|
||||
|
||||
Reference in New Issue
Block a user