From 1bc0263ea478022298692f0fb62b2f96254cd7c6 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 19 Feb 2024 13:13:49 -0600 Subject: [PATCH] Revert powerwall back to awaiting each api call (#110947) We converted these to run as tasks in the hope that it would be faster, but since the cost of establishing another connection and the task overhead exceeded the savings, it makes sense to await them all in series. --- .../components/powerwall/__init__.py | 87 ++++++++----------- 1 file changed, 34 insertions(+), 53 deletions(-) diff --git a/homeassistant/components/powerwall/__init__.py b/homeassistant/components/powerwall/__init__.py index 80a8d19cefe..086e49eef94 100644 --- a/homeassistant/components/powerwall/__init__.py +++ b/homeassistant/components/powerwall/__init__.py @@ -1,7 +1,6 @@ """The Tesla Powerwall integration.""" from __future__ import annotations -import asyncio from contextlib import AsyncExitStack from datetime import timedelta import logging @@ -221,35 +220,26 @@ async def _login_and_fetch_base_info( async def _call_base_info(power_wall: Powerwall, host: str) -> PowerwallBaseInfo: """Return PowerwallBaseInfo for the device.""" - - try: - async with asyncio.TaskGroup() as tg: - gateway_din = tg.create_task(power_wall.get_gateway_din()) - site_info = tg.create_task(power_wall.get_site_info()) - status = tg.create_task(power_wall.get_status()) - device_type = tg.create_task(power_wall.get_device_type()) - serial_numbers = tg.create_task(power_wall.get_serial_numbers()) - batteries = tg.create_task(power_wall.get_batteries()) - - # Mimic the behavior of asyncio.gather by reraising the first caught exception since - # this is what is expected by the caller of this method - # - # While it would have been cleaner to use asyncio.gather in the first place instead of - # TaskGroup but in cases where you have more than 6 tasks, the linter fails due to - # missing typing information. - except BaseExceptionGroup as e: - raise e.exceptions[0] from None - + # We await each call individually since the powerwall + # supports http keep-alive and we want to reuse the connection + # as its faster than establishing a new connection when + # run concurrently. + gateway_din = await power_wall.get_gateway_din() + site_info = await power_wall.get_site_info() + status = await power_wall.get_status() + device_type = await power_wall.get_device_type() + serial_numbers = await power_wall.get_serial_numbers() + batteries = await power_wall.get_batteries() # Serial numbers MUST be sorted to ensure the unique_id is always the same # for backwards compatibility. return PowerwallBaseInfo( - gateway_din=gateway_din.result().upper(), - site_info=site_info.result(), - status=status.result(), - device_type=device_type.result(), - serial_numbers=sorted(serial_numbers.result()), + gateway_din=gateway_din, + site_info=site_info, + status=status, + device_type=device_type, + serial_numbers=sorted(serial_numbers), url=f"https://{host}", - batteries={battery.serial_number: battery for battery in batteries.result()}, + batteries={battery.serial_number: battery for battery in batteries}, ) @@ -263,34 +253,25 @@ async def get_backup_reserve_percentage(power_wall: Powerwall) -> Optional[float async def _fetch_powerwall_data(power_wall: Powerwall) -> PowerwallData: """Process and update powerwall data.""" - - try: - async with asyncio.TaskGroup() as tg: - backup_reserve = tg.create_task(get_backup_reserve_percentage(power_wall)) - charge = tg.create_task(power_wall.get_charge()) - site_master = tg.create_task(power_wall.get_sitemaster()) - meters = tg.create_task(power_wall.get_meters()) - grid_services_active = tg.create_task(power_wall.is_grid_services_active()) - grid_status = tg.create_task(power_wall.get_grid_status()) - batteries = tg.create_task(power_wall.get_batteries()) - - # Mimic the behavior of asyncio.gather by reraising the first caught exception since - # this is what is expected by the caller of this method - # - # While it would have been cleaner to use asyncio.gather in the first place instead of - # TaskGroup but in cases where you have more than 6 tasks, the linter fails due to - # missing typing information. - except BaseExceptionGroup as e: - raise e.exceptions[0] from None - + # We await each call individually since the powerwall + # supports http keep-alive and we want to reuse the connection + # as its faster than establishing a new connection when + # run concurrently. + backup_reserve = await get_backup_reserve_percentage(power_wall) + charge = await power_wall.get_charge() + site_master = await power_wall.get_sitemaster() + meters = await power_wall.get_meters() + grid_services_active = await power_wall.is_grid_services_active() + grid_status = await power_wall.get_grid_status() + batteries = await power_wall.get_batteries() return PowerwallData( - charge=charge.result(), - site_master=site_master.result(), - meters=meters.result(), - grid_services_active=grid_services_active.result(), - grid_status=grid_status.result(), - backup_reserve=backup_reserve.result(), - batteries={battery.serial_number: battery for battery in batteries.result()}, + charge=charge, + site_master=site_master, + meters=meters, + grid_services_active=grid_services_active, + grid_status=grid_status, + backup_reserve=backup_reserve, + batteries={battery.serial_number: battery for battery in batteries}, )