Throttle connectivity check on connectivity issue (#5342)

* Throttle connectivity check on connectivity issue

If Supervisor detects a connectivity issue, currenlty every function
which requires internet get delayed by 10s due to the connectivity
check. This especially slows down initial startup when there are
connectivity issues. It is unlikely to resolve immeaditly, so throttle
the connectivity check to check every 30s.

* Fix pytest

* Reset throttle in test and refactor helper

* CodeRabbit suggestion

---------

Co-authored-by: Mike Degatano <michael.degatano@gmail.com>
This commit is contained in:
Stefan Agner
2024-10-10 22:57:16 +02:00
committed by GitHub
parent d5f33de808
commit 180a7c3990
4 changed files with 42 additions and 6 deletions

View File

@@ -1,6 +1,6 @@
"""Test supervisor object."""
from datetime import datetime
from datetime import datetime, timedelta
import errno
from unittest.mock import AsyncMock, Mock, PropertyMock, patch
@@ -8,6 +8,7 @@ from aiohttp import ClientTimeout
from aiohttp.client_exceptions import ClientError
from awesomeversion import AwesomeVersion
import pytest
from time_machine import travel
from supervisor.const import UpdateChannel
from supervisor.coresys import CoreSys
@@ -22,6 +23,8 @@ from supervisor.resolution.const import ContextType, IssueType
from supervisor.resolution.data import Issue
from supervisor.supervisor import Supervisor
from tests.common import reset_last_call
@pytest.fixture(name="websession", scope="function")
async def fixture_webession(coresys: CoreSys) -> AsyncMock:
@@ -58,21 +61,33 @@ async def test_connectivity_check(
assert supervisor_unthrottled.connectivity is connectivity
@pytest.mark.parametrize("side_effect,call_count", [(ClientError(), 3), (None, 1)])
@pytest.mark.parametrize(
"side_effect,call_interval,throttled",
[
(None, timedelta(minutes=5), True),
(None, timedelta(minutes=15), False),
(ClientError(), timedelta(seconds=20), True),
(ClientError(), timedelta(seconds=40), False),
],
)
async def test_connectivity_check_throttling(
coresys: CoreSys,
websession: AsyncMock,
side_effect: Exception | None,
call_count: int,
call_interval: timedelta,
throttled: bool,
):
"""Test connectivity check throttled when checks succeed."""
coresys.supervisor.connectivity = None
websession.head.side_effect = side_effect
for _ in range(3):
reset_last_call(Supervisor.check_connectivity)
with travel(datetime.now(), tick=False) as traveller:
await coresys.supervisor.check_connectivity()
traveller.shift(call_interval)
await coresys.supervisor.check_connectivity()
assert websession.head.call_count == call_count
assert websession.head.call_count == (1 if throttled else 2)
async def test_update_failed(coresys: CoreSys, capture_exception: Mock):