Fix live logbook stalling when there are no historical events with a high commit interval (#86110)

* Force live logbook to send an empty message to indicate no results

Since the sync task can take a while if the recorder is
busy, the logbook will appear to hang if we do not send
the first partial message even if its empty.

This work is in preparation for a higher database
commit interval where this issue is most obvious.

The historical only path did not have this issue because
it never had to wait for the db sync.

* update tests
This commit is contained in:
J. Nick Koston 2023-01-17 16:06:37 -10:00 committed by GitHub
parent 87b2a73460
commit 5279535046
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 26 additions and 2 deletions

View File

@ -83,6 +83,7 @@ async def _async_send_historical_events(
formatter: Callable[[int, Any], dict[str, Any]],
event_processor: EventProcessor,
partial: bool,
force_send: bool = False,
) -> dt | None:
"""Select historical data from the database and deliver it to the websocket.
@ -116,7 +117,7 @@ async def _async_send_historical_events(
# if its the last one (not partial) so
# consumers of the api know their request was
# answered but there were no results
if last_event_time or not partial:
if last_event_time or not partial or force_send:
connection.send_message(message)
return last_event_time
@ -150,7 +151,7 @@ async def _async_send_historical_events(
# if its the last one (not partial) so
# consumers of the api know their request was
# answered but there were no results
if older_query_last_event_time or not partial:
if older_query_last_event_time or not partial or force_send:
connection.send_message(older_message)
# Returns the time of the newest event
@ -384,6 +385,11 @@ async def ws_event_stream(
messages.event_message,
event_processor,
partial=True,
# Force a send since the wait for the sync task
# can take a a while if the recorder is busy and
# we want to make sure the client is not still spinning
# because it is waiting for the first message
force_send=True,
)
live_stream.task = asyncio.create_task(

View File

@ -1817,6 +1817,7 @@ async def test_subscribe_unsubscribe_logbook_stream_device(
assert msg["id"] == 7
assert msg["type"] == TYPE_RESULT
assert msg["success"]
await async_wait_recording_done(hass)
# There are no answers to our initial query
# so we get an empty reply. This is to ensure
@ -1828,6 +1829,15 @@ async def test_subscribe_unsubscribe_logbook_stream_device(
assert msg["id"] == 7
assert msg["type"] == "event"
assert msg["event"]["events"] == []
assert "partial" in msg["event"]
await async_wait_recording_done(hass)
msg = await asyncio.wait_for(websocket_client.receive_json(), 2)
assert msg["id"] == 7
assert msg["type"] == "event"
assert msg["event"]["events"] == []
assert "partial" not in msg["event"]
await async_wait_recording_done(hass)
hass.states.async_set("binary_sensor.should_not_appear", STATE_ON)
hass.states.async_set("binary_sensor.should_not_appear", STATE_OFF)
@ -1942,6 +1952,14 @@ async def test_logbook_stream_match_multiple_entities(
assert msg["id"] == 7
assert msg["type"] == "event"
assert msg["event"]["events"] == []
assert "partial" in msg["event"]
await async_wait_recording_done(hass)
msg = await asyncio.wait_for(websocket_client.receive_json(), 2)
assert msg["id"] == 7
assert msg["type"] == "event"
assert msg["event"]["events"] == []
assert "partial" not in msg["event"]
await async_wait_recording_done(hass)
hass.states.async_set("binary_sensor.should_not_appear", STATE_ON)