mirror of
https://github.com/home-assistant/core.git
synced 2025-07-08 05:47:10 +00:00
Improve error message for global timeout (#141563)
* Improve error message for global timeout * Add test * Message works with zone too
This commit is contained in:
parent
d25ba79427
commit
b36b591ccf
@ -929,7 +929,11 @@ async def _async_set_up_integrations(
|
||||
await _async_setup_multi_components(hass, stage_all_domains, config)
|
||||
continue
|
||||
try:
|
||||
async with hass.timeout.async_timeout(timeout, cool_down=COOLDOWN_TIME):
|
||||
async with hass.timeout.async_timeout(
|
||||
timeout,
|
||||
cool_down=COOLDOWN_TIME,
|
||||
cancel_message=f"Bootstrap stage {name} timeout",
|
||||
):
|
||||
await _async_setup_multi_components(hass, stage_all_domains, config)
|
||||
except TimeoutError:
|
||||
_LOGGER.warning(
|
||||
@ -941,7 +945,11 @@ async def _async_set_up_integrations(
|
||||
# Wrap up startup
|
||||
_LOGGER.debug("Waiting for startup to wrap up")
|
||||
try:
|
||||
async with hass.timeout.async_timeout(WRAP_UP_TIMEOUT, cool_down=COOLDOWN_TIME):
|
||||
async with hass.timeout.async_timeout(
|
||||
WRAP_UP_TIMEOUT,
|
||||
cool_down=COOLDOWN_TIME,
|
||||
cancel_message="Bootstrap startup wrap up timeout",
|
||||
):
|
||||
await hass.async_block_till_done()
|
||||
except TimeoutError:
|
||||
_LOGGER.warning(
|
||||
|
@ -148,6 +148,7 @@ class _GlobalTaskContext:
|
||||
task: asyncio.Task[Any],
|
||||
timeout: float,
|
||||
cool_down: float,
|
||||
cancel_message: str | None,
|
||||
) -> None:
|
||||
"""Initialize internal timeout context manager."""
|
||||
self._loop: asyncio.AbstractEventLoop = asyncio.get_running_loop()
|
||||
@ -161,6 +162,7 @@ class _GlobalTaskContext:
|
||||
self._state: _State = _State.INIT
|
||||
self._cool_down: float = cool_down
|
||||
self._cancelling = 0
|
||||
self._cancel_message = cancel_message
|
||||
|
||||
async def __aenter__(self) -> Self:
|
||||
self._manager.global_tasks.append(self)
|
||||
@ -242,7 +244,9 @@ class _GlobalTaskContext:
|
||||
"""Cancel own task."""
|
||||
if self._task.done():
|
||||
return
|
||||
self._task.cancel("Global task timeout")
|
||||
self._task.cancel(
|
||||
f"Global task timeout{': ' + self._cancel_message if self._cancel_message else ''}"
|
||||
)
|
||||
|
||||
def pause(self) -> None:
|
||||
"""Pause timers while it freeze."""
|
||||
@ -270,6 +274,7 @@ class _ZoneTaskContext:
|
||||
zone: _ZoneTimeoutManager,
|
||||
task: asyncio.Task[Any],
|
||||
timeout: float,
|
||||
cancel_message: str | None,
|
||||
) -> None:
|
||||
"""Initialize internal timeout context manager."""
|
||||
self._loop: asyncio.AbstractEventLoop = asyncio.get_running_loop()
|
||||
@ -280,6 +285,7 @@ class _ZoneTaskContext:
|
||||
self._expiration_time: float | None = None
|
||||
self._timeout_handler: asyncio.Handle | None = None
|
||||
self._cancelling = 0
|
||||
self._cancel_message = cancel_message
|
||||
|
||||
@property
|
||||
def state(self) -> _State:
|
||||
@ -354,7 +360,9 @@ class _ZoneTaskContext:
|
||||
# Timeout
|
||||
if self._task.done():
|
||||
return
|
||||
self._task.cancel("Zone timeout")
|
||||
self._task.cancel(
|
||||
f"Zone timeout{': ' + self._cancel_message if self._cancel_message else ''}"
|
||||
)
|
||||
|
||||
def pause(self) -> None:
|
||||
"""Pause timers while it freeze."""
|
||||
@ -486,7 +494,11 @@ class TimeoutManager:
|
||||
task.zones_done_signal()
|
||||
|
||||
def async_timeout(
|
||||
self, timeout: float, zone_name: str = ZONE_GLOBAL, cool_down: float = 0
|
||||
self,
|
||||
timeout: float,
|
||||
zone_name: str = ZONE_GLOBAL,
|
||||
cool_down: float = 0,
|
||||
cancel_message: str | None = None,
|
||||
) -> _ZoneTaskContext | _GlobalTaskContext:
|
||||
"""Timeout based on a zone.
|
||||
|
||||
@ -497,7 +509,9 @@ class TimeoutManager:
|
||||
|
||||
# Global Zone
|
||||
if zone_name == ZONE_GLOBAL:
|
||||
return _GlobalTaskContext(self, current_task, timeout, cool_down)
|
||||
return _GlobalTaskContext(
|
||||
self, current_task, timeout, cool_down, cancel_message
|
||||
)
|
||||
|
||||
# Zone Handling
|
||||
if zone_name in self.zones:
|
||||
@ -506,7 +520,7 @@ class TimeoutManager:
|
||||
self.zones[zone_name] = zone = _ZoneTimeoutManager(self, zone_name)
|
||||
|
||||
# Create Task
|
||||
return _ZoneTaskContext(zone, current_task, timeout)
|
||||
return _ZoneTaskContext(zone, current_task, timeout, cancel_message)
|
||||
|
||||
def async_freeze(
|
||||
self, zone_name: str = ZONE_GLOBAL
|
||||
|
@ -36,6 +36,18 @@ async def test_simple_global_timeout_freeze() -> None:
|
||||
await asyncio.sleep(0.3)
|
||||
|
||||
|
||||
async def test_simple_global_timeout_cancel_message() -> None:
|
||||
"""Test a simple global timeout cancel message."""
|
||||
timeout = TimeoutManager()
|
||||
|
||||
with suppress(TimeoutError):
|
||||
async with timeout.async_timeout(0.1, cancel_message="Test"):
|
||||
with pytest.raises(
|
||||
asyncio.CancelledError, match="Global task timeout: Test"
|
||||
):
|
||||
await asyncio.sleep(0.3)
|
||||
|
||||
|
||||
async def test_simple_zone_timeout_freeze_inside_executor_job(
|
||||
hass: HomeAssistant,
|
||||
) -> None:
|
||||
@ -222,6 +234,16 @@ async def test_simple_zone_timeout() -> None:
|
||||
await asyncio.sleep(0.3)
|
||||
|
||||
|
||||
async def test_simple_zone_timeout_cancel_message() -> None:
|
||||
"""Test a simple zone timeout cancel message."""
|
||||
timeout = TimeoutManager()
|
||||
|
||||
with suppress(TimeoutError):
|
||||
async with timeout.async_timeout(0.1, "test", cancel_message="Test"):
|
||||
with pytest.raises(asyncio.CancelledError, match="Zone timeout: Test"):
|
||||
await asyncio.sleep(0.3)
|
||||
|
||||
|
||||
async def test_simple_zone_timeout_does_not_leak_upward(
|
||||
hass: HomeAssistant,
|
||||
) -> None:
|
||||
|
Loading…
x
Reference in New Issue
Block a user