Add retry to api calls in Nord Pool (#132768)
parent
dba405dd88
commit
f99239538c
|
@ -2,6 +2,7 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from collections.abc import Callable
|
||||
from datetime import datetime, timedelta
|
||||
from typing import TYPE_CHECKING
|
||||
|
@ -69,23 +70,30 @@ class NordPoolDataUpdateCoordinator(DataUpdateCoordinator[DeliveryPeriodData]):
|
|||
self.unsub = async_track_point_in_utc_time(
|
||||
self.hass, self.fetch_data, self.get_next_interval(dt_util.utcnow())
|
||||
)
|
||||
data = await self.api_call()
|
||||
if data:
|
||||
self.async_set_updated_data(data)
|
||||
|
||||
async def api_call(self, retry: int = 3) -> DeliveryPeriodData | None:
|
||||
"""Make api call to retrieve data with retry if failure."""
|
||||
data = None
|
||||
try:
|
||||
data = await self.client.async_get_delivery_period(
|
||||
dt_util.now(),
|
||||
Currency(self.config_entry.data[CONF_CURRENCY]),
|
||||
self.config_entry.data[CONF_AREAS],
|
||||
)
|
||||
except NordPoolEmptyResponseError as error:
|
||||
LOGGER.debug("Empty response error: %s", error)
|
||||
self.async_set_update_error(error)
|
||||
return
|
||||
except NordPoolResponseError as error:
|
||||
LOGGER.debug("Response error: %s", error)
|
||||
self.async_set_update_error(error)
|
||||
return
|
||||
except NordPoolError as error:
|
||||
except (
|
||||
NordPoolEmptyResponseError,
|
||||
NordPoolResponseError,
|
||||
NordPoolError,
|
||||
) as error:
|
||||
LOGGER.debug("Connection error: %s", error)
|
||||
if retry > 0:
|
||||
next_run = (4 - retry) * 15
|
||||
LOGGER.debug("Wait %d seconds for next try", next_run)
|
||||
await asyncio.sleep(next_run)
|
||||
return await self.api_call(retry - 1)
|
||||
self.async_set_update_error(error)
|
||||
return
|
||||
|
||||
self.async_set_updated_data(data)
|
||||
return data
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import AsyncGenerator
|
||||
from datetime import datetime
|
||||
import json
|
||||
from typing import Any
|
||||
|
@ -23,6 +24,13 @@ from tests.common import MockConfigEntry, load_fixture
|
|||
from tests.test_util.aiohttp import AiohttpClientMocker
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
async def no_sleep() -> AsyncGenerator[None]:
|
||||
"""No sleeping."""
|
||||
with patch("homeassistant.components.nordpool.coordinator.asyncio.sleep"):
|
||||
yield
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def load_int(
|
||||
hass: HomeAssistant, get_data: DeliveryPeriodData
|
||||
|
|
|
@ -58,7 +58,7 @@ async def test_coordinator(
|
|||
freezer.tick(timedelta(hours=1))
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
mock_data.assert_called_once()
|
||||
assert mock_data.call_count == 4
|
||||
state = hass.states.get("sensor.nord_pool_se3_current_price")
|
||||
assert state.state == STATE_UNAVAILABLE
|
||||
mock_data.reset_mock()
|
||||
|
@ -68,7 +68,7 @@ async def test_coordinator(
|
|||
freezer.tick(timedelta(hours=1))
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
mock_data.assert_called_once()
|
||||
assert mock_data.call_count == 4
|
||||
state = hass.states.get("sensor.nord_pool_se3_current_price")
|
||||
assert state.state == STATE_UNAVAILABLE
|
||||
assert "Authentication error" in caplog.text
|
||||
|
@ -79,7 +79,7 @@ async def test_coordinator(
|
|||
freezer.tick(timedelta(hours=1))
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
mock_data.assert_called_once()
|
||||
assert mock_data.call_count == 4
|
||||
state = hass.states.get("sensor.nord_pool_se3_current_price")
|
||||
assert state.state == STATE_UNAVAILABLE
|
||||
assert "Empty response" in caplog.text
|
||||
|
@ -90,7 +90,7 @@ async def test_coordinator(
|
|||
freezer.tick(timedelta(hours=1))
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
mock_data.assert_called_once()
|
||||
assert mock_data.call_count == 4
|
||||
state = hass.states.get("sensor.nord_pool_se3_current_price")
|
||||
assert state.state == STATE_UNAVAILABLE
|
||||
assert "Response error" in caplog.text
|
||||
|
|
Loading…
Reference in New Issue