mirror of
https://github.com/esphome/aioesphomeapi.git
synced 2024-12-30 18:08:36 +01:00
Fix race scheduling reconnect from zeroconf records (#731)
This commit is contained in:
parent
c9091cbefc
commit
6e08933a75
@ -93,7 +93,7 @@ class ReconnectLogic(zeroconf.RecordUpdateListener):
|
|||||||
self._a_name: str | None = None
|
self._a_name: str | None = None
|
||||||
# Flag to check if the device is connected
|
# Flag to check if the device is connected
|
||||||
self._connection_state = ReconnectLogicState.DISCONNECTED
|
self._connection_state = ReconnectLogicState.DISCONNECTED
|
||||||
self._accept_zeroconf_records = True
|
self._accept_zeroconf_records: bool = True
|
||||||
self._connected_lock = asyncio.Lock()
|
self._connected_lock = asyncio.Lock()
|
||||||
self._is_stopped = True
|
self._is_stopped = True
|
||||||
self._zc_listening = False
|
self._zc_listening = False
|
||||||
@ -378,6 +378,11 @@ class ReconnectLogic(zeroconf.RecordUpdateListener):
|
|||||||
)
|
)
|
||||||
self._zc_listening = False
|
self._zc_listening = False
|
||||||
|
|
||||||
|
def _connect_from_zeroconf(self) -> None:
|
||||||
|
"""Connect from zeroconf."""
|
||||||
|
self._stop_zc_listen()
|
||||||
|
self._schedule_connect(0.0)
|
||||||
|
|
||||||
def async_update_records(
|
def async_update_records(
|
||||||
self,
|
self,
|
||||||
zc: zeroconf.Zeroconf, # pylint: disable=unused-argument
|
zc: zeroconf.Zeroconf, # pylint: disable=unused-argument
|
||||||
@ -411,7 +416,13 @@ class ReconnectLogic(zeroconf.RecordUpdateListener):
|
|||||||
# We can't stop the zeroconf listener here because we are in the middle of
|
# We can't stop the zeroconf listener here because we are in the middle of
|
||||||
# a zeroconf callback which is iterating the listeners.
|
# a zeroconf callback which is iterating the listeners.
|
||||||
#
|
#
|
||||||
# So we schedule a stop for the next event loop iteration.
|
# So we schedule a stop for the next event loop iteration as well as the
|
||||||
self.loop.call_soon(self._stop_zc_listen)
|
# connect attempt.
|
||||||
self._schedule_connect(0.0)
|
#
|
||||||
|
# If we scheduled the connect attempt immediately, the listener could fire
|
||||||
|
# again before the connect attempt and we cancel and reschedule the connect
|
||||||
|
# attempt again.
|
||||||
|
#
|
||||||
|
self.loop.call_soon(self._connect_from_zeroconf)
|
||||||
|
self._accept_zeroconf_records = False
|
||||||
return
|
return
|
||||||
|
@ -426,6 +426,7 @@ async def test_reconnect_zeroconf(
|
|||||||
assert rl._accept_zeroconf_records is True
|
assert rl._accept_zeroconf_records is True
|
||||||
assert not rl._is_stopped
|
assert not rl._is_stopped
|
||||||
|
|
||||||
|
caplog.clear()
|
||||||
with patch.object(cli, "start_connection") as mock_start_connection, patch.object(
|
with patch.object(cli, "start_connection") as mock_start_connection, patch.object(
|
||||||
cli, "finish_connection"
|
cli, "finish_connection"
|
||||||
):
|
):
|
||||||
@ -436,10 +437,13 @@ async def test_reconnect_zeroconf(
|
|||||||
assert (
|
assert (
|
||||||
"Triggering connect because of received mDNS record" in caplog.text
|
"Triggering connect because of received mDNS record" in caplog.text
|
||||||
) is should_trigger_zeroconf
|
) is should_trigger_zeroconf
|
||||||
|
assert rl._accept_zeroconf_records is not should_trigger_zeroconf
|
||||||
assert rl._zc_listening is True # should change after one iteration of the loop
|
assert rl._zc_listening is True # should change after one iteration of the loop
|
||||||
await asyncio.sleep(0)
|
await asyncio.sleep(0)
|
||||||
assert rl._zc_listening is not should_trigger_zeroconf
|
assert rl._zc_listening is not should_trigger_zeroconf
|
||||||
|
|
||||||
|
# The reconnect is scheduled to run in the next loop iteration
|
||||||
|
await asyncio.sleep(0)
|
||||||
assert mock_start_connection.call_count == int(should_trigger_zeroconf)
|
assert mock_start_connection.call_count == int(should_trigger_zeroconf)
|
||||||
assert log_text in caplog.text
|
assert log_text in caplog.text
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user