From d939c48b4aa292dd66a1369cae0bec9044e08887 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 11 Mar 2024 04:11:33 -1000 Subject: [PATCH] Fix here_travel_time creating many refresh requests at startup (#113041) --- .../components/here_travel_time/__init__.py | 26 ++++++------- .../components/here_travel_time/sensor.py | 6 --- .../here_travel_time/test_sensor.py | 37 +++++++++++-------- 3 files changed, 34 insertions(+), 35 deletions(-) diff --git a/homeassistant/components/here_travel_time/__init__.py b/homeassistant/components/here_travel_time/__init__.py index 19ba1f8ebaf..9da1ce491f0 100644 --- a/homeassistant/components/here_travel_time/__init__.py +++ b/homeassistant/components/here_travel_time/__init__.py @@ -5,6 +5,7 @@ from __future__ import annotations from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_API_KEY, CONF_MODE, Platform from homeassistant.core import HomeAssistant +from homeassistant.helpers.start import async_at_started from homeassistant.util import dt as dt_util from .const import ( @@ -49,22 +50,19 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b departure=departure, ) + cls: type[HERETransitDataUpdateCoordinator] | type[HERERoutingDataUpdateCoordinator] if config_entry.data[CONF_MODE] in {TRAVEL_MODE_PUBLIC, "publicTransportTimeTable"}: - hass.data.setdefault(DOMAIN, {})[ - config_entry.entry_id - ] = HERETransitDataUpdateCoordinator( - hass, - api_key, - here_travel_time_config, - ) + cls = HERETransitDataUpdateCoordinator else: - hass.data.setdefault(DOMAIN, {})[ - config_entry.entry_id - ] = HERERoutingDataUpdateCoordinator( - hass, - api_key, - here_travel_time_config, - ) + cls = HERERoutingDataUpdateCoordinator + + data_coordinator = cls(hass, api_key, here_travel_time_config) + hass.data.setdefault(DOMAIN, {})[config_entry.entry_id] = data_coordinator + + async def _async_update_at_start(_: HomeAssistant) -> None: + await data_coordinator.async_refresh() + + config_entry.async_on_unload(async_at_started(hass, _async_update_at_start)) await hass.config_entries.async_forward_entry_setups(config_entry, PLATFORMS) return True diff --git a/homeassistant/components/here_travel_time/sensor.py b/homeassistant/components/here_travel_time/sensor.py index 1fd4f8d94bc..190a8455e83 100644 --- a/homeassistant/components/here_travel_time/sensor.py +++ b/homeassistant/components/here_travel_time/sensor.py @@ -25,7 +25,6 @@ from homeassistant.const import ( from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo from homeassistant.helpers.entity_platform import AddEntitiesCallback -from homeassistant.helpers.start import async_at_started from homeassistant.helpers.update_coordinator import CoordinatorEntity from .const import ( @@ -141,11 +140,6 @@ class HERETravelTimeSensor( await self._async_restore_state() await super().async_added_to_hass() - async def _update_at_start(_: HomeAssistant) -> None: - await self.async_update() - - self.async_on_remove(async_at_started(self.hass, _update_at_start)) - @callback def _handle_coordinator_update(self) -> None: """Handle updated data from the coordinator.""" diff --git a/tests/components/here_travel_time/test_sensor.py b/tests/components/here_travel_time/test_sensor.py index 6c5cd776ff2..0231ac6428f 100644 --- a/tests/components/here_travel_time/test_sensor.py +++ b/tests/components/here_travel_time/test_sensor.py @@ -60,7 +60,7 @@ from homeassistant.const import ( CONF_API_KEY, CONF_MODE, CONF_NAME, - EVENT_HOMEASSISTANT_START, + EVENT_HOMEASSISTANT_STARTED, UnitOfLength, UnitOfTime, ) @@ -122,6 +122,7 @@ async def test_sensor( departure_time, ) -> None: """Test that sensor works.""" + hass.set_state(CoreState.not_running) entry = MockConfigEntry( domain=DOMAIN, unique_id="0123456789", @@ -143,7 +144,7 @@ async def test_sensor( entry.add_to_hass(hass) await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() - hass.bus.async_fire(EVENT_HOMEASSISTANT_START) + hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED) await hass.async_block_till_done() duration = hass.states.get("sensor.test_duration") @@ -201,7 +202,7 @@ async def test_circular_ref( await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() - hass.bus.async_fire(EVENT_HOMEASSISTANT_START) + hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED) await hass.async_block_till_done() assert "No coordinates found for test.first" in caplog.text @@ -210,6 +211,7 @@ async def test_circular_ref( @pytest.mark.usefixtures("valid_response") async def test_public_transport(hass: HomeAssistant) -> None: """Test that public transport mode is handled.""" + hass.set_state(CoreState.not_running) entry = MockConfigEntry( domain=DOMAIN, unique_id="0123456789", @@ -232,7 +234,7 @@ async def test_public_transport(hass: HomeAssistant) -> None: await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() - hass.bus.async_fire(EVENT_HOMEASSISTANT_START) + hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED) await hass.async_block_till_done() assert ( @@ -263,7 +265,7 @@ async def test_no_attribution_response(hass: HomeAssistant) -> None: await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() - hass.bus.async_fire(EVENT_HOMEASSISTANT_START) + hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED) await hass.async_block_till_done() assert ( @@ -273,6 +275,7 @@ async def test_no_attribution_response(hass: HomeAssistant) -> None: async def test_entity_ids(hass: HomeAssistant, valid_response: MagicMock) -> None: """Test that origin/destination supplied by entities works.""" + hass.set_state(CoreState.not_running) zone_config = { "zone": [ { @@ -309,7 +312,7 @@ async def test_entity_ids(hass: HomeAssistant, valid_response: MagicMock) -> Non await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() - hass.bus.async_fire(EVENT_HOMEASSISTANT_START) + hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED) await hass.async_block_till_done() assert hass.states.get("sensor.test_distance").state == "13.682" @@ -348,7 +351,7 @@ async def test_destination_entity_not_found( await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() - hass.bus.async_fire(EVENT_HOMEASSISTANT_START) + hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED) await hass.async_block_till_done() assert "Could not find entity device_tracker.test" in caplog.text @@ -376,7 +379,7 @@ async def test_origin_entity_not_found( await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() - hass.bus.async_fire(EVENT_HOMEASSISTANT_START) + hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED) await hass.async_block_till_done() assert "Could not find entity device_tracker.test" in caplog.text @@ -408,7 +411,7 @@ async def test_invalid_destination_entity_state( await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() - hass.bus.async_fire(EVENT_HOMEASSISTANT_START) + hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED) await hass.async_block_till_done() assert ( @@ -442,7 +445,7 @@ async def test_invalid_origin_entity_state( await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() - hass.bus.async_fire(EVENT_HOMEASSISTANT_START) + hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED) await hass.async_block_till_done() assert ( @@ -477,7 +480,7 @@ async def test_route_not_found( entry.add_to_hass(hass) await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() - hass.bus.async_fire(EVENT_HOMEASSISTANT_START) + hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED) await hass.async_block_till_done() assert "Route calculation failed: Couldn't find a route." in caplog.text @@ -635,6 +638,7 @@ async def test_transit_errors( hass: HomeAssistant, caplog: pytest.LogCaptureFixture, exception, expected_message ) -> None: """Test that transit errors are correctly handled.""" + hass.set_state(CoreState.not_running) with patch( "here_transit.HERETransitApi.route", side_effect=exception(), @@ -656,7 +660,7 @@ async def test_transit_errors( entry.add_to_hass(hass) await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() - hass.bus.async_fire(EVENT_HOMEASSISTANT_START) + hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED) await hass.async_block_till_done() assert expected_message in caplog.text @@ -668,6 +672,7 @@ async def test_routing_rate_limit( freezer: FrozenDateTimeFactory, ) -> None: """Test that rate limiting is applied when encountering HTTP 429.""" + hass.set_state(CoreState.not_running) with patch( "here_routing.HERERoutingApi.route", return_value=RESPONSE, @@ -681,7 +686,7 @@ async def test_routing_rate_limit( entry.add_to_hass(hass) await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() - hass.bus.async_fire(EVENT_HOMEASSISTANT_START) + hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED) await hass.async_block_till_done() assert hass.states.get("sensor.test_distance").state == "13.682" @@ -716,6 +721,7 @@ async def test_transit_rate_limit( freezer: FrozenDateTimeFactory, ) -> None: """Test that rate limiting is applied when encountering HTTP 429.""" + hass.set_state(CoreState.not_running) with patch( "here_transit.HERETransitApi.route", return_value=TRANSIT_RESPONSE, @@ -737,7 +743,7 @@ async def test_transit_rate_limit( entry.add_to_hass(hass) await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() - hass.bus.async_fire(EVENT_HOMEASSISTANT_START) + hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED) await hass.async_block_till_done() assert hass.states.get("sensor.test_distance").state == "1.883" @@ -771,6 +777,7 @@ async def test_multiple_sections( hass: HomeAssistant, ) -> None: """Test that multiple sections are handled correctly.""" + hass.set_state(CoreState.not_running) entry = MockConfigEntry( domain=DOMAIN, unique_id="0123456789", @@ -788,7 +795,7 @@ async def test_multiple_sections( entry.add_to_hass(hass) await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() - hass.bus.async_fire(EVENT_HOMEASSISTANT_START) + hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED) await hass.async_block_till_done() duration = hass.states.get("sensor.test_duration")