mirror of
https://github.com/home-assistant/core.git
synced 2025-07-12 15:57:06 +00:00
Only create a single resolver object if there are multiple aiohttp sessions (#144090)
This commit is contained in:
parent
97be2c4ac9
commit
2890fc7dd2
@ -28,6 +28,7 @@ from homeassistant.util.json import json_loads
|
||||
|
||||
from .frame import warn_use
|
||||
from .json import json_dumps
|
||||
from .singleton import singleton
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from aiohttp.typedefs import JSONDecoder
|
||||
@ -39,6 +40,7 @@ DATA_CONNECTOR: HassKey[dict[tuple[bool, int, str], aiohttp.BaseConnector]] = Ha
|
||||
DATA_CLIENTSESSION: HassKey[dict[tuple[bool, int, str], aiohttp.ClientSession]] = (
|
||||
HassKey("aiohttp_clientsession")
|
||||
)
|
||||
DATA_RESOLVER: HassKey[HassAsyncDNSResolver] = HassKey("aiohttp_resolver")
|
||||
|
||||
SERVER_SOFTWARE = (
|
||||
f"{APPLICATION_NAME}/{__version__} "
|
||||
@ -70,6 +72,21 @@ MAXIMUM_CONNECTIONS = 4096
|
||||
MAXIMUM_CONNECTIONS_PER_HOST = 100
|
||||
|
||||
|
||||
class HassAsyncDNSResolver(AsyncDualMDNSResolver):
|
||||
"""Home Assistant AsyncDNSResolver.
|
||||
|
||||
This is a wrapper around the AsyncDualMDNSResolver to only
|
||||
close the resolver when the Home Assistant instance is closed.
|
||||
"""
|
||||
|
||||
async def real_close(self) -> None:
|
||||
"""Close the resolver."""
|
||||
await super().close()
|
||||
|
||||
async def close(self) -> None:
|
||||
"""Close the resolver."""
|
||||
|
||||
|
||||
class HassClientResponse(aiohttp.ClientResponse):
|
||||
"""aiohttp.ClientResponse with a json method that uses json_loads by default."""
|
||||
|
||||
@ -363,7 +380,7 @@ def _async_get_connector(
|
||||
ssl=ssl_context,
|
||||
limit=MAXIMUM_CONNECTIONS,
|
||||
limit_per_host=MAXIMUM_CONNECTIONS_PER_HOST,
|
||||
resolver=_async_make_resolver(hass),
|
||||
resolver=_async_get_or_create_resolver(hass),
|
||||
)
|
||||
connectors[connector_key] = connector
|
||||
|
||||
@ -376,6 +393,19 @@ def _async_get_connector(
|
||||
return connector
|
||||
|
||||
|
||||
@singleton(DATA_RESOLVER)
|
||||
@callback
|
||||
def _async_make_resolver(hass: HomeAssistant) -> AsyncDualMDNSResolver:
|
||||
return AsyncDualMDNSResolver(async_zeroconf=zeroconf.async_get_async_zeroconf(hass))
|
||||
def _async_get_or_create_resolver(hass: HomeAssistant) -> HassAsyncDNSResolver:
|
||||
"""Return the HassAsyncDNSResolver."""
|
||||
resolver = _async_make_resolver(hass)
|
||||
|
||||
async def _async_close_resolver(event: Event) -> None:
|
||||
await resolver.real_close()
|
||||
|
||||
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_CLOSE, _async_close_resolver)
|
||||
return resolver
|
||||
|
||||
|
||||
@callback
|
||||
def _async_make_resolver(hass: HomeAssistant) -> HassAsyncDNSResolver:
|
||||
return HassAsyncDNSResolver(async_zeroconf=zeroconf.async_get_async_zeroconf(hass))
|
||||
|
@ -1319,9 +1319,11 @@ def disable_translations_once(
|
||||
@pytest_asyncio.fixture(autouse=True, scope="session", loop_scope="session")
|
||||
async def mock_zeroconf_resolver() -> AsyncGenerator[_patch]:
|
||||
"""Mock out the zeroconf resolver."""
|
||||
resolver = AsyncResolver()
|
||||
resolver.real_close = resolver.close
|
||||
patcher = patch(
|
||||
"homeassistant.helpers.aiohttp_client._async_make_resolver",
|
||||
return_value=AsyncResolver(),
|
||||
return_value=resolver,
|
||||
)
|
||||
patcher.start()
|
||||
try:
|
||||
|
@ -401,3 +401,15 @@ async def test_async_mdnsresolver(
|
||||
resp = await session.post("http://localhost/xyz", json={"x": 1})
|
||||
assert resp.status == 200
|
||||
assert await resp.json() == {"x": 1}
|
||||
|
||||
|
||||
async def test_resolver_is_singleton(hass: HomeAssistant) -> None:
|
||||
"""Test that the resolver is a singleton."""
|
||||
session = client.async_get_clientsession(hass)
|
||||
session2 = client.async_get_clientsession(hass)
|
||||
session3 = client.async_create_clientsession(hass)
|
||||
assert isinstance(session._connector, aiohttp.TCPConnector)
|
||||
assert isinstance(session2._connector, aiohttp.TCPConnector)
|
||||
assert isinstance(session3._connector, aiohttp.TCPConnector)
|
||||
assert session._connector._resolver is session2._connector._resolver
|
||||
assert session._connector._resolver is session3._connector._resolver
|
||||
|
Loading…
x
Reference in New Issue
Block a user