Bound Tesla Fleet vehicle first refresh with a timeout (#181606)

This commit is contained in:
Brett Adams
2026-09-08 12:11:09 +02:00
committed by GitHub
parent 3188580baf
commit 08ccec7d68
3 changed files with 37 additions and 1 deletions
@@ -1,5 +1,6 @@
"""Tesla Fleet integration."""
import asyncio
from typing import Final
import jwt
@@ -34,6 +35,7 @@ from homeassistant.helpers.device_registry import DeviceInfo
from .const import DOMAIN, LOGGER
from .coordinator import (
VEHICLE_FIRST_REFRESH_TIMEOUT,
TeslaFleetEnergySiteHistoryCoordinator,
TeslaFleetEnergySiteInfoCoordinator,
TeslaFleetEnergySiteLiveCoordinator,
@@ -159,7 +161,15 @@ async def async_setup_entry(hass: HomeAssistant, entry: TeslaFleetConfigEntry) -
hass, entry, api_vehicle, product, Scope.VEHICLE_LOCATION in scopes
)
await coordinator.async_config_entry_first_refresh()
# A sleeping vehicle can take minutes to answer vehicle_data; bound the
# first refresh so setup retries instead of stalling HA's bootstrap.
try:
async with asyncio.timeout(VEHICLE_FIRST_REFRESH_TIMEOUT):
await coordinator.async_config_entry_first_refresh()
except TimeoutError as err:
raise ConfigEntryNotReady(
f"Timed out waiting for vehicle {vin} to respond"
) from err
device = DeviceInfo(
identifiers={(DOMAIN, vin)},
@@ -36,6 +36,11 @@ VEHICLE_WAIT_SECONDS = 900
VEHICLE_WAIT = timedelta(seconds=VEHICLE_WAIT_SECONDS)
VEHICLE_STUCK_SECONDS = 1200
# Kept well under Home Assistant's stage-2 setup budget (SLOW_SETUP_MAX_WAIT, 300s)
# so a sleeping vehicle raises ConfigEntryNotReady and the entry retries instead of
# being cancelled into a non-retried setup error.
VEHICLE_FIRST_REFRESH_TIMEOUT = 60
ENERGY_INTERVAL_SECONDS = 60
ENERGY_INTERVAL = timedelta(seconds=ENERGY_INTERVAL_SECONDS)
ENERGY_HISTORY_INTERVAL = timedelta(minutes=5)
+21
View File
@@ -1,5 +1,6 @@
"""Test the Tesla Fleet init."""
import asyncio
from copy import deepcopy
from datetime import timedelta
from unittest.mock import AsyncMock, Mock, PropertyMock, patch
@@ -96,6 +97,26 @@ async def test_init_error(
assert normal_config_entry.state is state
async def test_vehicle_first_refresh_timeout(
hass: HomeAssistant,
normal_config_entry: MockConfigEntry,
mock_vehicle_data: AsyncMock,
) -> None:
"""Test a slow first vehicle refresh retries instead of blocking setup."""
never = asyncio.Event()
async def _hang(*args: object, **kwargs: object) -> None:
await never.wait()
mock_vehicle_data.side_effect = _hang
with patch("homeassistant.components.tesla_fleet.VEHICLE_FIRST_REFRESH_TIMEOUT", 0):
await setup_platform(hass, normal_config_entry)
assert normal_config_entry.state is ConfigEntryState.SETUP_RETRY
never.set()
async def test_oauth_refresh_expired(
hass: HomeAssistant,
normal_config_entry: MockConfigEntry,