xoscar 0.9.0__cp312-cp312-macosx_10_13_x86_64.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.
Files changed (94) hide show
  1. xoscar/__init__.py +61 -0
  2. xoscar/_utils.cpython-312-darwin.so +0 -0
  3. xoscar/_utils.pxd +36 -0
  4. xoscar/_utils.pyx +246 -0
  5. xoscar/_version.py +693 -0
  6. xoscar/aio/__init__.py +16 -0
  7. xoscar/aio/base.py +86 -0
  8. xoscar/aio/file.py +59 -0
  9. xoscar/aio/lru.py +228 -0
  10. xoscar/aio/parallelism.py +39 -0
  11. xoscar/api.py +527 -0
  12. xoscar/backend.py +67 -0
  13. xoscar/backends/__init__.py +14 -0
  14. xoscar/backends/allocate_strategy.py +160 -0
  15. xoscar/backends/communication/__init__.py +30 -0
  16. xoscar/backends/communication/base.py +315 -0
  17. xoscar/backends/communication/core.py +69 -0
  18. xoscar/backends/communication/dummy.py +253 -0
  19. xoscar/backends/communication/errors.py +20 -0
  20. xoscar/backends/communication/socket.py +444 -0
  21. xoscar/backends/communication/ucx.py +538 -0
  22. xoscar/backends/communication/utils.py +97 -0
  23. xoscar/backends/config.py +157 -0
  24. xoscar/backends/context.py +437 -0
  25. xoscar/backends/core.py +352 -0
  26. xoscar/backends/indigen/__init__.py +16 -0
  27. xoscar/backends/indigen/__main__.py +19 -0
  28. xoscar/backends/indigen/backend.py +51 -0
  29. xoscar/backends/indigen/driver.py +26 -0
  30. xoscar/backends/indigen/fate_sharing.py +221 -0
  31. xoscar/backends/indigen/pool.py +515 -0
  32. xoscar/backends/indigen/shared_memory.py +548 -0
  33. xoscar/backends/message.cpython-312-darwin.so +0 -0
  34. xoscar/backends/message.pyi +255 -0
  35. xoscar/backends/message.pyx +646 -0
  36. xoscar/backends/pool.py +1630 -0
  37. xoscar/backends/router.py +285 -0
  38. xoscar/backends/test/__init__.py +16 -0
  39. xoscar/backends/test/backend.py +38 -0
  40. xoscar/backends/test/pool.py +233 -0
  41. xoscar/batch.py +256 -0
  42. xoscar/collective/__init__.py +27 -0
  43. xoscar/collective/backend/__init__.py +13 -0
  44. xoscar/collective/backend/nccl_backend.py +160 -0
  45. xoscar/collective/common.py +102 -0
  46. xoscar/collective/core.py +737 -0
  47. xoscar/collective/process_group.py +687 -0
  48. xoscar/collective/utils.py +41 -0
  49. xoscar/collective/xoscar_pygloo.cpython-312-darwin.so +0 -0
  50. xoscar/collective/xoscar_pygloo.pyi +239 -0
  51. xoscar/constants.py +23 -0
  52. xoscar/context.cpython-312-darwin.so +0 -0
  53. xoscar/context.pxd +21 -0
  54. xoscar/context.pyx +368 -0
  55. xoscar/core.cpython-312-darwin.so +0 -0
  56. xoscar/core.pxd +51 -0
  57. xoscar/core.pyx +664 -0
  58. xoscar/debug.py +188 -0
  59. xoscar/driver.py +42 -0
  60. xoscar/errors.py +63 -0
  61. xoscar/libcpp.pxd +31 -0
  62. xoscar/metrics/__init__.py +21 -0
  63. xoscar/metrics/api.py +288 -0
  64. xoscar/metrics/backends/__init__.py +13 -0
  65. xoscar/metrics/backends/console/__init__.py +13 -0
  66. xoscar/metrics/backends/console/console_metric.py +82 -0
  67. xoscar/metrics/backends/metric.py +149 -0
  68. xoscar/metrics/backends/prometheus/__init__.py +13 -0
  69. xoscar/metrics/backends/prometheus/prometheus_metric.py +70 -0
  70. xoscar/nvutils.py +717 -0
  71. xoscar/profiling.py +260 -0
  72. xoscar/serialization/__init__.py +20 -0
  73. xoscar/serialization/aio.py +141 -0
  74. xoscar/serialization/core.cpython-312-darwin.so +0 -0
  75. xoscar/serialization/core.pxd +28 -0
  76. xoscar/serialization/core.pyi +57 -0
  77. xoscar/serialization/core.pyx +944 -0
  78. xoscar/serialization/cuda.py +111 -0
  79. xoscar/serialization/exception.py +48 -0
  80. xoscar/serialization/mlx.py +67 -0
  81. xoscar/serialization/numpy.py +82 -0
  82. xoscar/serialization/pyfury.py +37 -0
  83. xoscar/serialization/scipy.py +72 -0
  84. xoscar/serialization/torch.py +180 -0
  85. xoscar/utils.py +522 -0
  86. xoscar/virtualenv/__init__.py +34 -0
  87. xoscar/virtualenv/core.py +268 -0
  88. xoscar/virtualenv/platform.py +56 -0
  89. xoscar/virtualenv/utils.py +100 -0
  90. xoscar/virtualenv/uv.py +321 -0
  91. xoscar-0.9.0.dist-info/METADATA +230 -0
  92. xoscar-0.9.0.dist-info/RECORD +94 -0
  93. xoscar-0.9.0.dist-info/WHEEL +6 -0
  94. xoscar-0.9.0.dist-info/top_level.txt +2 -0
