Skip to content

Commit f4d297a

Browse files
committed
Speed up stopping the reconnect logic if we are at a safe place to cancel
If the connection has not established yet, we can cancel the connection process when the reconnect logic is stopped instead of waiting for the connection to fail. If we have already finished connecting and started the handshake, we wait for it to complete so we can try to disconnect cleanly
1 parent e9755bd commit f4d297a

File tree

2 files changed

+37
-0
lines changed

2 files changed

+37
-0
lines changed

aioesphomeapi/reconnect_logic.py

+7
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,13 @@ async def start(self) -> None:
317317
async def stop(self) -> None:
318318
"""Stop the connecting logic background task. Does not disconnect the client."""
319319
self._cancel_connect("Stopping")
320+
if self._connect_task and self._connection_state == ReconnectLogicState.CONNECTING:
321+
# If we are still establishing a connection, we can safely
322+
# cancel the connect task here, otherwise we need to wait
323+
# for the connect task to finish so we can gracefully
324+
# disconnect.
325+
self._connect_task.cancel("Stopping")
326+
320327
async with self._connected_lock:
321328
self._is_stopped = True
322329
# Cancel again while holding the lock

tests/test_reconnect_logic.py

+30
Original file line numberDiff line numberDiff line change
@@ -371,3 +371,33 @@ async def quick_connect_fail(*args, **kwargs):
371371
assert log_text in caplog.text
372372

373373
await rl.stop()
374+
assert rl._is_stopped is True
375+
assert rl._connection_state is ReconnectLogicState.DISCONNECTED
376+
377+
378+
@pytest.mark.asyncio
379+
async def test_reconnect_logic_stop_callback():
380+
"""Test that the stop_callback stops the ReconnectLogic."""
381+
cli = APIClient(
382+
address="1.2.3.4",
383+
port=6052,
384+
password=None,
385+
)
386+
rl = ReconnectLogic(
387+
client=cli,
388+
on_disconnect=AsyncMock(),
389+
on_connect=AsyncMock(),
390+
zeroconf_instance=_get_mock_zeroconf(),
391+
name="mydevice",
392+
)
393+
await rl.start()
394+
assert rl._connection_state is ReconnectLogicState.DISCONNECTED
395+
await asyncio.sleep(0)
396+
assert rl._connection_state is ReconnectLogicState.CONNECTING
397+
assert rl._is_stopped is False
398+
rl.stop_callback()
399+
# Wait for cancellation to propagate
400+
for _ in range(4):
401+
await asyncio.sleep(0)
402+
assert rl._is_stopped is True
403+
assert rl._connection_state is ReconnectLogicState.DISCONNECTED

0 commit comments

Comments
 (0)