mirror of
https://github.com/home-assistant/core.git
synced 2025-07-14 16:57:10 +00:00
Add retry to api calls in Nord Pool (#132768)
This commit is contained in:
parent
dba405dd88
commit
f99239538c
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import asyncio
|
||||||
from collections.abc import Callable
|
from collections.abc import Callable
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
@ -69,23 +70,30 @@ class NordPoolDataUpdateCoordinator(DataUpdateCoordinator[DeliveryPeriodData]):
|
|||||||
self.unsub = async_track_point_in_utc_time(
|
self.unsub = async_track_point_in_utc_time(
|
||||||
self.hass, self.fetch_data, self.get_next_interval(dt_util.utcnow())
|
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:
|
try:
|
||||||
data = await self.client.async_get_delivery_period(
|
data = await self.client.async_get_delivery_period(
|
||||||
dt_util.now(),
|
dt_util.now(),
|
||||||
Currency(self.config_entry.data[CONF_CURRENCY]),
|
Currency(self.config_entry.data[CONF_CURRENCY]),
|
||||||
self.config_entry.data[CONF_AREAS],
|
self.config_entry.data[CONF_AREAS],
|
||||||
)
|
)
|
||||||
except NordPoolEmptyResponseError as error:
|
except (
|
||||||
LOGGER.debug("Empty response error: %s", error)
|
NordPoolEmptyResponseError,
|
||||||
self.async_set_update_error(error)
|
NordPoolResponseError,
|
||||||
return
|
NordPoolError,
|
||||||
except NordPoolResponseError as error:
|
) as error:
|
||||||
LOGGER.debug("Response error: %s", error)
|
|
||||||
self.async_set_update_error(error)
|
|
||||||
return
|
|
||||||
except NordPoolError as error:
|
|
||||||
LOGGER.debug("Connection error: %s", 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)
|
self.async_set_update_error(error)
|
||||||
return
|
|
||||||
|
|
||||||
self.async_set_updated_data(data)
|
return data
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from collections.abc import AsyncGenerator
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import json
|
import json
|
||||||
from typing import Any
|
from typing import Any
|
||||||
@ -23,6 +24,13 @@ from tests.common import MockConfigEntry, load_fixture
|
|||||||
from tests.test_util.aiohttp import AiohttpClientMocker
|
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
|
@pytest.fixture
|
||||||
async def load_int(
|
async def load_int(
|
||||||
hass: HomeAssistant, get_data: DeliveryPeriodData
|
hass: HomeAssistant, get_data: DeliveryPeriodData
|
||||||
|
@ -58,7 +58,7 @@ async def test_coordinator(
|
|||||||
freezer.tick(timedelta(hours=1))
|
freezer.tick(timedelta(hours=1))
|
||||||
async_fire_time_changed(hass)
|
async_fire_time_changed(hass)
|
||||||
await hass.async_block_till_done(wait_background_tasks=True)
|
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")
|
state = hass.states.get("sensor.nord_pool_se3_current_price")
|
||||||
assert state.state == STATE_UNAVAILABLE
|
assert state.state == STATE_UNAVAILABLE
|
||||||
mock_data.reset_mock()
|
mock_data.reset_mock()
|
||||||
@ -68,7 +68,7 @@ async def test_coordinator(
|
|||||||
freezer.tick(timedelta(hours=1))
|
freezer.tick(timedelta(hours=1))
|
||||||
async_fire_time_changed(hass)
|
async_fire_time_changed(hass)
|
||||||
await hass.async_block_till_done(wait_background_tasks=True)
|
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")
|
state = hass.states.get("sensor.nord_pool_se3_current_price")
|
||||||
assert state.state == STATE_UNAVAILABLE
|
assert state.state == STATE_UNAVAILABLE
|
||||||
assert "Authentication error" in caplog.text
|
assert "Authentication error" in caplog.text
|
||||||
@ -79,7 +79,7 @@ async def test_coordinator(
|
|||||||
freezer.tick(timedelta(hours=1))
|
freezer.tick(timedelta(hours=1))
|
||||||
async_fire_time_changed(hass)
|
async_fire_time_changed(hass)
|
||||||
await hass.async_block_till_done(wait_background_tasks=True)
|
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")
|
state = hass.states.get("sensor.nord_pool_se3_current_price")
|
||||||
assert state.state == STATE_UNAVAILABLE
|
assert state.state == STATE_UNAVAILABLE
|
||||||
assert "Empty response" in caplog.text
|
assert "Empty response" in caplog.text
|
||||||
@ -90,7 +90,7 @@ async def test_coordinator(
|
|||||||
freezer.tick(timedelta(hours=1))
|
freezer.tick(timedelta(hours=1))
|
||||||
async_fire_time_changed(hass)
|
async_fire_time_changed(hass)
|
||||||
await hass.async_block_till_done(wait_background_tasks=True)
|
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")
|
state = hass.states.get("sensor.nord_pool_se3_current_price")
|
||||||
assert state.state == STATE_UNAVAILABLE
|
assert state.state == STATE_UNAVAILABLE
|
||||||
assert "Response error" in caplog.text
|
assert "Response error" in caplog.text
|
||||||
|
Loading…
x
Reference in New Issue
Block a user