Prevent config entry retry from blocking startup (#48660)

- If there are two integrations doing long retries async_block_till_done() will never be done
This commit is contained in:
J. Nick Koston 2021-04-03 14:00:22 -10:00 committed by GitHub
parent 86176f1bf9
commit cfe2df9ebd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 40 additions and 6 deletions

View File

@ -11,7 +11,8 @@ import weakref
import attr
from homeassistant import data_entry_flow, loader
from homeassistant.core import CALLBACK_TYPE, HomeAssistant, callback
from homeassistant.const import EVENT_HOMEASSISTANT_STARTED
from homeassistant.core import CALLBACK_TYPE, CoreState, HomeAssistant, callback
from homeassistant.exceptions import ConfigEntryNotReady, HomeAssistantError
from homeassistant.helpers import device_registry, entity_registry
from homeassistant.helpers.event import Event
@ -276,14 +277,19 @@ class ConfigEntry:
wait_time,
)
async def setup_again(now: Any) -> None:
async def setup_again(*_: Any) -> None:
"""Run setup again."""
self._async_cancel_retry_setup = None
await self.async_setup(hass, integration=integration, tries=tries)
self._async_cancel_retry_setup = hass.helpers.event.async_call_later(
wait_time, setup_again
)
if hass.state == CoreState.running:
self._async_cancel_retry_setup = hass.helpers.event.async_call_later(
wait_time, setup_again
)
else:
self._async_cancel_retry_setup = hass.bus.async_listen_once(
EVENT_HOMEASSISTANT_STARTED, setup_again
)
return
except Exception: # pylint: disable=broad-except
_LOGGER.exception(

View File

@ -6,7 +6,8 @@ from unittest.mock import AsyncMock, patch
import pytest
from homeassistant import config_entries, data_entry_flow, loader
from homeassistant.core import callback
from homeassistant.const import EVENT_HOMEASSISTANT_STARTED
from homeassistant.core import CoreState, callback
from homeassistant.exceptions import ConfigEntryNotReady, HomeAssistantError
from homeassistant.helpers import entity_registry as er
from homeassistant.setup import async_setup_component
@ -904,6 +905,33 @@ async def test_setup_retrying_during_unload(hass):
assert len(mock_call.return_value.mock_calls) == 1
async def test_setup_retrying_during_unload_before_started(hass):
"""Test if we unload an entry that is in retry mode before started."""
entry = MockConfigEntry(domain="test")
hass.state = CoreState.starting
initial_listeners = hass.bus.async_listeners()[EVENT_HOMEASSISTANT_STARTED]
mock_setup_entry = AsyncMock(side_effect=ConfigEntryNotReady)
mock_integration(hass, MockModule("test", async_setup_entry=mock_setup_entry))
mock_entity_platform(hass, "config_flow.test", None)
await entry.async_setup(hass)
await hass.async_block_till_done()
assert entry.state == config_entries.ENTRY_STATE_SETUP_RETRY
assert (
hass.bus.async_listeners()[EVENT_HOMEASSISTANT_STARTED] == initial_listeners + 1
)
await entry.async_unload(hass)
await hass.async_block_till_done()
assert entry.state == config_entries.ENTRY_STATE_NOT_LOADED
assert (
hass.bus.async_listeners()[EVENT_HOMEASSISTANT_STARTED] == initial_listeners + 0
)
async def test_entry_options(hass, manager):
"""Test that we can set options on an entry."""
entry = MockConfigEntry(domain="test", data={"first": True}, options=None)