Refactor integration startup time to show wall clock time (#113707)
* Refactor setup time tracking to exclude time waiting on other operations We now exclude the import time and th time waiting on base platforms to setup from the setup times * tweak * tweak * tweak * tweak * adjust * fixes * fixes * preen * preen * tweak * tweak * adjust * tweak * reduce * do not count integrtion platforms against their parent integration * handle legacy tts platforms * stt as well * one more wait * use the same pattern in all the legacy * fix tts and stt legacy * fix * fix * reduce * preen * entity comp does not wait for platforms * scene blocks as well * fix test * test fixes * coverage * coverage * coverage * fix test * Update tests/test_setup.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Update tests/test_setup.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Update homeassistant/setup.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * strip * strip WAIT_PLATFORM_INTEGRATION * strip WAIT_PLATFORM_INTEGRATION * strip WAIT_PLATFORM_INTEGRATION * strip WAIT_PLATFORM_INTEGRATION * remove complexity * Apply suggestions from code review * no longer works that way * fixes * fixes * fixes --------- Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
This commit is contained in:
parent
9be5f3531f
commit
c615b52840
20 changed files with 598 additions and 176 deletions
|
@ -32,7 +32,7 @@ from homeassistant.core import (
|
|||
)
|
||||
from homeassistant.exceptions import HomeAssistantError, PlatformNotReady
|
||||
from homeassistant.generated import languages
|
||||
from homeassistant.setup import async_start_setup
|
||||
from homeassistant.setup import SetupPhases, async_start_setup
|
||||
from homeassistant.util.async_ import create_eager_task
|
||||
|
||||
from . import (
|
||||
|
@ -284,7 +284,13 @@ class EntityPlatform:
|
|||
discovery_info,
|
||||
)
|
||||
|
||||
await self._async_setup_platform(async_create_setup_awaitable)
|
||||
with async_start_setup(
|
||||
hass,
|
||||
integration=self.platform_name,
|
||||
group=str(id(platform_config)),
|
||||
phase=SetupPhases.PLATFORM_SETUP,
|
||||
):
|
||||
await self._async_setup_platform(async_create_setup_awaitable)
|
||||
|
||||
@callback
|
||||
def async_shutdown(self) -> None:
|
||||
|
@ -341,81 +347,78 @@ class EntityPlatform:
|
|||
self.platform_name,
|
||||
SLOW_SETUP_WARNING,
|
||||
)
|
||||
with async_start_setup(hass, [full_name]):
|
||||
try:
|
||||
awaitable = async_create_setup_awaitable()
|
||||
if asyncio.iscoroutine(awaitable):
|
||||
awaitable = create_eager_task(awaitable)
|
||||
try:
|
||||
awaitable = async_create_setup_awaitable()
|
||||
if asyncio.iscoroutine(awaitable):
|
||||
awaitable = create_eager_task(awaitable)
|
||||
|
||||
async with hass.timeout.async_timeout(SLOW_SETUP_MAX_WAIT, self.domain):
|
||||
await asyncio.shield(awaitable)
|
||||
async with hass.timeout.async_timeout(SLOW_SETUP_MAX_WAIT, self.domain):
|
||||
await asyncio.shield(awaitable)
|
||||
|
||||
# Block till all entities are done
|
||||
while self._tasks:
|
||||
# Await all tasks even if they are done
|
||||
# to ensure exceptions are propagated
|
||||
pending = self._tasks.copy()
|
||||
self._tasks.clear()
|
||||
await asyncio.gather(*pending)
|
||||
# Block till all entities are done
|
||||
while self._tasks:
|
||||
# Await all tasks even if they are done
|
||||
# to ensure exceptions are propagated
|
||||
pending = self._tasks.copy()
|
||||
self._tasks.clear()
|
||||
await asyncio.gather(*pending)
|
||||
|
||||
hass.config.components.add(full_name)
|
||||
self._setup_complete = True
|
||||
return True
|
||||
except PlatformNotReady as ex:
|
||||
tries += 1
|
||||
wait_time = min(tries, 6) * PLATFORM_NOT_READY_BASE_WAIT_TIME
|
||||
message = str(ex)
|
||||
ready_message = f"ready yet: {message}" if message else "ready yet"
|
||||
if tries == 1:
|
||||
logger.warning(
|
||||
"Platform %s not %s; Retrying in background in %d seconds",
|
||||
self.platform_name,
|
||||
ready_message,
|
||||
wait_time,
|
||||
)
|
||||
else:
|
||||
logger.debug(
|
||||
"Platform %s not %s; Retrying in %d seconds",
|
||||
self.platform_name,
|
||||
ready_message,
|
||||
wait_time,
|
||||
)
|
||||
|
||||
async def setup_again(*_args: Any) -> None:
|
||||
"""Run setup again."""
|
||||
self._async_cancel_retry_setup = None
|
||||
await self._async_setup_platform(
|
||||
async_create_setup_awaitable, tries
|
||||
)
|
||||
|
||||
if hass.state is CoreState.running:
|
||||
self._async_cancel_retry_setup = async_call_later(
|
||||
hass, wait_time, setup_again
|
||||
)
|
||||
else:
|
||||
self._async_cancel_retry_setup = hass.bus.async_listen_once(
|
||||
EVENT_HOMEASSISTANT_STARTED, setup_again
|
||||
)
|
||||
return False
|
||||
except TimeoutError:
|
||||
logger.error(
|
||||
(
|
||||
"Setup of platform %s is taking longer than %s seconds."
|
||||
" Startup will proceed without waiting any longer."
|
||||
),
|
||||
hass.config.components.add(full_name)
|
||||
self._setup_complete = True
|
||||
return True
|
||||
except PlatformNotReady as ex:
|
||||
tries += 1
|
||||
wait_time = min(tries, 6) * PLATFORM_NOT_READY_BASE_WAIT_TIME
|
||||
message = str(ex)
|
||||
ready_message = f"ready yet: {message}" if message else "ready yet"
|
||||
if tries == 1:
|
||||
logger.warning(
|
||||
"Platform %s not %s; Retrying in background in %d seconds",
|
||||
self.platform_name,
|
||||
SLOW_SETUP_MAX_WAIT,
|
||||
ready_message,
|
||||
wait_time,
|
||||
)
|
||||
return False
|
||||
except Exception: # pylint: disable=broad-except
|
||||
logger.exception(
|
||||
"Error while setting up %s platform for %s",
|
||||
else:
|
||||
logger.debug(
|
||||
"Platform %s not %s; Retrying in %d seconds",
|
||||
self.platform_name,
|
||||
self.domain,
|
||||
ready_message,
|
||||
wait_time,
|
||||
)
|
||||
return False
|
||||
finally:
|
||||
warn_task.cancel()
|
||||
|
||||
async def setup_again(*_args: Any) -> None:
|
||||
"""Run setup again."""
|
||||
self._async_cancel_retry_setup = None
|
||||
await self._async_setup_platform(async_create_setup_awaitable, tries)
|
||||
|
||||
if hass.state is CoreState.running:
|
||||
self._async_cancel_retry_setup = async_call_later(
|
||||
hass, wait_time, setup_again
|
||||
)
|
||||
else:
|
||||
self._async_cancel_retry_setup = hass.bus.async_listen_once(
|
||||
EVENT_HOMEASSISTANT_STARTED, setup_again
|
||||
)
|
||||
return False
|
||||
except TimeoutError:
|
||||
logger.error(
|
||||
(
|
||||
"Setup of platform %s is taking longer than %s seconds."
|
||||
" Startup will proceed without waiting any longer."
|
||||
),
|
||||
self.platform_name,
|
||||
SLOW_SETUP_MAX_WAIT,
|
||||
)
|
||||
return False
|
||||
except Exception: # pylint: disable=broad-except
|
||||
logger.exception(
|
||||
"Error while setting up %s platform for %s",
|
||||
self.platform_name,
|
||||
self.domain,
|
||||
)
|
||||
return False
|
||||
finally:
|
||||
warn_task.cancel()
|
||||
|
||||
async def _async_get_translations(
|
||||
self, language: str, category: str, integration: str
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue