Defer bluetooth scanner watchdog restart if one is already in progress (#80679)

This commit is contained in:
J. Nick Koston 2022-10-20 13:56:20 -05:00 committed by GitHub
parent 5589edd814
commit 03362bec1c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 72 additions and 0 deletions

View File

@ -347,6 +347,12 @@ class HaScanner(BaseHaScanner):
) )
if time_since_last_detection < SCANNER_WATCHDOG_TIMEOUT: if time_since_last_detection < SCANNER_WATCHDOG_TIMEOUT:
return return
if self._start_stop_lock.locked():
_LOGGER.debug(
"%s: Scanner is already restarting, deferring restart",
self.name,
)
return
_LOGGER.info( _LOGGER.info(
"%s: Bluetooth scanner has gone quiet for %ss, restarting", "%s: Bluetooth scanner has gone quiet for %ss, restarting",
self.name, self.name,

View File

@ -1,4 +1,5 @@
"""Tests for the Bluetooth integration scanners.""" """Tests for the Bluetooth integration scanners."""
import asyncio
from datetime import timedelta from datetime import timedelta
import time import time
from unittest.mock import MagicMock, patch from unittest.mock import MagicMock, patch
@ -487,3 +488,68 @@ async def test_adapter_fails_to_start_and_takes_a_bit_to_init(
assert len(mock_recover_adapter.mock_calls) == 1 assert len(mock_recover_adapter.mock_calls) == 1
assert "Waiting for adapter to initialize" in caplog.text assert "Waiting for adapter to initialize" in caplog.text
async def test_restart_takes_longer_than_watchdog_time(hass, one_adapter, caplog):
"""Test we do not try to recover the adapter again if the restart is still in progress."""
release_start_event = asyncio.Event()
called_start = 0
class MockBleakScanner:
async def start(self, *args, **kwargs):
"""Mock Start."""
nonlocal called_start
called_start += 1
if called_start == 1:
return
await release_start_event.wait()
async def stop(self, *args, **kwargs):
"""Mock Start."""
@property
def discovered_devices(self):
"""Mock discovered_devices."""
return []
def register_detection_callback(self, callback: AdvertisementDataCallback):
"""Mock Register Detection Callback."""
scanner = MockBleakScanner()
start_time_monotonic = time.monotonic()
with patch(
"homeassistant.components.bluetooth.scanner.ADAPTER_INIT_TIME",
0,
), patch(
"homeassistant.components.bluetooth.scanner.MONOTONIC_TIME",
return_value=start_time_monotonic,
), patch(
"homeassistant.components.bluetooth.scanner.OriginalBleakScanner",
return_value=scanner,
), patch(
"homeassistant.components.bluetooth.util.recover_adapter", return_value=True
):
await async_setup_with_one_adapter(hass)
assert called_start == 1
# Now force a recover adapter 2x
for _ in range(2):
with patch(
"homeassistant.components.bluetooth.scanner.MONOTONIC_TIME",
return_value=start_time_monotonic
+ SCANNER_WATCHDOG_TIMEOUT
+ SCANNER_WATCHDOG_INTERVAL.total_seconds(),
):
async_fire_time_changed(
hass, dt_util.utcnow() + SCANNER_WATCHDOG_INTERVAL
)
await asyncio.sleep(0)
# Now release the start event
release_start_event.set()
await hass.async_block_till_done()
assert "already restarting" in caplog.text