Skip to content
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
342ee3a
Skip db locking test with postgresql/MySQL
bdraco Feb 9, 2023
dc3a7b3
Turn back off test_shutdown_before_startup_finishes on MySQL
bdraco Feb 9, 2023
0005e89
switch to the guards instead
bdraco Feb 9, 2023
57e16da
Merge branch 'test_shutdown_before_startup_finishes_mysql' into ii
bdraco Feb 9, 2023
30c3637
Disable test_migration_in_progress on MySQL
bdraco Feb 9, 2023
3d3310e
Merge branch 'disable_test_migration_in_progress' into ii
bdraco Feb 9, 2023
d6d5848
Disable test_entity_ids on MariaDB
bdraco Feb 9, 2023
a3ddbe2
Merge branch 'test_entity_ids_innodb_deadlock' into ii
bdraco Feb 9, 2023
8cdea7c
better fix, close stale connections
bdraco Feb 9, 2023
a5ec73d
Update tests/components/recorder/test_init.py
bdraco Feb 9, 2023
c97a053
Merge branch 'dev' into ii
epenet Feb 9, 2023
8ecf6dd
raise if connections active instead
bdraco Feb 9, 2023
d1a1903
Merge branch 'dev' into ii
bdraco Feb 9, 2023
9cadd9e
Merge remote-tracking branch 'origin/ii' into ii
bdraco Feb 9, 2023
58f63c7
Update tests/conftest.py
bdraco Feb 9, 2023
51f60a1
Update tests/conftest.py
bdraco Feb 9, 2023
43f9518
Update tests/conftest.py
bdraco Feb 9, 2023
fb61803
fix another test
bdraco Feb 9, 2023
fb29081
still dispose
bdraco Feb 9, 2023
a3ada74
fix more tests
bdraco Feb 9, 2023
aeecaf4
Merge remote-tracking branch 'upstream/dev' into ii
bdraco Feb 9, 2023
a9c4fcd
Really ensure recorder test fixture is setup before hass fixture
emontnemery Feb 9, 2023
538ac39
Merge remote-tracking branch 'upstream/recorder_fix_cleanup' into ii
bdraco Feb 9, 2023
5593833
fix run history test
bdraco Feb 9, 2023
a6ddc36
Merge branch 'dev' into ii
bdraco Feb 9, 2023
fc414a6
add missing patch
bdraco Feb 9, 2023
ce60266
Merge remote-tracking branch 'origin/ii' into ii
bdraco Feb 9, 2023
4ed0f8e
comment
bdraco Feb 9, 2023
17323e5
add mocks
bdraco Feb 9, 2023
770a322
Merge branch 'dev' into ii
bdraco Feb 9, 2023
ac64ebc
make sure event session is still closed if the commit fails
bdraco Feb 9, 2023
7b837c8
Merge remote-tracking branch 'origin/ii' into ii
bdraco Feb 9, 2023
7c954a9
Ensure recorder still shuts down if the final commit fails
bdraco Feb 9, 2023
3f21467
do not block event loop
bdraco Feb 9, 2023
0d89e9d
Merge branch 'ensure_recorder_shutdown' into ii
bdraco Feb 9, 2023
7e9ca89
do the session in the executor as well
bdraco Feb 9, 2023
7ae6e20
Merge branch 'ensure_recorder_shutdown' into ii
bdraco Feb 9, 2023
2f4e86b
safer
bdraco Feb 9, 2023
10acbbf
Merge branch 'ensure_recorder_shutdown' into ii
bdraco Feb 9, 2023
7e4a272
Merge branch 'dev' into ii
bdraco Feb 9, 2023
b33e9ca
Update tests/components/recorder/test_init.py
bdraco Feb 9, 2023
0cabe31
Merge branch 'dev' into ii
bdraco Feb 9, 2023
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
4 changes: 2 additions & 2 deletions homeassistant/components/recorder/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -1217,13 +1217,13 @@ 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)

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
8 changes: 7 additions & 1 deletion tests/components/recorder/test_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,10 @@ async def test_shutdown_before_startup_finishes(
assert run_info.run_id == 1
assert run_info.start is not None
assert run_info.end is not None
# We patched out engine to prevent the close from happening
# so we need to manually close the session
session.close()
await hass.async_add_executor_job(instance._shutdown)


async def test_canceled_before_startup_finishes(
Expand All @@ -152,6 +156,9 @@ async def test_canceled_before_startup_finishes(
"Recorder startup was externally canceled before it could complete"
in caplog.text
)
# We patched out engine to prevent the close from happening
# so we need to manually close the session
await hass.async_add_executor_job(instance._shutdown)


async def test_shutdown_closes_connections(recorder_mock, hass):
Expand Down Expand Up @@ -1624,7 +1631,6 @@ async def test_database_lock_timeout(recorder_mock, hass, recorder_db_url):
return

hass.bus.async_fire(EVENT_HOMEASSISTANT_STOP)
Comment thread
bdraco marked this conversation as resolved.

instance = get_instance(hass)

class BlockQueue(recorder.tasks.RecorderTask):
Expand Down
2 changes: 2 additions & 0 deletions tests/components/recorder/test_migrate.py
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,7 @@ def test_forgiving_add_column(recorder_db_url: str) -> None:
migration._add_columns(
instance.get_session, "hello", ["context_id CHARACTER(36)"]
)
engine.dispose()


def test_forgiving_add_index(recorder_db_url: str) -> None:
Expand All @@ -446,6 +447,7 @@ def test_forgiving_add_index(recorder_db_url: str) -> None:
instance = Mock()
instance.get_session = Mock(return_value=session)
migration._create_index(instance.get_session, "states", "ix_states_context_id")
engine.dispose()


@pytest.mark.parametrize(
Expand Down
22 changes: 18 additions & 4 deletions tests/components/recorder/test_run_history.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,13 @@
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.helpers import recorder as recorder_helper
from homeassistant.setup import async_setup_component
from homeassistant.util import dt as dt_util

from .common import async_wait_recording_done


async def test_run_history(recorder_mock, hass):
"""Test the run history gives the correct run."""
Expand Down Expand Up @@ -47,12 +52,21 @@ 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."""
async def test_run_history_while_recorder_is_not_yet_started(
recorder_db_url: str, hass: HomeAssistant
) -> None:
"""Test the run history while recorder is not yet started.

This usually happens during schema migration because
we do not start right away.
"""
recorder_helper.async_initialize_recorder(hass)
await async_setup_component(
hass, "recorder", {"recorder": {"db_url": recorder_db_url}}
)
instance = recorder.get_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)
await async_wait_recording_done(hass)
assert run_history.current.start == run_history.recording_start
assert run_history.current.created >= run_history.recording_start
10 changes: 5 additions & 5 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -1077,17 +1077,17 @@ def _ha_orm_quote(mixed, ident):
made_url = sa.make_url(db_url)
db = made_url.database
engine = sa.create_engine(db_url)
# Kill any open connections to the database before dropping it
# Check for any open connections to the database before dropping it
# to ensure that InnoDB does not deadlock.
with engine.begin() as connection:
query = sa.text(
"select id FROM information_schema.processlist WHERE db=:db and id != CONNECTION_ID()"
)
for row in connection.execute(query, parameters={"db": db}).fetchall():
_LOGGER.warning(
"Killing MySQL connection to temporary database %s", row.id
rows = connection.execute(query, parameters={"db": db}).fetchall()
if rows:
raise RuntimeError(
f"Unable to drop database {db} because it is in use by {rows}"
)
connection.execute(sa.text("KILL :id"), parameters={"id": row.id})
engine.dispose()
Comment thread
bdraco marked this conversation as resolved.
sqlalchemy_utils.drop_database(db_url)
elif db_url.startswith("postgresql://"):
Expand Down