mirror of
https://github.com/home-assistant/core.git
synced 2026-10-07 06:50:41 -04:00
Use wait_shared_future in singleton helper (#183889)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
5153c2a3c2
commit
da2a753a0b
@@ -7,6 +7,7 @@ import inspect
|
||||
from typing import Any, Literal, assert_type, cast, overload
|
||||
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.util.async_ import wait_shared_future
|
||||
from homeassistant.util.hass_dict import HassKey
|
||||
|
||||
type _FuncType[_T] = Callable[[HomeAssistant], _T]
|
||||
@@ -78,7 +79,7 @@ def singleton[_S, _T, _U](
|
||||
obj_or_future = hass.data[data_key]
|
||||
|
||||
if isinstance(obj_or_future, asyncio.Future):
|
||||
return cast(_T, await obj_or_future)
|
||||
return cast(_T, await wait_shared_future(obj_or_future))
|
||||
|
||||
return cast(_T, obj_or_future)
|
||||
|
||||
|
||||
@@ -101,3 +101,32 @@ async def test_singleton_async_concurrent_raises(mock_hass: HomeAssistant) -> No
|
||||
# Only the first caller ran the wrapped function; the waiter observed its error.
|
||||
assert calls == 1
|
||||
assert "test_key" not in mock_hass.data
|
||||
|
||||
|
||||
async def test_singleton_async_concurrent_waiter_cancelled(
|
||||
mock_hass: HomeAssistant,
|
||||
) -> None:
|
||||
"""Verify cancelling a waiting caller does not break the in-progress call."""
|
||||
release = asyncio.Event()
|
||||
result = object()
|
||||
|
||||
@singleton.singleton("test_key")
|
||||
async def something(hass: HomeAssistant) -> Any:
|
||||
await release.wait()
|
||||
return result
|
||||
|
||||
task1 = asyncio.create_task(something(mock_hass))
|
||||
await asyncio.sleep(0)
|
||||
task2 = asyncio.create_task(something(mock_hass))
|
||||
await asyncio.sleep(0)
|
||||
|
||||
task2.cancel()
|
||||
with pytest.raises(asyncio.CancelledError):
|
||||
await task2
|
||||
|
||||
release.set()
|
||||
async with asyncio.timeout(1):
|
||||
assert await task1 is result
|
||||
|
||||
assert mock_hass.data["test_key"] is result
|
||||
assert await something(mock_hass) is result
|
||||
|
||||
Reference in New Issue
Block a user