Skip to content

Commit ed7db1f

Browse files
authored
fix: never create a new asyncio loop (#310)
1 parent 6e04bfa commit ed7db1f

File tree

6 files changed

+18
-14
lines changed

6 files changed

+18
-14
lines changed

roborock/api.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
from .roborock_message import (
2222
RoborockMessage,
2323
)
24-
from .util import get_next_int, get_running_loop_or_create_one
24+
from .util import get_next_int
2525

2626
_LOGGER = logging.getLogger(__name__)
2727
KEEPALIVE = 60
@@ -35,7 +35,6 @@ class RoborockClient(ABC):
3535

3636
def __init__(self, device_info: DeviceData) -> None:
3737
"""Initialize RoborockClient."""
38-
self.event_loop = get_running_loop_or_create_one()
3938
self.device_info = device_info
4039
self._nonce = secrets.token_bytes(16)
4140
self._waiting_queue: dict[int, RoborockFuture] = {}

roborock/cloud_api.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from __future__ import annotations
22

3+
import asyncio
34
import logging
45
import threading
56
from abc import ABC
@@ -158,7 +159,8 @@ async def async_disconnect(self) -> None:
158159
if disconnected_future := self._sync_disconnect():
159160
# There are no errors set on this future
160161
await disconnected_future
161-
await self.event_loop.run_in_executor(None, self._mqtt_client.loop_stop)
162+
loop = asyncio.get_running_loop()
163+
await loop.run_in_executor(None, self._mqtt_client.loop_stop)
162164

163165
async def async_connect(self) -> None:
164166
async with self._mutex:

roborock/local_api.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import asyncio
44
import logging
55
from abc import ABC
6-
from asyncio import Lock, TimerHandle, Transport
6+
from asyncio import Lock, TimerHandle, Transport, get_running_loop
77
from collections.abc import Callable
88
from dataclasses import dataclass
99

@@ -72,7 +72,8 @@ async def keep_alive_func(self, _=None):
7272
await self.ping()
7373
except RoborockException:
7474
pass
75-
self.keep_alive_task = self.event_loop.call_later(10, lambda: asyncio.create_task(self.keep_alive_func()))
75+
loop = asyncio.get_running_loop()
76+
self.keep_alive_task = loop.call_later(10, lambda: asyncio.create_task(self.keep_alive_func()))
7677

7778
async def async_connect(self) -> None:
7879
should_ping = False
@@ -82,7 +83,8 @@ async def async_connect(self) -> None:
8283
self._sync_disconnect()
8384
async with async_timeout.timeout(self.queue_timeout):
8485
self._logger.debug(f"Connecting to {self.host}")
85-
self.transport, _ = await self.event_loop.create_connection( # type: ignore
86+
loop = get_running_loop()
87+
self.transport, _ = await loop.create_connection( # type: ignore
8688
lambda: self._local_protocol, self.host, 58867
8789
)
8890
self._logger.info(f"Connected to {self.host}")
@@ -94,7 +96,8 @@ async def async_connect(self) -> None:
9496
await self.keep_alive_func()
9597

9698
def _sync_disconnect(self) -> None:
97-
if self.transport and self.event_loop.is_running():
99+
loop = asyncio.get_running_loop()
100+
if self.transport and loop.is_running():
98101
self._logger.debug(f"Disconnecting from {self.host}")
99102
self.transport.close()
100103
if self.keep_alive_task:

roborock/util.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,7 @@ def wrapped(*args, **kwargs):
7474

7575

7676
class RepeatableTask:
77-
def __init__(self, loop: AbstractEventLoop, callback: Callable[[], Coroutine], interval: int):
78-
self.loop = loop
77+
def __init__(self, callback: Callable[[], Coroutine], interval: int):
7978
self.callback = callback
8079
self.interval = interval
8180
self._task: TimerHandle | None = None
@@ -86,7 +85,8 @@ async def _run_task(self):
8685
response = await self.callback()
8786
except RoborockException:
8887
pass
89-
self._task = self.loop.call_later(self.interval, self._run_task_soon)
88+
loop = asyncio.get_running_loop()
89+
self._task = loop.call_later(self.interval, self._run_task_soon)
9090
return response
9191

9292
def _run_task_soon(self):

roborock/version_1_apis/roborock_client_v1.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,11 +82,11 @@
8282

8383

8484
class AttributeCache:
85-
def __init__(self, attribute: RoborockAttribute, loop: asyncio.AbstractEventLoop, send_command: _SendCommandT):
85+
def __init__(self, attribute: RoborockAttribute, send_command: _SendCommandT):
8686
self.attribute = attribute
8787
self._send_command = send_command
8888
self.attribute = attribute
89-
self.task = RepeatableTask(loop, self._async_value, EVICT_TIME)
89+
self.task = RepeatableTask(self._async_value, EVICT_TIME)
9090
self._value: Any = None
9191
self._mutex = asyncio.Lock()
9292
self.unsupported: bool = False
@@ -156,7 +156,7 @@ def __init__(self, device_info: DeviceData, endpoint: str):
156156
super().__init__(device_info)
157157
self._status_type: type[Status] = ModelStatus.get(device_info.model, S7MaxVStatus)
158158
self.cache: dict[CacheableAttribute, AttributeCache] = {
159-
cacheable_attribute: AttributeCache(attr, self.event_loop, self._send_command)
159+
cacheable_attribute: AttributeCache(attr, self._send_command)
160160
for cacheable_attribute, attr in get_cache_map().items()
161161
}
162162
if device_info.device.duid not in self._listeners:

tests/conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ def handle_write(data: bytes) -> None:
227227

228228
return (mock_transport, "proto")
229229

230-
with patch("roborock.api.get_running_loop_or_create_one") as mock_loop:
230+
with patch("roborock.local_api.get_running_loop") as mock_loop:
231231
mock_loop.return_value.create_connection.side_effect = create_connection
232232
yield
233233

0 commit comments

Comments
 (0)