Ensure we do not start discovered flows until after the started event has fired (#38047)
* Ensure we do not start discovered flows until after the start event has fired This change makes zeroconf and ssdp match discovery behavior of not creating config flows until the start event has been fired. This prevents config flow creation/dependency installs for discovered config flows from competing for cpu time during startup. * Start discovery/service browser/ssdp when EVENT_HOMEASSISTANT_STARTED is fired instead of EVENT_HOMEASSISTANT_START
This commit is contained in:
parent
e766a119d2
commit
5cf7b1b1bc
5 changed files with 43 additions and 10 deletions
|
@ -15,7 +15,7 @@ import voluptuous as vol
|
|||
|
||||
from homeassistant import config_entries
|
||||
from homeassistant.components import zeroconf
|
||||
from homeassistant.const import EVENT_HOMEASSISTANT_START
|
||||
from homeassistant.const import EVENT_HOMEASSISTANT_STARTED
|
||||
from homeassistant.core import callback
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.discovery import async_discover, async_load_platform
|
||||
|
@ -209,7 +209,7 @@ async def async_setup(hass, config):
|
|||
"""Schedule the first discovery when Home Assistant starts up."""
|
||||
async_track_point_in_utc_time(hass, scan_devices, dt_util.utcnow())
|
||||
|
||||
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_START, schedule_first)
|
||||
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STARTED, schedule_first)
|
||||
|
||||
return True
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import aiohttp
|
|||
from defusedxml import ElementTree
|
||||
from netdisco import ssdp, util
|
||||
|
||||
from homeassistant.const import EVENT_HOMEASSISTANT_STARTED
|
||||
from homeassistant.generated.ssdp import SSDP
|
||||
from homeassistant.helpers.event import async_track_time_interval
|
||||
|
||||
|
@ -33,12 +34,12 @@ _LOGGER = logging.getLogger(__name__)
|
|||
async def async_setup(hass, config):
|
||||
"""Set up the SSDP integration."""
|
||||
|
||||
async def initialize():
|
||||
async def initialize(_):
|
||||
scanner = Scanner(hass)
|
||||
await scanner.async_scan(None)
|
||||
async_track_time_interval(hass, scanner.async_scan, SCAN_INTERVAL)
|
||||
|
||||
hass.loop.create_task(initialize())
|
||||
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STARTED, initialize)
|
||||
|
||||
return True
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ from homeassistant import util
|
|||
from homeassistant.const import (
|
||||
ATTR_NAME,
|
||||
EVENT_HOMEASSISTANT_START,
|
||||
EVENT_HOMEASSISTANT_STARTED,
|
||||
EVENT_HOMEASSISTANT_STOP,
|
||||
__version__,
|
||||
)
|
||||
|
@ -247,7 +248,13 @@ def setup(hass, config):
|
|||
if HOMEKIT_TYPE not in ZEROCONF:
|
||||
types.append(HOMEKIT_TYPE)
|
||||
|
||||
HaServiceBrowser(zeroconf, types, handlers=[service_update])
|
||||
def zeroconf_hass_started(_event):
|
||||
"""Start the service browser."""
|
||||
|
||||
_LOGGER.debug("Starting Zeroconf browser")
|
||||
HaServiceBrowser(zeroconf, types, handlers=[service_update])
|
||||
|
||||
hass.bus.listen_once(EVENT_HOMEASSISTANT_STARTED, zeroconf_hass_started)
|
||||
|
||||
return True
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import pytest
|
|||
from homeassistant import config_entries
|
||||
from homeassistant.bootstrap import async_setup_component
|
||||
from homeassistant.components import discovery
|
||||
from homeassistant.const import EVENT_HOMEASSISTANT_STARTED
|
||||
from homeassistant.util.dt import utcnow
|
||||
|
||||
from tests.async_mock import patch
|
||||
|
@ -36,10 +37,12 @@ def netdisco_mock():
|
|||
|
||||
async def mock_discovery(hass, discoveries, config=BASE_CONFIG):
|
||||
"""Mock discoveries."""
|
||||
result = await async_setup_component(hass, "discovery", config)
|
||||
assert result
|
||||
|
||||
await hass.async_start()
|
||||
with patch("homeassistant.components.zeroconf.async_get_instance"):
|
||||
assert await async_setup_component(hass, "discovery", config)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_start()
|
||||
hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
with patch.object(discovery, "_discover", discoveries), patch(
|
||||
"homeassistant.components.discovery.async_discover", return_value=mock_coro()
|
||||
|
|
|
@ -4,7 +4,7 @@ from zeroconf import InterfaceChoice, IPVersion, ServiceInfo, ServiceStateChange
|
|||
|
||||
from homeassistant.components import zeroconf
|
||||
from homeassistant.components.zeroconf import CONF_DEFAULT_INTERFACE, CONF_IPV6
|
||||
from homeassistant.const import EVENT_HOMEASSISTANT_STOP
|
||||
from homeassistant.const import EVENT_HOMEASSISTANT_STARTED, EVENT_HOMEASSISTANT_STOP
|
||||
from homeassistant.generated import zeroconf as zc_gen
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
|
@ -76,6 +76,8 @@ async def test_setup(hass, mock_zeroconf):
|
|||
) as mock_service_browser:
|
||||
mock_zeroconf.get_service_info.side_effect = get_service_info_mock
|
||||
assert await async_setup_component(hass, zeroconf.DOMAIN, {zeroconf.DOMAIN: {}})
|
||||
hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(mock_service_browser.mock_calls) == 1
|
||||
expected_flow_calls = 0
|
||||
|
@ -97,6 +99,8 @@ async def test_setup_with_default_interface(hass, mock_zeroconf):
|
|||
assert await async_setup_component(
|
||||
hass, zeroconf.DOMAIN, {zeroconf.DOMAIN: {CONF_DEFAULT_INTERFACE: True}}
|
||||
)
|
||||
hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert mock_zeroconf.called_with(interface_choice=InterfaceChoice.Default)
|
||||
|
||||
|
@ -123,6 +127,8 @@ async def test_setup_without_ipv6(hass, mock_zeroconf):
|
|||
assert await async_setup_component(
|
||||
hass, zeroconf.DOMAIN, {zeroconf.DOMAIN: {CONF_IPV6: False}}
|
||||
)
|
||||
hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert mock_zeroconf.called_with(ip_version=IPVersion.V4Only)
|
||||
|
||||
|
@ -136,6 +142,8 @@ async def test_setup_with_ipv6(hass, mock_zeroconf):
|
|||
assert await async_setup_component(
|
||||
hass, zeroconf.DOMAIN, {zeroconf.DOMAIN: {CONF_IPV6: True}}
|
||||
)
|
||||
hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert mock_zeroconf.called_with()
|
||||
|
||||
|
@ -147,6 +155,8 @@ async def test_setup_with_ipv6_default(hass, mock_zeroconf):
|
|||
):
|
||||
mock_zeroconf.get_service_info.side_effect = get_service_info_mock
|
||||
assert await async_setup_component(hass, zeroconf.DOMAIN, {zeroconf.DOMAIN: {}})
|
||||
hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert mock_zeroconf.called_with()
|
||||
|
||||
|
@ -164,6 +174,8 @@ async def test_homekit_match_partial_space(hass, mock_zeroconf):
|
|||
"LIFX bulb", HOMEKIT_STATUS_UNPAIRED
|
||||
)
|
||||
assert await async_setup_component(hass, zeroconf.DOMAIN, {zeroconf.DOMAIN: {}})
|
||||
hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(mock_service_browser.mock_calls) == 1
|
||||
assert len(mock_config_flow.mock_calls) == 1
|
||||
|
@ -183,6 +195,8 @@ async def test_homekit_match_partial_dash(hass, mock_zeroconf):
|
|||
"Rachio-fa46ba", HOMEKIT_STATUS_UNPAIRED
|
||||
)
|
||||
assert await async_setup_component(hass, zeroconf.DOMAIN, {zeroconf.DOMAIN: {}})
|
||||
hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(mock_service_browser.mock_calls) == 1
|
||||
assert len(mock_config_flow.mock_calls) == 1
|
||||
|
@ -202,6 +216,8 @@ async def test_homekit_match_full(hass, mock_zeroconf):
|
|||
"BSB002", HOMEKIT_STATUS_UNPAIRED
|
||||
)
|
||||
assert await async_setup_component(hass, zeroconf.DOMAIN, {zeroconf.DOMAIN: {}})
|
||||
hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
homekit_mock = get_homekit_info_mock("BSB002", HOMEKIT_STATUS_UNPAIRED)
|
||||
info = homekit_mock("_hap._tcp.local.", "BSB002._hap._tcp.local.")
|
||||
|
@ -226,6 +242,8 @@ async def test_homekit_already_paired(hass, mock_zeroconf):
|
|||
"tado", HOMEKIT_STATUS_PAIRED
|
||||
)
|
||||
assert await async_setup_component(hass, zeroconf.DOMAIN, {zeroconf.DOMAIN: {}})
|
||||
hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(mock_service_browser.mock_calls) == 1
|
||||
assert len(mock_config_flow.mock_calls) == 2
|
||||
|
@ -246,6 +264,8 @@ async def test_homekit_invalid_paring_status(hass, mock_zeroconf):
|
|||
"tado", b"invalid"
|
||||
)
|
||||
assert await async_setup_component(hass, zeroconf.DOMAIN, {zeroconf.DOMAIN: {}})
|
||||
hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(mock_service_browser.mock_calls) == 1
|
||||
assert len(mock_config_flow.mock_calls) == 1
|
||||
|
@ -265,6 +285,8 @@ async def test_homekit_not_paired(hass, mock_zeroconf):
|
|||
"this_will_not_match_any_integration", HOMEKIT_STATUS_UNPAIRED
|
||||
)
|
||||
assert await async_setup_component(hass, zeroconf.DOMAIN, {zeroconf.DOMAIN: {}})
|
||||
hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(mock_service_browser.mock_calls) == 1
|
||||
assert len(mock_config_flow.mock_calls) == 1
|
||||
|
|
Loading…
Add table
Reference in a new issue