Reduce creation of MQTT related discovery tasks (#90801)

* Reduce creation of MQTT related discovery tasks

Most of the branching can avoid creating a task as it
did not need to await for the majority of cases. We
fallback to creating a task for the cases were we do
need to await.

* comment

* revert
This commit is contained in:
J. Nick Koston 2023-04-08 17:14:22 -10:00 committed by GitHub
parent d442f2aedb
commit 66b105fb21
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 43 additions and 10 deletions

View File

@ -218,7 +218,8 @@ async def async_start( # noqa: C901
discovery_hash = (component, discovery_id)
if discovery_hash in mqtt_data.discovery_already_discovered or payload:
async def discovery_done(_: Any) -> None:
@callback
def discovery_done(_: Any) -> None:
pending = mqtt_data.discovery_pending_discovered[discovery_hash][
"pending"
]

View File

@ -832,8 +832,37 @@ class MqttDiscoveryUpdate(Entity):
else:
await self.async_remove(force_remove=True)
async def discovery_callback(payload: MQTTDiscoveryPayload) -> None:
"""Handle discovery update."""
async def _async_process_discovery_update(
payload: MQTTDiscoveryPayload,
discovery_update: Callable[
[MQTTDiscoveryPayload], Coroutine[Any, Any, None]
],
discovery_data: DiscoveryInfoType,
) -> None:
"""Process discovery update."""
try:
await discovery_update(payload)
finally:
send_discovery_done(self.hass, discovery_data)
async def _async_process_discovery_update_and_remove(
payload: MQTTDiscoveryPayload, discovery_data: DiscoveryInfoType
) -> None:
"""Process discovery update and remove entity."""
self._cleanup_discovery_on_remove()
await _async_remove_state_and_registry_entry(self)
send_discovery_done(self.hass, discovery_data)
@callback
def discovery_callback(payload: MQTTDiscoveryPayload) -> None:
"""Handle discovery update.
If the payload has changed we will create a task to
do the discovery update.
As this callback can fire when nothing has changed, this
is a normal function to avoid task creation until it is needed.
"""
_LOGGER.debug(
"Got update for entity with hash: %s '%s'",
discovery_hash,
@ -846,17 +875,20 @@ class MqttDiscoveryUpdate(Entity):
if not payload:
# Empty payload: Remove component
_LOGGER.info("Removing component: %s", self.entity_id)
self._cleanup_discovery_on_remove()
await _async_remove_state_and_registry_entry(self)
send_discovery_done(self.hass, self._discovery_data)
self.hass.async_create_task(
_async_process_discovery_update_and_remove(
payload, self._discovery_data
)
)
elif self._discovery_update:
if old_payload != self._discovery_data[ATTR_DISCOVERY_PAYLOAD]:
# Non-empty, changed payload: Notify component
_LOGGER.info("Updating component: %s", self.entity_id)
try:
await self._discovery_update(payload)
finally:
send_discovery_done(self.hass, self._discovery_data)
self.hass.async_create_task(
_async_process_discovery_update(
payload, self._discovery_update, self._discovery_data
)
)
else:
# Non-empty, unchanged payload: Ignore to avoid changing states
_LOGGER.debug("Ignoring unchanged update for: %s", self.entity_id)