@@ -0,0 +1,646 @@
1
+ # Copyright 2022-2023 XProbe Inc.
2
+ # derived from copyright 1999-2022 Alibaba Group Holding Ltd.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ import asyncio
17
+ from enum import Enum
18
+ from types import TracebackType
19
+ from typing import Any, Type
20
+
21
+ from tblib import pickling_support
22
+
23
+ from ..core cimport ActorRef, BufferRef
24
+ from ..serialization.core cimport Serializer
25
+
26
+ from ..utils import wrap_exception
27
+
28
+ from .._utils cimport new_random_id
29
+
30
+ # make sure traceback can be pickled
31
+ pickling_support.install()
32
+
33
+ cdef int _DEFAULT_PROTOCOL = 0
34
+ DEFAULT_PROTOCOL = _DEFAULT_PROTOCOL
35
+
36
+
37
+ class MessageType(Enum):
38
+ control = 0
39
+ result = 1
40
+ error = 2
41
+ create_actor = 3
42
+ destroy_actor = 4
43
+ has_actor = 5
44
+ actor_ref = 6
45
+ send = 7
46
+ tell = 8
47
+ cancel = 9
48
+ copy_to_buffers = 10
49
+ copy_to_fileobjs = 11
50
+ forward = 12
51
+
52
+
53
+ class ControlMessageType(Enum):
54
+ stop = 0
55
+ restart = 1
56
+ sync_config = 2
57
+ get_config = 3
58
+ wait_pool_recovered = 4
59
+ add_sub_pool_actor = 5
60
+ # the new channel created is for data transfer only
61
+ switch_to_copy_to = 6
62
+
63
+
64
+ cdef class _MessageSerialItem:
65
+ cdef:
66
+ tuple serialized
67
+ list subs
68
+
69
+ def __cinit__(self, tuple serialized, list subs):
70
+ self.serialized = serialized
71
+ self.subs = subs
72
+
73
+
74
+ cdef class _MessageBase:
75
+ message_type: MessageType = None
76
+
77
+ cdef:
78
+ public int protocol
79
+ public bytes message_id
80
+ public list message_trace
81
+ public object profiling_context
82
+
83
+ def __init__(
84
+ self,
85
+ bytes message_id = None,
86
+ int protocol = _DEFAULT_PROTOCOL,
87
+ list message_trace = None,
88
+ object profiling_context = None,
89
+ ):
90
+ self.message_id = message_id
91
+ self.protocol = protocol
92
+ # A message can be in the scope of other messages,
93
+ # this is mainly used for detecting deadlocks,
94
+ # e.g. Actor `A` sent a message(id: 1) to actor `B`,
95
+ # in the processing of `B`, it sent back a message(id: 2) to `A`,
96
+ # deadlock happens, because `A` is still waiting for reply from `B`.
97
+ # In this case, the `scoped_message_ids` will be [1, 2],
98
+ # `A` will find that id:1 already exists in inbox,
99
+ # thus deadlock detected.
100
+ self.message_trace = message_trace
101
+ self.profiling_context = profiling_context
102
+
103
+ cdef _MessageSerialItem serial(self):
104
+ return _MessageSerialItem(
105
+ (
106
+ self.message_type.value,
107
+ self.message_id,
108
+ self.protocol,
109
+ self.message_trace,
110
+ self.profiling_context,
111
+ ),
112
+ [],
113
+ )
114
+
115
+ cdef deserial_members(self, tuple serialized, list subs):
116
+ self.message_id = serialized[1]
117
+ self.protocol = serialized[2]
118
+ self.message_trace = serialized[3]
119
+ self.profiling_context = serialized[4]
120
+
121
+ def __repr__(self):
122
+ cdef list attr_reprs = []
123
+ for attr in dir(self):
124
+ if attr.startswith("_") or attr == "message_type":
125
+ continue
126
+ val = getattr(self, attr)
127
+ if callable(val):
128
+ continue
129
+ attr_reprs.append(f"{attr}={val!r}")
130
+ values = ", ".join(attr_reprs)
131
+ return f"{type(self).__name__}({values})"
132
+
133
+
134
+ cdef class ControlMessage(_MessageBase):
135
+ message_type = MessageType.control
136
+
137
+ cdef:
138
+ public str address
139
+ public object control_message_type
140
+ public object content
141
+
142
+ def __init__(
143
+ self,
144
+ bytes message_id = None,
145
+ str address = None,
146
+ object control_message_type: ControlMessageType = None,
147
+ object content: Any = None,
148
+ int protocol = _DEFAULT_PROTOCOL,
149
+ list message_trace = None,
150
+ ):
151
+ _MessageBase.__init__(
152
+ self, message_id, protocol=protocol, message_trace=message_trace
153
+ )
154
+ self.address = address
155
+ self.control_message_type = control_message_type
156
+ self.content = content
157
+
158
+ cdef _MessageSerialItem serial(self):
159
+ cdef _MessageSerialItem item = _MessageBase.serial(self)
160
+ item.serialized += (
161
+ self.address,
162
+ self.control_message_type,
163
+ )
164
+ item.subs = [self.content]
165
+ return item
166
+
167
+ cdef deserial_members(self, tuple serialized, list subs):
168
+ _MessageBase.deserial_members(self, serialized, subs)
169
+ self.address = serialized[-2]
170
+ self.control_message_type = serialized[-1]
171
+ self.content = subs[0]
172
+
173
+
174
+ cdef class ResultMessage(_MessageBase):
175
+ message_type = MessageType.result
176
+
177
+ cdef:
178
+ public object result
179
+
180
+ def __init__(
181
+ self,
182
+ bytes message_id = None,
183
+ object result: Any = None,
184
+ int protocol = _DEFAULT_PROTOCOL,
185
+ list message_trace = None,
186
+ object profiling_context = None,
187
+ ):
188
+ _MessageBase.__init__(
189
+ self,
190
+ message_id,
191
+ protocol=protocol,
192
+ message_trace=message_trace,
193
+ profiling_context=profiling_context,
194
+ )
195
+ self.result = result
196
+
197
+ cdef _MessageSerialItem serial(self):
198
+ cdef _MessageSerialItem item = _MessageBase.serial(self)
199
+ item.subs = [self.result]
200
+ return item
201
+
202
+ cdef deserial_members(self, tuple serialized, list subs):
203
+ _MessageBase.deserial_members(self, serialized, subs)
204
+ self.result = subs[0]
205
+
206
+
207
+ class _AsCauseBase:
208
+ def __str__(self):
209
+ return f"[address={self.address}, pid={self.pid}] {str(self.__wrapped__)}"
210
+
211
+
212
+ cdef class ErrorMessage(_MessageBase):
213
+ message_type = MessageType.error
214
+
215
+ cdef:
216
+ public str address
217
+ public long pid
218
+ public type error_type
219
+ public object error
220
+ public object traceback
221
+
222
+ def __init__(
223
+ self,
224
+ bytes message_id = None,
225
+ str address: str = None,
226
+ long pid = -1,
227
+ type error_type: Type[BaseException] = None,
228
+ object error: BaseException = None,
229
+ object traceback: TracebackType = None,
230
+ int protocol = _DEFAULT_PROTOCOL,
231
+ list message_trace = None,
232
+ ):
233
+ _MessageBase.__init__(
234
+ self, message_id, protocol=protocol, message_trace=message_trace
235
+ )
236
+ self.address = address
237
+ self.pid = pid
238
+ self.error_type = error_type
239
+ self.error = error
240
+ self.traceback = traceback
241
+
242
+ def as_instanceof_cause(self):
243
+ # Check the as_instanceof_cause is not recursive.
244
+ #
245
+ # e.g. actor_a.method1 will reraise the exception raised
246
+ # from actor_b.method2. But these two actors are in the same
247
+ # process, so we don't want to append duplicated address and pid in the
248
+ # error message.
249
+ if issubclass(self.error_type, _AsCauseBase):
250
+ return self.error.with_traceback(self.traceback)
251
+
252
+ # for being compatible with Python 3.12 `asyncio.wait_for`
253
+ # https://github.com/python/cpython/pull/113850
254
+ if isinstance(self.error, asyncio.CancelledError):
255
+ return asyncio.CancelledError(f"[address={self.address}, pid={self.pid}]").with_traceback(self.traceback)
256
+
257
+ return wrap_exception(
258
+ self.error,
259
+ (_AsCauseBase,),
260
+ traceback=self.traceback,
261
+ attr_dict=dict(address=self.address, pid=self.pid),
262
+ )
263
+
264
+ cdef _MessageSerialItem serial(self):
265
+ cdef _MessageSerialItem item = _MessageBase.serial(self)
266
+ item.serialized += (self.address, self.pid)
267
+ item.subs = [self.error_type, self.error, self.traceback]
268
+ return item
269
+
270
+ cdef deserial_members(self, tuple serialized, list subs):
271
+ _MessageBase.deserial_members(self, serialized, subs)
272
+ self.address = serialized[-2]
273
+ self.pid = serialized[-1]
274
+ self.error_type = subs[0]
275
+ self.error = subs[1]
276
+ self.traceback = subs[2]
277
+
278
+
279
+ cdef class CreateActorMessage(_MessageBase):
280
+ message_type = MessageType.create_actor
281
+
282
+ cdef:
283
+ public type actor_cls
284
+ public bytes actor_id
285
+ public tuple args
286
+ public dict kwargs
287
+ public object allocate_strategy
288
+ public object from_main
289
+
290
+ def __init__(
291
+ self,
292
+ bytes message_id = None,
293
+ type actor_cls = None,
294
+ bytes actor_id = None,
295
+ tuple args = None,
296
+ dict kwargs = None,
297
+ object allocate_strategy = None,
298
+ object from_main: bool = False,
299
+ int protocol = _DEFAULT_PROTOCOL,
300
+ list message_trace = None,
301
+ ):
302
+ _MessageBase.__init__(
303
+ self, message_id, protocol=protocol, message_trace=message_trace
304
+ )
305
+ self.actor_cls = actor_cls
306
+ self.actor_id = actor_id
307
+ self.args = args
308
+ self.kwargs = kwargs
309
+ self.allocate_strategy = allocate_strategy
310
+ self.from_main = from_main
311
+
312
+ cdef _MessageSerialItem serial(self):
313
+ cdef _MessageSerialItem item = _MessageBase.serial(self)
314
+ item.serialized += (
315
+ self.actor_id, self.allocate_strategy, self.from_main
316
+ )
317
+ item.subs = [self.actor_cls, self.args, self.kwargs]
318
+ return item
319
+
320
+ cdef deserial_members(self, tuple serialized, list subs):
321
+ _MessageBase.deserial_members(self, serialized, subs)
322
+ self.actor_id = serialized[-3]
323
+ self.allocate_strategy = serialized[-2]
324
+ self.from_main = serialized[-1]
325
+ self.actor_cls = subs[0]
326
+ self.args = subs[1]
327
+ self.kwargs = subs[2]
328
+
329
+
330
+ cdef class DestroyActorMessage(_MessageBase):
331
+ message_type = MessageType.destroy_actor
332
+
333
+ cdef:
334
+ public ActorRef actor_ref
335
+ public object from_main
336
+
337
+ def __init__(
338
+ self,
339
+ bytes message_id = None,
340
+ ActorRef actor_ref = None,
341
+ object from_main: bool = False,
342
+ int protocol = _DEFAULT_PROTOCOL,
343
+ list message_trace = None,
344
+ ):
345
+ _MessageBase.__init__(
346
+ self, message_id, protocol=protocol, message_trace=message_trace
347
+ )
348
+ self.actor_ref = actor_ref
349
+ self.from_main = from_main
350
+
351
+ cdef _MessageSerialItem serial(self):
352
+ cdef _MessageSerialItem item = _MessageBase.serial(self)
353
+ item.serialized += (
354
+ self.actor_ref.address, self.actor_ref.uid,
355
+ self.actor_ref.proxy_addresses, self.from_main
356
+ )
357
+ return item
358
+
359
+ cdef deserial_members(self, tuple serialized, list subs):
360
+ _MessageBase.deserial_members(self, serialized, subs)
361
+ self.actor_ref = ActorRef(serialized[-4], serialized[-3], serialized[-2])
362
+ self.from_main = serialized[-1]
363
+
364
+
365
+ cdef class HasActorMessage(_MessageBase):
366
+ message_type = MessageType.has_actor
367
+
368
+ cdef:
369
+ public ActorRef actor_ref
370
+
371
+ def __init__(
372
+ self,
373
+ bytes message_id = None,
374
+ ActorRef actor_ref = None,
375
+ int protocol = _DEFAULT_PROTOCOL,
376
+ list message_trace = None,
377
+ ):
378
+ _MessageBase.__init__(
379
+ self, message_id, protocol=protocol, message_trace=message_trace
380
+ )
381
+ self.actor_ref = actor_ref
382
+
383
+ cdef _MessageSerialItem serial(self):
384
+ cdef _MessageSerialItem item = _MessageBase.serial(self)
385
+ item.serialized += (
386
+ self.actor_ref.address, self.actor_ref.uid, self.actor_ref.proxy_addresses
387
+ )
388
+ return item
389
+
390
+ cdef deserial_members(self, tuple serialized, list subs):
391
+ _MessageBase.deserial_members(self, serialized, subs)
392
+ self.actor_ref = ActorRef(serialized[-3], serialized[-2], serialized[-1])
393
+
394
+
395
+ cdef class ActorRefMessage(_MessageBase):
396
+ message_type = MessageType.actor_ref
397
+
398
+ cdef:
399
+ public ActorRef actor_ref
400
+
401
+ def __init__(
402
+ self,
403
+ bytes message_id = None,
404
+ ActorRef actor_ref = None,
405
+ int protocol = _DEFAULT_PROTOCOL,
406
+ list message_trace = None,
407
+ ):
408
+ _MessageBase.__init__(
409
+ self, message_id, protocol=protocol, message_trace=message_trace
410
+ )
411
+ self.actor_ref = actor_ref
412
+
413
+ cdef _MessageSerialItem serial(self):
414
+ cdef _MessageSerialItem item = _MessageBase.serial(self)
415
+ item.serialized += (
416
+ self.actor_ref.address, self.actor_ref.uid, self.actor_ref.proxy_addresses
417
+ )
418
+ return item
419
+
420
+ cdef deserial_members(self, tuple serialized, list subs):
421
+ _MessageBase.deserial_members(self, serialized, subs)
422
+ self.actor_ref = ActorRef(serialized[-3], serialized[-2], serialized[-1])
423
+
424
+
425
+ cdef class SendMessage(_MessageBase):
426
+ message_type = MessageType.send
427
+
428
+ cdef:
429
+ public ActorRef actor_ref
430
+ public object content
431
+
432
+ def __init__(
433
+ self,
434
+ bytes message_id = None,
435
+ ActorRef actor_ref = None,
436
+ object content = None,
437
+ int protocol = _DEFAULT_PROTOCOL,
438
+ list message_trace = None,
439
+ object profiling_context = None,
440
+ ):
441
+ _MessageBase.__init__(
442
+ self,
443
+ message_id,
444
+ protocol=protocol,
445
+ message_trace=message_trace,
446
+ profiling_context=profiling_context,
447
+ )
448
+ self.actor_ref = actor_ref
449
+ self.content = content
450
+
451
+ cdef _MessageSerialItem serial(self):
452
+ cdef _MessageSerialItem item = _MessageBase.serial(self)
453
+ item.serialized += (
454
+ self.actor_ref.address, self.actor_ref.uid, self.actor_ref.proxy_addresses
455
+ )
456
+ item.subs = [self.content]
457
+ return item
458
+
459
+ cdef deserial_members(self, tuple serialized, list subs):
460
+ _MessageBase.deserial_members(self, serialized, subs)
461
+ self.actor_ref = ActorRef(serialized[-3], serialized[-2], serialized[-1])
462
+ self.content = subs[0]
463
+
464
+
465
+ cdef class TellMessage(SendMessage):
466
+ message_type = MessageType.tell
467
+
468
+
469
+ cdef class CancelMessage(_MessageBase):
470
+ message_type = MessageType.cancel
471
+
472
+ cdef:
473
+ public str address
474
+ public bytes cancel_message_id
475
+
476
+ def __init__(
477
+ self,
478
+ bytes message_id = None,
479
+ str address = None,
480
+ bytes cancel_message_id = None,
481
+ int protocol = _DEFAULT_PROTOCOL,
482
+ list message_trace = None,
483
+ ):
484
+ _MessageBase.__init__(
485
+ self, message_id, protocol=protocol, message_trace=message_trace
486
+ )
487
+ self.address = address
488
+ self.cancel_message_id = cancel_message_id
489
+
490
+ cdef _MessageSerialItem serial(self):
491
+ cdef _MessageSerialItem item = _MessageBase.serial(self)
492
+ item.serialized += (
493
+ self.address, self.cancel_message_id
494
+ )
495
+ return item
496
+
497
+ cdef deserial_members(self, tuple serialized, list subs):
498
+ _MessageBase.deserial_members(self, serialized, subs)
499
+ self.address = serialized[-2]
500
+ self.cancel_message_id = serialized[-1]
501
+
502
+
503
+ cdef class CopyToBuffersMessage(_MessageBase):
504
+ message_type = MessageType.copy_to_buffers
505
+
506
+ cdef:
507
+ public object content
508
+
509
+ def __init__(
510
+ self,
511
+ bytes message_id = None,
512
+ object content = None,
513
+ int protocol = _DEFAULT_PROTOCOL,
514
+ list message_trace = None,
515
+ ):
516
+ _MessageBase.__init__(
517
+ self,
518
+ message_id,
519
+ protocol=protocol,
520
+ message_trace=message_trace
521
+ )
522
+ self.content = content
523
+
524
+ cdef _MessageSerialItem serial(self):
525
+ cdef _MessageSerialItem item = _MessageBase.serial(self)
526
+ item.subs = [self.content]
527
+ return item
528
+
529
+ cdef deserial_members(self, tuple serialized, list subs):
530
+ _MessageBase.deserial_members(self, serialized, subs)
531
+ self.content = subs[0]
532
+
533
+
534
+ cdef class CopyToFileObjectsMessage(CopyToBuffersMessage):
535
+ message_type = MessageType.copy_to_fileobjs
536
+
537
+
538
+ cdef class ForwardMessage(_MessageBase):
539
+ message_type = MessageType.forward
540
+
541
+ cdef:
542
+ public str address
543
+ public _MessageBase raw_message
544
+
545
+ def __init__(
546
+ self,
547
+ bytes message_id = None,
548
+ str address = None,
549
+ _MessageBase raw_message = None,
550
+ int protocol = DEFAULT_PROTOCOL,
551
+ list message_trace = None,
552
+ ):
553
+ _MessageBase.__init__(
554
+ self,
555
+ message_id,
556
+ protocol=protocol,
557
+ message_trace=message_trace
558
+ )
559
+ self.address = address
560
+ self.raw_message = raw_message
561
+
562
+ cdef _MessageSerialItem serial(self):
563
+ cdef _MessageSerialItem item = _MessageBase.serial(self)
564
+ cdef _MessageSerialItem raw_message_serialized = self.raw_message.serial()
565
+ item.serialized += (self.address,)
566
+ item.serialized += raw_message_serialized.serialized
567
+ item.subs += raw_message_serialized.subs
568
+ return item
569
+
570
+ cdef deserial_members(self, tuple serialized, list subs):
571
+ # 5 is magic number that means serialized for _MessageBase
572
+ base_serialized = serialized[:5]
573
+ _MessageBase.deserial_members(self, base_serialized, [])
574
+ self.address = serialized[5]
575
+ # process raw message
576
+ tp = _message_type_to_message_cls[serialized[6]]
577
+ cdef _MessageBase raw_message = <_MessageBase>(tp())
578
+ raw_message.deserial_members(serialized[6:], subs)
579
+ self.raw_message = raw_message
580
+
581
+
582
+ cdef dict _message_type_to_message_cls = {
583
+ MessageType.control.value: ControlMessage,
584
+ MessageType.result.value: ResultMessage,
585
+ MessageType.error.value: ErrorMessage,
586
+ MessageType.create_actor.value: CreateActorMessage,
587
+ MessageType.destroy_actor.value: DestroyActorMessage,
588
+ MessageType.has_actor.value: HasActorMessage,
589
+ MessageType.actor_ref.value: ActorRefMessage,
590
+ MessageType.send.value: SendMessage,
591
+ MessageType.tell.value: TellMessage,
592
+ MessageType.cancel.value: CancelMessage,
593
+ MessageType.copy_to_buffers.value: CopyToBuffersMessage,
594
+ MessageType.copy_to_fileobjs.value: CopyToFileObjectsMessage,
595
+ MessageType.forward.value: ForwardMessage,
596
+ }
597
+
598
+
599
+ class DeserializeMessageFailed(RuntimeError):
600
+ def __init__(self, message_id):
601
+ self.message_id = message_id
602
+
603
+ def __str__(self):
604
+ return f"Deserialize {self.message_id} failed"
605
+
606
+
607
+ cdef class MessageSerializer(Serializer):
608
+ serializer_id = 32105
609
+
610
+ cpdef serial(self, object obj, dict context):
611
+ cdef _MessageBase msg = <_MessageBase>obj
612
+ cdef _MessageSerialItem ser_item
613
+
614
+ assert msg.protocol == _DEFAULT_PROTOCOL, "only support protocol 0 for now"
615
+ ser_item = msg.serial()
616
+ return ser_item.serialized, ser_item.subs, False
617
+
618
+ cpdef deserial(self, tuple serialized, dict context, list subs):
619
+ cdef _MessageBase msg
620
+
621
+ msg_type = serialized[0]
622
+ msg = _message_type_to_message_cls[msg_type]()
623
+ msg.deserial_members(serialized, subs)
624
+ return msg
625
+
626
+ cpdef on_deserial_error(
627
+ self,
628
+ tuple serialized,
629
+ dict context,
630
+ list subs_serialized,
631
+ int error_index,
632
+ object exc,
633
+ ):
634
+ message_id = serialized[1] # pos of message_id field
635
+ try:
636
+ raise DeserializeMessageFailed(message_id) from exc
637
+ except BaseException as new_ex:
638
+ return new_ex
639
+
640
+
641
+ # register message serializer
642
+ MessageSerializer.register(_MessageBase)
643
+
644
+
645
+ cpdef bytes new_message_id():
646
+ return new_random_id(32)