Speed up single entity/response service calls (#96729)
* Significantly speed up single entity/response service calls Since the majority of service calls are single entity, we can avoid creating tasks in this case. Since the multi-entity service calls always check the result and raise, we can switch the asyncio.wait to asyncio.gather * Significantly speed up single entity/response service calls Since the majority of service calls are single entity, we can avoid creating tasks in this case. Since the multi-entity service calls always check the result and raise, we can switch the asyncio.wait to asyncio.gather * revert * cannot be inside pytest.raises * one more * Update homeassistant/helpers/service.py
This commit is contained in:
parent
c76fac0633
commit
3a06659120
11 changed files with 50 additions and 18 deletions
|
@ -741,6 +741,8 @@ async def entity_service_call( # noqa: C901
|
|||
Calls all platforms simultaneously.
|
||||
"""
|
||||
entity_perms: None | (Callable[[str, str], bool]) = None
|
||||
return_response = call.return_response
|
||||
|
||||
if call.context.user_id:
|
||||
user = await hass.auth.async_get_user(call.context.user_id)
|
||||
if user is None:
|
||||
|
@ -851,13 +853,27 @@ async def entity_service_call( # noqa: C901
|
|||
entities.append(entity)
|
||||
|
||||
if not entities:
|
||||
if call.return_response:
|
||||
if return_response:
|
||||
raise HomeAssistantError(
|
||||
"Service call requested response data but did not match any entities"
|
||||
)
|
||||
return None
|
||||
|
||||
if call.return_response and len(entities) != 1:
|
||||
if len(entities) == 1:
|
||||
# Single entity case avoids creating tasks and allows returning
|
||||
# ServiceResponse
|
||||
entity = entities[0]
|
||||
response_data = await _handle_entity_call(
|
||||
hass, entity, func, data, call.context
|
||||
)
|
||||
if entity.should_poll:
|
||||
# Context expires if the turn on commands took a long time.
|
||||
# Set context again so it's there when we update
|
||||
entity.async_set_context(call.context)
|
||||
await entity.async_update_ha_state(True)
|
||||
return response_data if return_response else None
|
||||
|
||||
if return_response:
|
||||
raise HomeAssistantError(
|
||||
"Service call requested response data but matched more than one entity"
|
||||
)
|
||||
|
@ -874,9 +890,8 @@ async def entity_service_call( # noqa: C901
|
|||
)
|
||||
assert not pending
|
||||
|
||||
response_data: ServiceResponse | None
|
||||
for task in done:
|
||||
response_data = task.result() # pop exception if have
|
||||
task.result() # pop exception if have
|
||||
|
||||
tasks: list[asyncio.Task[None]] = []
|
||||
|
||||
|
@ -895,7 +910,7 @@ async def entity_service_call( # noqa: C901
|
|||
for future in done:
|
||||
future.result() # pop exception if have
|
||||
|
||||
return response_data if call.return_response else None
|
||||
return None
|
||||
|
||||
|
||||
async def _handle_entity_call(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue