xoscar 0.4.1__cp39-cp39-win_amd64.whl → 0.4.3__cp39-cp39-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of xoscar might be problematic. Click here for more details.

Binary file
@@ -17,8 +17,9 @@ from __future__ import annotations
17
17
 
18
18
  import asyncio
19
19
  import concurrent.futures as futures
20
+ import logging
20
21
  import weakref
21
- from typing import Any, Callable, Coroutine, Dict, Type
22
+ from typing import Any, Callable, Coroutine, Dict, Optional, Type
22
23
  from urllib.parse import urlparse
23
24
 
24
25
  from ...errors import ServerClosed
@@ -29,13 +30,15 @@ from .errors import ChannelClosed
29
30
 
30
31
  DEFAULT_DUMMY_ADDRESS = "dummy://0"
31
32
 
33
+ logger = logging.getLogger(__name__)
34
+
32
35
 
33
36
  class DummyChannel(Channel):
34
37
  """
35
38
  Channel for communications in same process.
36
39
  """
37
40
 
38
- __slots__ = "_in_queue", "_out_queue", "_closed"
41
+ __slots__ = "__weakref__", "_in_queue", "_out_queue", "_closed"
39
42
 
40
43
  name = "dummy"
41
44
 
@@ -100,8 +103,8 @@ class DummyServer(Server):
100
103
  _address_to_instances: weakref.WeakValueDictionary[str, "DummyServer"] = (
101
104
  weakref.WeakValueDictionary()
102
105
  )
103
- _channels: list[ChannelType]
104
- _tasks: list[asyncio.Task]
106
+ _channels: weakref.WeakSet[Channel]
107
+ _tasks: set[asyncio.Task]
105
108
  scheme: str | None = "dummy"
106
109
 
107
110
  def __init__(
@@ -111,8 +114,8 @@ class DummyServer(Server):
111
114
  ):
112
115
  super().__init__(address, channel_handler)
113
116
  self._closed = asyncio.Event()
114
- self._channels = []
115
- self._tasks = []
117
+ self._channels = weakref.WeakSet()
118
+ self._tasks = set()
116
119
 
117
120
  @classmethod
118
121
  def get_instance(cls, address: str):
@@ -178,7 +181,7 @@ class DummyServer(Server):
178
181
  f"{type(self).__name__} got unexpected "
179
182
  f'arguments: {",".join(kwargs)}'
180
183
  )
181
- self._channels.append(channel)
184
+ self._channels.add(channel)
182
185
  await self.channel_handler(channel)
183
186
 
184
187
  @implements(Server.stop)
@@ -203,6 +206,7 @@ class DummyClient(Client):
203
206
  self, local_address: str | None, dest_address: str | None, channel: Channel
204
207
  ):
205
208
  super().__init__(local_address, dest_address, channel)
209
+ self._task: Optional[asyncio.Task] = None
206
210
 
207
211
  @staticmethod
208
212
  @implements(Client.connect)
@@ -232,11 +236,25 @@ class DummyClient(Client):
232
236
  task = asyncio.create_task(conn_coro)
233
237
  client = DummyClient(local_address, dest_address, client_channel)
234
238
  client._task = task
235
- server._tasks.append(task)
239
+ server._tasks.add(task)
240
+
241
+ def _discard(t):
242
+ server._tasks.discard(t)
243
+ logger.info("Channel exit: %s", server_channel.info)
244
+
245
+ task.add_done_callback(_discard)
236
246
  return client
237
247
 
238
248
  @implements(Client.close)
239
249
  async def close(self):
240
250
  await super().close()
241
- self._task.cancel()
242
- self._task = None
251
+ if self._task is not None:
252
+ task_loop = self._task.get_loop()
253
+ if task_loop is not None:
254
+ if not task_loop.is_running():
255
+ logger.warning(
256
+ "Dummy channel cancel task on a stopped loop, dest address: %s.",
257
+ self.dest_address,
258
+ )
259
+ self._task.cancel()
260
+ self._task = None
@@ -113,7 +113,7 @@ class SocketChannel(Channel):
113
113
  class _BaseSocketServer(Server, metaclass=ABCMeta):
114
114
  __slots__ = "_aio_server", "_channels"
115
115
 
116
- _channels: list[ChannelType]
116
+ _channels: set[Channel]
117
117
 
118
118
  def __init__(
119
119
  self,
@@ -124,7 +124,7 @@ class _BaseSocketServer(Server, metaclass=ABCMeta):
124
124
  super().__init__(address, channel_handler)
125
125
  # asyncio.Server
126
126
  self._aio_server = aio_server
127
- self._channels = []
127
+ self._channels = set()
128
128
 
129
129
  @implements(Server.start)
130
130
  async def start(self):
@@ -170,9 +170,16 @@ class _BaseSocketServer(Server, metaclass=ABCMeta):
170
170
  dest_address=dest_address,
171
171
  channel_type=self.channel_type,
172
172
  )
173
- self._channels.append(channel)
173
+ self._channels.add(channel)
174
174
  # handle over channel to some handlers
175
- await self.channel_handler(channel)
175
+ try:
176
+ await self.channel_handler(channel)
177
+ finally:
178
+ if not channel.closed:
179
+ await channel.close()
180
+ # Remove channel if channel exit
181
+ self._channels.discard(channel)
182
+ logger.debug("Channel exit: %s", channel.info)
176
183
 
177
184
  @implements(Server.stop)
178
185
  async def stop(self):
@@ -185,6 +192,7 @@ class _BaseSocketServer(Server, metaclass=ABCMeta):
185
192
  await asyncio.gather(
186
193
  *(channel.close() for channel in self._channels if not channel.closed)
187
194
  )
195
+ self._channels.clear()
188
196
 
189
197
  @property
190
198
  @implements(Server.stopped)
@@ -368,7 +368,7 @@ class UCXServer(Server):
368
368
  scheme = "ucx"
369
369
 
370
370
  _ucp_listener: "ucp.Listener" # type: ignore
371
- _channels: List[UCXChannel]
371
+ _channels: set[UCXChannel]
372
372
 
373
373
  def __init__(
374
374
  self,
@@ -381,7 +381,7 @@ class UCXServer(Server):
381
381
  self.host = host
382
382
  self.port = port
383
383
  self._ucp_listener = ucp_listener
384
- self._channels = []
384
+ self._channels = set()
385
385
  self._closed = asyncio.Event()
386
386
 
387
387
  @classproperty
@@ -469,9 +469,16 @@ class UCXServer(Server):
469
469
  channel = UCXChannel(
470
470
  ucp_endpoint, local_address=local_address, dest_address=dest_address
471
471
  )
472
- self._channels.append(channel)
472
+ self._channels.add(channel)
473
473
  # handle over channel to some handlers
474
- await self.channel_handler(channel)
474
+ try:
475
+ await self.channel_handler(channel)
476
+ finally:
477
+ if not channel.closed:
478
+ await channel.close()
479
+ # Remove channel if channel exit
480
+ self._channels.discard(channel)
481
+ logger.debug("Channel exit: %s", channel.info)
475
482
 
476
483
  @implements(Server.stop)
477
484
  async def stop(self):
@@ -480,7 +487,7 @@ class UCXServer(Server):
480
487
  await asyncio.gather(
481
488
  *(channel.close() for channel in self._channels if not channel.closed)
482
489
  )
483
- self._channels = []
490
+ self._channels.clear()
484
491
  self._ucp_listener = None
485
492
  self._closed.set()
486
493
 
xoscar/backends/core.py CHANGED
@@ -16,8 +16,11 @@
16
16
  from __future__ import annotations
17
17
 
18
18
  import asyncio
19
+ import atexit
19
20
  import copy
20
21
  import logging
22
+ import threading
23
+ import weakref
21
24
  from typing import Type, Union
22
25
 
23
26
  from .._utils import Timer
@@ -31,8 +34,8 @@ ResultMessageType = Union[ResultMessage, ErrorMessage]
31
34
  logger = logging.getLogger(__name__)
32
35
 
33
36
 
34
- class ActorCaller:
35
- __slots__ = "_client_to_message_futures", "_clients", "_profiling_data"
37
+ class ActorCallerThreadLocal:
38
+ __slots__ = ("_client_to_message_futures", "_clients", "_profiling_data")
36
39
 
37
40
  _client_to_message_futures: dict[Client, dict[bytes, asyncio.Future]]
38
41
  _clients: dict[Client, asyncio.Task]
@@ -193,6 +196,7 @@ class ActorCaller:
193
196
  return await self.call_with_client(client, message, wait)
194
197
 
195
198
  async def stop(self):
199
+ logger.debug("Actor caller stop.")
196
200
  try:
197
201
  await asyncio.gather(*[client.close() for client in self._clients])
198
202
  except (ConnectionError, ServerClosed):
@@ -202,3 +206,38 @@ class ActorCaller:
202
206
  def cancel_tasks(self):
203
207
  # cancel listening for all clients
204
208
  _ = [task.cancel() for task in self._clients.values()]
209
+
210
+
211
+ class ActorCaller:
212
+ __slots__ = "_thread_local"
213
+
214
+ class _RefHolder:
215
+ pass
216
+
217
+ _close_loop = asyncio.new_event_loop()
218
+ _close_thread = threading.Thread(target=_close_loop.run_forever, daemon=True)
219
+ _close_thread.start()
220
+ atexit.register(_close_loop.call_soon_threadsafe, _close_loop.stop)
221
+
222
+ def __init__(self):
223
+ self._thread_local = threading.local()
224
+
225
+ def __getattr__(self, item):
226
+ try:
227
+ actor_caller = self._thread_local.actor_caller
228
+ except AttributeError:
229
+ thread_info = str(threading.current_thread())
230
+ logger.debug("Creating a new actor caller for thread: %s", thread_info)
231
+ actor_caller = self._thread_local.actor_caller = ActorCallerThreadLocal()
232
+ ref = self._thread_local.ref = ActorCaller._RefHolder()
233
+ # If the thread exit, we clean the related actor callers and channels.
234
+
235
+ def _cleanup():
236
+ asyncio.run_coroutine_threadsafe(actor_caller.stop(), self._close_loop)
237
+ logger.debug(
238
+ "Clean up the actor caller due to thread exit: %s", thread_info
239
+ )
240
+
241
+ weakref.finalize(ref, _cleanup)
242
+
243
+ return getattr(actor_caller, item)
Binary file
xoscar/collective/uv.dll CHANGED
Binary file
Binary file
Binary file
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: xoscar
3
- Version: 0.4.1
3
+ Version: 0.4.3
4
4
  Summary: Python actor framework for heterogeneous computing.
5
5
  Home-page: http://github.com/xorbitsai/xoscar
6
6
  Author: Qin Xuye
@@ -1,5 +1,5 @@
1
1
  xoscar/__init__.py,sha256=dlwtB7dnDp5WME6CZVQY7d9lk1yJ9s___H5UxjGlAd4,1668
2
- xoscar/_utils.cp39-win_amd64.pyd,sha256=rA-ivDY6A_BsLAJaLh6nxgHBRS2H16c8E4qVq4P1WII,117248
2
+ xoscar/_utils.cp39-win_amd64.pyd,sha256=FFd9OHF1DlHakZ6yDteAogr772FTnd1M36h5HHEtHtU,117248
3
3
  xoscar/_utils.pxd,sha256=rlNbTg5lhXA-jCOLksqF4jhUlNn0xw2jx1HxdLa34pc,1193
4
4
  xoscar/_utils.pyx,sha256=5Wvind3AQ3JaMK7Zv9SjhiPO6LEol2hW7_fMncn69go,7300
5
5
  xoscar/_version.py,sha256=bsfCVAo_o9LkiP3AjPsP4SRRqhjuS0t4D1WGJPzbdls,24412
@@ -7,10 +7,10 @@ xoscar/api.py,sha256=B5oXv4vgMxMteh1YNaBmNFDrUFmYa_dCdzfaWwwZnCo,13820
7
7
  xoscar/backend.py,sha256=8G5JwjoOT6Q2slb11eXNApxgcmvNQUCdQzkoIMDwLcQ,1917
8
8
  xoscar/batch.py,sha256=Jk5BSpvMFAV9DrRy0a9tgPvIo_dt8cbJReZBL0cnOPc,8128
9
9
  xoscar/constants.py,sha256=GJ1KEOxwnqksc9K_GH42TSWpQECeC6ti3KJmE3PUcTw,810
10
- xoscar/context.cp39-win_amd64.pyd,sha256=vs5foDr1olIiaEnZsYkMQZ9vGCMlpcJ8OK43SDwIE9A,158720
10
+ xoscar/context.cp39-win_amd64.pyd,sha256=76-7TUpyoo8cjEh3CKN3IZ_jCEtMGz2fLQ9YqvsrBWI,158720
11
11
  xoscar/context.pxd,sha256=6n6IAbmArSRq8EjcsbS6npW8xP1jI0qOoS1fF0oyj-o,746
12
12
  xoscar/context.pyx,sha256=FOJVerGOvxe2USryXEQA0rpaFX_ScxISH6QWKUcahY8,11310
13
- xoscar/core.cp39-win_amd64.pyd,sha256=Qlcy3lIJsk0eVtIGjCMArFiUxx6cAhDkL3NUrlDCui0,334336
13
+ xoscar/core.cp39-win_amd64.pyd,sha256=DxPbFOMnDiZZU6rT7qwin6JrcUnfsK09XZZ1YBLiMnU,334336
14
14
  xoscar/core.pxd,sha256=dGv62H92PFG98SVILuF641kY-NWFEt1FYqqOX3WY5RQ,1330
15
15
  xoscar/core.pyx,sha256=0YvJW2AHgymyfsAlPGvIFw65J5gTKO3PK2p1wl4VlJ0,22388
16
16
  xoscar/debug.py,sha256=hrmxIH6zvTKasQo6PUUgXu5mgEsR0g87Fvpw7CoHipg,5257
@@ -29,18 +29,18 @@ xoscar/backends/__init__.py,sha256=g9OllTquu9MRB5nySVoyiRv2z-_OSALWrOhwt7L9WXc,6
29
29
  xoscar/backends/allocate_strategy.py,sha256=DzvTlixwzTANURI2mDLHm3vcaugSPDxU6UQZb89KH0U,5005
30
30
  xoscar/backends/config.py,sha256=7nmvU_19zYR7n-bT8BNasbjntwmobmMiM7wN7O6Lujc,5129
31
31
  xoscar/backends/context.py,sha256=NukXzBwq9ZwuiN1y6RE1hfNGsW589hDtJAVwu-DV9E0,15874
32
- xoscar/backends/core.py,sha256=TNf-ROrmVixN9A82Fh1gh1UkqBdBZJd1_nlMtP4A0Bw,8243
33
- xoscar/backends/message.cp39-win_amd64.pyd,sha256=P6pGrismuoAN2wK2LIO0QR-c_RmNEWToDuSPrwU9uYk,268800
32
+ xoscar/backends/core.py,sha256=UBgPX-9ZdC2b6Ci5dGowlqdp1Sb2JU9ULYOhHkd9wOQ,9623
33
+ xoscar/backends/message.cp39-win_amd64.pyd,sha256=IomY97q4oiL6LGLCxUN0Zw5x5lW6jW48lsmQrdv8yc4,268800
34
34
  xoscar/backends/message.pyx,sha256=23j-fjxOVONPWY0-C5sfCOMbZCx4PTxN0GU8YfrLNeg,18529
35
35
  xoscar/backends/pool.py,sha256=nh2DTrcOrZc75TG2v7MXeGLMLhEO4GsObD7zirymZ3c,61445
36
36
  xoscar/backends/router.py,sha256=GJpSV_LhzINHdTp5jtsMHfPNMkNb1KI-WlqGqhwApGU,7953
37
37
  xoscar/backends/communication/__init__.py,sha256=Z0_RJkPGwLJeapSNt-TiO9DvnpBPu8P4PCooLaAqjkk,1080
38
38
  xoscar/backends/communication/base.py,sha256=wmWTeE4lcB_ohqyJJ6MdzMGcrOqy2RSKRp8y-NDuFdY,7736
39
39
  xoscar/backends/communication/core.py,sha256=ZM_fU0yokoPzXcJ6j-89llp2r7J9pl3gE5iImn4b4bE,2199
40
- xoscar/backends/communication/dummy.py,sha256=apbkfFdVWqeqc8Cc1LInOw6ikVoFWixTwBN__djxgBY,8040
40
+ xoscar/backends/communication/dummy.py,sha256=hxp2wvBFR-X63Nxj128yBNKn5D_azW-UrWNCQNYJHJI,8739
41
41
  xoscar/backends/communication/errors.py,sha256=-O6ZaKs6Gz7g_ZnKU2wrz8D9btowqaYuQ9u0zCYSLWo,743
42
- xoscar/backends/communication/socket.py,sha256=sq9abnWvngA55Sxz3TV0nL4JuxZX79DgTQn8E3xbRXY,14111
43
- xoscar/backends/communication/ucx.py,sha256=defQN2sirsu-KqvXox_I_wzAfWSq5LJkjKdzo0vtPgw,20234
42
+ xoscar/backends/communication/socket.py,sha256=AQMGCOroKabjQHwm50dKH8blFp_7mFiW4JCrhe97-jE,14400
43
+ xoscar/backends/communication/ucx.py,sha256=SQh461aiqdKKZe9fC4sDroFO2FmtQ_vX0oKSQjnqoFA,20498
44
44
  xoscar/backends/communication/utils.py,sha256=F-muF5_ow9JzAPAZ3d8XaGDiz3bRZOdWmWBDwQOVLe0,3761
45
45
  xoscar/backends/indigen/__init__.py,sha256=Khr2aGbaIw_04NIdY7QNhdljCKbmmzLb4NeAOM3LF8M,701
46
46
  xoscar/backends/indigen/backend.py,sha256=cCMkZDEKuRQlFb6v79JvWi5lfzsvAafznOeEWlw7CWY,1663
@@ -54,8 +54,8 @@ xoscar/collective/common.py,sha256=9c7xq3IOUvfA0I9GnpalUqXZOzmF6IEILv4zL64BYVE,3
54
54
  xoscar/collective/core.py,sha256=191aPxbUgWpjzrqyozndImDAQhZFmqoQdBkHFLDfXN0,24239
55
55
  xoscar/collective/process_group.py,sha256=kTPbrLMJSGhqbiWvTIiz-X3W0rZWd_CFn_zUIlXbOlM,23286
56
56
  xoscar/collective/utils.py,sha256=p3WEVtXvnVhkuO5mRgQBhBRFr1dKHcDKMjrbMyuiyfg,1219
57
- xoscar/collective/uv.dll,sha256=iPM9bHhRkk5hi2xcYQzj5R1hWm1tg-XVsouCAuoigYc,620544
58
- xoscar/collective/xoscar_pygloo.cp39-win_amd64.pyd,sha256=whMek_2N9JrumuEIpr4UQpHENkYTTnCoyPO1PdTz7WI,775168
57
+ xoscar/collective/uv.dll,sha256=r0EqFH4Q-ae4ruaT8tBL07fQT962_YhxL25R6bwsocs,620544
58
+ xoscar/collective/xoscar_pygloo.cp39-win_amd64.pyd,sha256=e0Fgk3HD1EnswaD9OjQ2Nn79PiCgxiRM6poGN_J7Cus,775168
59
59
  xoscar/metrics/__init__.py,sha256=RjXuuYw4I2YYgD8UY2Z5yCZk0Z56xMJ1n40O80Dtxf8,726
60
60
  xoscar/metrics/api.py,sha256=dtJ4QrIqQNXhJedeqOPs4TXKgrRGZFFN50xAd9SCfec,9144
61
61
  xoscar/metrics/backends/__init__.py,sha256=ZHepfhCDRuK9yz4pAM7bjpWDvS3Ijp1YgyynoUFLeuU,594
@@ -66,7 +66,7 @@ xoscar/metrics/backends/prometheus/__init__.py,sha256=ZHepfhCDRuK9yz4pAM7bjpWDvS
66
66
  xoscar/metrics/backends/prometheus/prometheus_metric.py,sha256=65hb8O3tmsEJ7jgOrIwl_suj9SE5Tmqcfjuk0urkLvE,2120
67
67
  xoscar/serialization/__init__.py,sha256=NOAn046vnHEkx--82BKNinV8EpyOfT5hqfRBGnKl56s,866
68
68
  xoscar/serialization/aio.py,sha256=7YLXgkWpQ3ANy-TZ1qO8Mt4_J3cZFhFh2FEgUgxMT60,4873
69
- xoscar/serialization/core.cp39-win_amd64.pyd,sha256=VcEI1DR7qE5PF3bUVUvxFMLp8dvzBw_zaxC_0CDXCOw,298496
69
+ xoscar/serialization/core.cp39-win_amd64.pyd,sha256=FFRO3EB7jb_z5pq16gIb8neIVFLTwYF20vVwMjlv2po,298496
70
70
  xoscar/serialization/core.pxd,sha256=X-47bqBM2Kzw5SkLqICdKD0gU6CpmLsBxC3kfW--wVk,1013
71
71
  xoscar/serialization/core.pyx,sha256=ZKexLRnRwZXXn2045kR7xfM_szcoPNrDuouQCWtpFp8,30570
72
72
  xoscar/serialization/cuda.py,sha256=Fj4Cpr_YmkGceUCo0mQn8fRvmHP_5WcLdRx6epZ3RC0,3869
@@ -74,7 +74,7 @@ xoscar/serialization/exception.py,sha256=t6yZn_Ate04UE1RbabNh7mu739sdtwarjuPXWhA
74
74
  xoscar/serialization/numpy.py,sha256=C6WVx-Sdl2OHBAvVY34DFjAKXlekMbpc2ni6bR8wxYo,3001
75
75
  xoscar/serialization/pyfury.py,sha256=3ucal29Hr7PX9_1SfB2x43FE2xw_C0rLkVv3foL7qwM,1200
76
76
  xoscar/serialization/scipy.py,sha256=9ph-yoRoNiwUZTwQrn35U60VPirWlncXNAg6EXvqMR4,2554
77
- xoscar-0.4.1.dist-info/METADATA,sha256=BfnUJHhYjnOGtAknk32D1ACdmTse9w3dZ-tE-NoIXQE,9265
78
- xoscar-0.4.1.dist-info/WHEEL,sha256=yA7mxgqX2UV73NtJdMh2AAmdb628loM81912H3s5r00,100
79
- xoscar-0.4.1.dist-info/top_level.txt,sha256=vYlqqY4Nys8Thm1hePIuUv8eQePdULVWMmt7lXtX_ZA,21
80
- xoscar-0.4.1.dist-info/RECORD,,
77
+ xoscar-0.4.3.dist-info/METADATA,sha256=9OJj9wwgu76by-N6gTxrPIjqkkpPSI_jFKMRAAqrc6Q,9265
78
+ xoscar-0.4.3.dist-info/WHEEL,sha256=yA7mxgqX2UV73NtJdMh2AAmdb628loM81912H3s5r00,100
79
+ xoscar-0.4.3.dist-info/top_level.txt,sha256=vYlqqY4Nys8Thm1hePIuUv8eQePdULVWMmt7lXtX_ZA,21
80
+ xoscar-0.4.3.dist-info/RECORD,,
File without changes