fix(amberelectric): add request timeouts (#150613)

Signed-off-by: JP-Ellis <josh@jpellis.me>
This commit is contained in:
JP-Ellis
2025-08-20 15:59:33 +10:00
committed by GitHub
parent 0b231ff042
commit 19b2c6da23
4 changed files with 32 additions and 10 deletions

View File

@@ -16,7 +16,7 @@ from homeassistant.helpers.selector import (
SelectSelectorMode, SelectSelectorMode,
) )
from .const import CONF_SITE_ID, CONF_SITE_NAME, DOMAIN from .const import CONF_SITE_ID, CONF_SITE_NAME, DOMAIN, REQUEST_TIMEOUT
API_URL = "https://app.amber.com.au/developers" API_URL = "https://app.amber.com.au/developers"
@@ -64,7 +64,9 @@ class AmberElectricConfigFlow(ConfigFlow, domain=DOMAIN):
api = amberelectric.AmberApi(api_client) api = amberelectric.AmberApi(api_client)
try: try:
sites: list[Site] = filter_sites(api.get_sites()) sites: list[Site] = filter_sites(
api.get_sites(_request_timeout=REQUEST_TIMEOUT)
)
except amberelectric.ApiException as api_exception: except amberelectric.ApiException as api_exception:
if api_exception.status == 403: if api_exception.status == 403:
self._errors[CONF_API_TOKEN] = "invalid_api_token" self._errors[CONF_API_TOKEN] = "invalid_api_token"

View File

@@ -21,3 +21,5 @@ SERVICE_GET_FORECASTS = "get_forecasts"
GENERAL_CHANNEL = "general" GENERAL_CHANNEL = "general"
CONTROLLED_LOAD_CHANNEL = "controlled_load" CONTROLLED_LOAD_CHANNEL = "controlled_load"
FEED_IN_CHANNEL = "feed_in" FEED_IN_CHANNEL = "feed_in"
REQUEST_TIMEOUT = 15

View File

@@ -16,7 +16,7 @@ from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
from .const import LOGGER from .const import LOGGER, REQUEST_TIMEOUT
from .helpers import normalize_descriptor from .helpers import normalize_descriptor
type AmberConfigEntry = ConfigEntry[AmberUpdateCoordinator] type AmberConfigEntry = ConfigEntry[AmberUpdateCoordinator]
@@ -82,7 +82,11 @@ class AmberUpdateCoordinator(DataUpdateCoordinator):
"grid": {}, "grid": {},
} }
try: try:
data = self._api.get_current_prices(self.site_id, next=288) data = self._api.get_current_prices(
self.site_id,
next=288,
_request_timeout=REQUEST_TIMEOUT,
)
intervals = [interval.actual_instance for interval in data] intervals = [interval.actual_instance for interval in data]
except ApiException as api_exception: except ApiException as api_exception:
raise UpdateFailed("Missing price data, skipping update") from api_exception raise UpdateFailed("Missing price data, skipping update") from api_exception

View File

@@ -15,7 +15,11 @@ from amberelectric.models.spike_status import SpikeStatus
from dateutil import parser from dateutil import parser
import pytest import pytest
from homeassistant.components.amberelectric.const import CONF_SITE_ID, CONF_SITE_NAME from homeassistant.components.amberelectric.const import (
CONF_SITE_ID,
CONF_SITE_NAME,
REQUEST_TIMEOUT,
)
from homeassistant.components.amberelectric.coordinator import AmberUpdateCoordinator from homeassistant.components.amberelectric.coordinator import AmberUpdateCoordinator
from homeassistant.const import CONF_API_TOKEN from homeassistant.const import CONF_API_TOKEN
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
@@ -104,7 +108,9 @@ async def test_fetch_general_site(hass: HomeAssistant, current_price_api: Mock)
result = await data_service._async_update_data() result = await data_service._async_update_data()
current_price_api.get_current_prices.assert_called_with( current_price_api.get_current_prices.assert_called_with(
GENERAL_ONLY_SITE_ID, next=288 GENERAL_ONLY_SITE_ID,
next=288,
_request_timeout=REQUEST_TIMEOUT,
) )
assert result["current"].get("general") == GENERAL_CHANNEL[0].actual_instance assert result["current"].get("general") == GENERAL_CHANNEL[0].actual_instance
@@ -136,7 +142,9 @@ async def test_fetch_no_general_site(
await data_service._async_update_data() await data_service._async_update_data()
current_price_api.get_current_prices.assert_called_with( current_price_api.get_current_prices.assert_called_with(
GENERAL_ONLY_SITE_ID, next=288 GENERAL_ONLY_SITE_ID,
next=288,
_request_timeout=REQUEST_TIMEOUT,
) )
@@ -150,7 +158,9 @@ async def test_fetch_api_error(hass: HomeAssistant, current_price_api: Mock) ->
result = await data_service._async_update_data() result = await data_service._async_update_data()
current_price_api.get_current_prices.assert_called_with( current_price_api.get_current_prices.assert_called_with(
GENERAL_ONLY_SITE_ID, next=288 GENERAL_ONLY_SITE_ID,
next=288,
_request_timeout=REQUEST_TIMEOUT,
) )
assert result["current"].get("general") == GENERAL_CHANNEL[0].actual_instance assert result["current"].get("general") == GENERAL_CHANNEL[0].actual_instance
@@ -201,7 +211,9 @@ async def test_fetch_general_and_controlled_load_site(
result = await data_service._async_update_data() result = await data_service._async_update_data()
current_price_api.get_current_prices.assert_called_with( current_price_api.get_current_prices.assert_called_with(
GENERAL_AND_CONTROLLED_SITE_ID, next=288 GENERAL_AND_CONTROLLED_SITE_ID,
next=288,
_request_timeout=REQUEST_TIMEOUT,
) )
assert result["current"].get("general") == GENERAL_CHANNEL[0].actual_instance assert result["current"].get("general") == GENERAL_CHANNEL[0].actual_instance
@@ -241,7 +253,9 @@ async def test_fetch_general_and_feed_in_site(
result = await data_service._async_update_data() result = await data_service._async_update_data()
current_price_api.get_current_prices.assert_called_with( current_price_api.get_current_prices.assert_called_with(
GENERAL_AND_FEED_IN_SITE_ID, next=288 GENERAL_AND_FEED_IN_SITE_ID,
next=288,
_request_timeout=REQUEST_TIMEOUT,
) )
assert result["current"].get("general") == GENERAL_CHANNEL[0].actual_instance assert result["current"].get("general") == GENERAL_CHANNEL[0].actual_instance