Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions homeassistant/components/recorder/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -1213,13 +1213,18 @@ def _end_session(self) -> None:
"""End the recorder session."""
if self.event_session is None:
return
try:
if self.run_history.active:
self.run_history.end(self.event_session)
try:
self._commit_event_session_or_retry()
self.event_session.close()
except Exception as err: # pylint: disable=broad-except
_LOGGER.exception("Error saving the event session during shutdown: %s", err)

try:
self.event_session.close()
except Exception as err: # pylint: disable=broad-except
_LOGGER.exception(
Comment thread
bdraco marked this conversation as resolved.
Outdated
"Error closing the event session during shutdown: %s", err
)
self.run_history.clear()

def _shutdown(self) -> None:
Expand Down
10 changes: 7 additions & 3 deletions homeassistant/components/recorder/run_history.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ def current(self) -> RecorderRuns:
start=self.recording_start, created=dt_util.utcnow()
)

@property
def active(self) -> bool:
"""Return if a run is active."""
return self._current_run_info is not None

def get(self, start: datetime) -> RecorderRuns | None:
"""Return the recorder run that started before or at start.

Expand Down Expand Up @@ -142,6 +147,5 @@ def clear(self) -> None:

Must run in the recorder thread.
"""
assert self._current_run_info is not None
assert self._current_run_info.end is not None
self._current_run_info = None
if self._current_run_info:
self._current_run_info = None
28 changes: 24 additions & 4 deletions tests/components/recorder/test_run_history.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
"""Test run history."""

from datetime import timedelta
from unittest.mock import patch

from homeassistant.components import recorder
from homeassistant.components.recorder.db_schema import RecorderRuns
from homeassistant.components.recorder.models import process_timestamp
from homeassistant.core import HomeAssistant
from homeassistant.util import dt as dt_util

from tests.common import SetupRecorderInstanceT


async def test_run_history(recorder_mock, hass):
"""Test the run history gives the correct run."""
Expand Down Expand Up @@ -47,12 +51,28 @@ async def test_run_history(recorder_mock, hass):
)


async def test_run_history_during_schema_migration(recorder_mock, hass):
"""Test the run history during schema migration."""
instance = recorder.get_instance(hass)
async def test_run_history_while_recorder_is_not_yet_started(
async_setup_recorder_instance: SetupRecorderInstanceT,
hass: HomeAssistant,
recorder_db_url: str,
) -> None:
"""Test the run history while recorder is not yet started.

This usually happens during schema migration because
we do not start right away.
"""
# Prevent the run history from starting to ensure
# we can test run_history.current.start returns the expected value
with patch(
"homeassistant.components.recorder.run_history.RunHistory.start",
):
instance = await async_setup_recorder_instance(hass)
run_history = instance.run_history
assert run_history.current.start == run_history.recording_start
with instance.get_session() as session:
run_history.start(session)
# Ideally we would run run_history.start in the recorder thread
# but since we mocked it out above, we run it directly here
# via the database executor to avoid blocking the event loop.
await instance.async_add_executor_job(run_history.start, session)
assert run_history.current.start == run_history.recording_start
assert run_history.current.created >= run_history.recording_start