Fix setup race when config entry is in a setup retry state (#73145)
parent
0c21bf7c25
commit
2e47cee72a
|
@ -90,6 +90,8 @@ class ConfigEntryState(Enum):
|
|||
"""The config entry has not been loaded"""
|
||||
FAILED_UNLOAD = "failed_unload", False
|
||||
"""An error occurred when trying to unload the entry"""
|
||||
SETUP_IN_PROGRESS = "setup_in_progress", True
|
||||
"""The config entry is setting up."""
|
||||
|
||||
_recoverable: bool
|
||||
|
||||
|
@ -294,6 +296,10 @@ class ConfigEntry:
|
|||
if integration is None:
|
||||
integration = await loader.async_get_integration(hass, self.domain)
|
||||
|
||||
# Only store setup result as state if it was not forwarded.
|
||||
if self.domain == integration.domain:
|
||||
self.state = ConfigEntryState.SETUP_IN_PROGRESS
|
||||
|
||||
self.supports_unload = await support_entry_unload(hass, self.domain)
|
||||
self.supports_remove_device = await support_remove_from_device(
|
||||
hass, self.domain
|
||||
|
|
|
@ -16,7 +16,7 @@ from homeassistant.const import (
|
|||
EVENT_HOMEASSISTANT_STARTED,
|
||||
EVENT_HOMEASSISTANT_STOP,
|
||||
)
|
||||
from homeassistant.core import CoreState, Event, callback
|
||||
from homeassistant.core import CoreState, Event, HomeAssistant, callback
|
||||
from homeassistant.data_entry_flow import RESULT_TYPE_ABORT, BaseServiceInfo, FlowResult
|
||||
from homeassistant.exceptions import (
|
||||
ConfigEntryAuthFailed,
|
||||
|
@ -3190,3 +3190,73 @@ async def test_entry_reload_concurrency(hass, manager):
|
|||
await asyncio.gather(*tasks)
|
||||
assert entry.state is config_entries.ConfigEntryState.LOADED
|
||||
assert loaded == 1
|
||||
|
||||
|
||||
async def test_unique_id_update_while_setup_in_progress(
|
||||
hass: HomeAssistant, manager: config_entries.ConfigEntries
|
||||
) -> None:
|
||||
"""Test we handle the case where the config entry is updated while setup is in progress."""
|
||||
|
||||
async def mock_setup_entry(hass, entry):
|
||||
"""Mock setting up entry."""
|
||||
await asyncio.sleep(0.1)
|
||||
return True
|
||||
|
||||
async def mock_unload_entry(hass, entry):
|
||||
"""Mock unloading an entry."""
|
||||
return True
|
||||
|
||||
hass.config.components.add("comp")
|
||||
entry = MockConfigEntry(
|
||||
domain="comp",
|
||||
data={"additional": "data", "host": "0.0.0.0"},
|
||||
unique_id="mock-unique-id",
|
||||
state=config_entries.ConfigEntryState.SETUP_RETRY,
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
mock_integration(
|
||||
hass,
|
||||
MockModule(
|
||||
"comp",
|
||||
async_setup_entry=mock_setup_entry,
|
||||
async_unload_entry=mock_unload_entry,
|
||||
),
|
||||
)
|
||||
mock_entity_platform(hass, "config_flow.comp", None)
|
||||
updates = {"host": "1.1.1.1"}
|
||||
|
||||
hass.async_create_task(hass.config_entries.async_reload(entry.entry_id))
|
||||
await asyncio.sleep(0)
|
||||
assert entry.state is config_entries.ConfigEntryState.SETUP_IN_PROGRESS
|
||||
|
||||
class TestFlow(config_entries.ConfigFlow):
|
||||
"""Test flow."""
|
||||
|
||||
VERSION = 1
|
||||
|
||||
async def async_step_user(self, user_input=None):
|
||||
"""Test user step."""
|
||||
await self.async_set_unique_id("mock-unique-id")
|
||||
await self._abort_if_unique_id_configured(
|
||||
updates=updates, reload_on_update=True
|
||||
)
|
||||
|
||||
with patch.dict(config_entries.HANDLERS, {"comp": TestFlow}), patch(
|
||||
"homeassistant.config_entries.ConfigEntries.async_reload"
|
||||
) as async_reload:
|
||||
result = await manager.flow.async_init(
|
||||
"comp", context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result["type"] == RESULT_TYPE_ABORT
|
||||
assert result["reason"] == "already_configured"
|
||||
assert entry.data["host"] == "1.1.1.1"
|
||||
assert entry.data["additional"] == "data"
|
||||
|
||||
# Setup is already in progress, we should not reload
|
||||
# if it fails it will go into a retry state and try again
|
||||
assert len(async_reload.mock_calls) == 0
|
||||
await hass.async_block_till_done()
|
||||
assert entry.state is config_entries.ConfigEntryState.LOADED
|
||||
|
|
Loading…
Reference in New Issue