diff --git a/homeassistant/components/recorder/core.py b/homeassistant/components/recorder/core.py index 2b8f45703b5..3f284bdd83d 100644 --- a/homeassistant/components/recorder/core.py +++ b/homeassistant/components/recorder/core.py @@ -773,6 +773,7 @@ class Recorder(threading.Thread): "Database Migration Failed", "recorder_database_migration", ) + self.hass.add_job(self._async_startup_failed) return if not database_was_ready: diff --git a/tests/components/recorder/test_migrate.py b/tests/components/recorder/test_migrate.py index 682c0a55767..f32f5c4aaaf 100644 --- a/tests/components/recorder/test_migrate.py +++ b/tests/components/recorder/test_migrate.py @@ -200,8 +200,14 @@ async def test_database_migration_encounters_corruption( assert move_away.called +@pytest.mark.parametrize( + ("live_migration", "expected_setup_result"), [(True, True), (False, False)] +) async def test_database_migration_encounters_corruption_not_sqlite( - hass: HomeAssistant, async_setup_recorder_instance: RecorderInstanceGenerator + hass: HomeAssistant, + async_setup_recorder_instance: RecorderInstanceGenerator, + live_migration: bool, + expected_setup_result: bool, ) -> None: """Test we fail on database error when we cannot recover.""" assert recorder.util.async_migration_in_progress(hass) is False @@ -226,8 +232,14 @@ async def test_database_migration_encounters_corruption_not_sqlite( "homeassistant.components.persistent_notification.dismiss", side_effect=pn.dismiss, ) as mock_dismiss, + patch( + "homeassistant.components.recorder.core.migration.live_migration", + return_value=live_migration, + ), ): - await async_setup_recorder_instance(hass, wait_recorder=False) + await async_setup_recorder_instance( + hass, wait_recorder=False, expected_setup_result=expected_setup_result + ) hass.states.async_set("my.entity", "on", {}) hass.states.async_set("my.entity", "off", {}) await hass.async_block_till_done() diff --git a/tests/conftest.py b/tests/conftest.py index 2c8c351f165..f21dfbec5e7 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1394,6 +1394,8 @@ async def _async_init_recorder_component( hass: HomeAssistant, add_config: dict[str, Any] | None = None, db_url: str | None = None, + *, + expected_setup_result: bool, ) -> None: """Initialize the recorder asynchronously.""" # pylint: disable-next=import-outside-toplevel @@ -1408,10 +1410,13 @@ async def _async_init_recorder_component( with patch("homeassistant.components.recorder.ALLOW_IN_MEMORY_DB", True): if recorder.DOMAIN not in hass.data: recorder_helper.async_initialize_recorder(hass) - assert await async_setup_component( - hass, recorder.DOMAIN, {recorder.DOMAIN: config} + setup_task = asyncio.ensure_future( + async_setup_component(hass, recorder.DOMAIN, {recorder.DOMAIN: config}) ) - assert recorder.DOMAIN in hass.config.components + # Wait for recorder integration to setup + setup_result = await setup_task + assert setup_result == expected_setup_result + assert (recorder.DOMAIN in hass.config.components) == expected_setup_result _LOGGER.info( "Test recorder successfully started, database location: %s", config[recorder.CONF_DB_URL], @@ -1527,10 +1532,16 @@ async def async_test_recorder( hass: HomeAssistant, config: ConfigType | None = None, *, + expected_setup_result: bool = True, wait_recorder: bool = True, ) -> AsyncGenerator[recorder.Recorder]: """Setup and return recorder instance.""" # noqa: D401 - await _async_init_recorder_component(hass, config, recorder_db_url) + await _async_init_recorder_component( + hass, + config, + recorder_db_url, + expected_setup_result=expected_setup_result, + ) await hass.async_block_till_done() instance = hass.data[recorder.DATA_INSTANCE] # The recorder's worker is not started until Home Assistant is running @@ -1557,12 +1568,18 @@ async def async_setup_recorder_instance( hass: HomeAssistant, config: ConfigType | None = None, *, + expected_setup_result: bool = True, wait_recorder: bool = True, ) -> AsyncGenerator[recorder.Recorder]: """Set up and return recorder instance.""" return await stack.enter_async_context( - async_test_recorder(hass, config, wait_recorder=wait_recorder) + async_test_recorder( + hass, + config, + expected_setup_result=expected_setup_result, + wait_recorder=wait_recorder, + ) ) yield async_setup_recorder