opengris-scaler 1.12.37__cp38-cp38-musllinux_1_2_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.
- opengris_scaler-1.12.37.dist-info/METADATA +730 -0
- opengris_scaler-1.12.37.dist-info/RECORD +196 -0
- opengris_scaler-1.12.37.dist-info/WHEEL +5 -0
- opengris_scaler-1.12.37.dist-info/entry_points.txt +10 -0
- opengris_scaler-1.12.37.dist-info/licenses/LICENSE +201 -0
- opengris_scaler-1.12.37.dist-info/licenses/LICENSE.spdx +7 -0
- opengris_scaler-1.12.37.dist-info/licenses/NOTICE +8 -0
- opengris_scaler.libs/libcapnp-1-e88d5415.0.1.so +0 -0
- opengris_scaler.libs/libgcc_s-2298274a.so.1 +0 -0
- opengris_scaler.libs/libkj-1-9bebd8ac.0.1.so +0 -0
- opengris_scaler.libs/libstdc++-08d5c7eb.so.6.0.33 +0 -0
- scaler/__init__.py +14 -0
- scaler/about.py +5 -0
- scaler/client/__init__.py +0 -0
- scaler/client/agent/__init__.py +0 -0
- scaler/client/agent/client_agent.py +218 -0
- scaler/client/agent/disconnect_manager.py +27 -0
- scaler/client/agent/future_manager.py +112 -0
- scaler/client/agent/heartbeat_manager.py +74 -0
- scaler/client/agent/mixins.py +89 -0
- scaler/client/agent/object_manager.py +98 -0
- scaler/client/agent/task_manager.py +64 -0
- scaler/client/client.py +672 -0
- scaler/client/future.py +252 -0
- scaler/client/object_buffer.py +129 -0
- scaler/client/object_reference.py +25 -0
- scaler/client/serializer/__init__.py +0 -0
- scaler/client/serializer/default.py +16 -0
- scaler/client/serializer/mixins.py +38 -0
- scaler/cluster/__init__.py +0 -0
- scaler/cluster/cluster.py +95 -0
- scaler/cluster/combo.py +157 -0
- scaler/cluster/object_storage_server.py +45 -0
- scaler/cluster/scheduler.py +86 -0
- scaler/config/__init__.py +0 -0
- scaler/config/common/__init__.py +0 -0
- scaler/config/common/logging.py +41 -0
- scaler/config/common/web.py +18 -0
- scaler/config/common/worker.py +65 -0
- scaler/config/common/worker_adapter.py +28 -0
- scaler/config/config_class.py +317 -0
- scaler/config/defaults.py +94 -0
- scaler/config/mixins.py +20 -0
- scaler/config/section/__init__.py +0 -0
- scaler/config/section/cluster.py +66 -0
- scaler/config/section/ecs_worker_adapter.py +78 -0
- scaler/config/section/native_worker_adapter.py +30 -0
- scaler/config/section/object_storage_server.py +13 -0
- scaler/config/section/scheduler.py +126 -0
- scaler/config/section/symphony_worker_adapter.py +35 -0
- scaler/config/section/top.py +16 -0
- scaler/config/section/webui.py +16 -0
- scaler/config/types/__init__.py +0 -0
- scaler/config/types/network_backend.py +12 -0
- scaler/config/types/object_storage_server.py +45 -0
- scaler/config/types/worker.py +67 -0
- scaler/config/types/zmq.py +83 -0
- scaler/entry_points/__init__.py +0 -0
- scaler/entry_points/cluster.py +10 -0
- scaler/entry_points/object_storage_server.py +26 -0
- scaler/entry_points/scheduler.py +51 -0
- scaler/entry_points/top.py +272 -0
- scaler/entry_points/webui.py +6 -0
- scaler/entry_points/worker_adapter_ecs.py +22 -0
- scaler/entry_points/worker_adapter_native.py +31 -0
- scaler/entry_points/worker_adapter_symphony.py +26 -0
- scaler/io/__init__.py +0 -0
- scaler/io/async_binder.py +89 -0
- scaler/io/async_connector.py +95 -0
- scaler/io/async_object_storage_connector.py +225 -0
- scaler/io/mixins.py +154 -0
- scaler/io/sync_connector.py +68 -0
- scaler/io/sync_object_storage_connector.py +249 -0
- scaler/io/sync_subscriber.py +83 -0
- scaler/io/utility.py +80 -0
- scaler/io/ymq/__init__.py +0 -0
- scaler/io/ymq/_ymq.pyi +95 -0
- scaler/io/ymq/_ymq.so +0 -0
- scaler/io/ymq/ymq.py +138 -0
- scaler/io/ymq_async_object_storage_connector.py +184 -0
- scaler/io/ymq_sync_object_storage_connector.py +184 -0
- scaler/object_storage/__init__.py +0 -0
- scaler/object_storage/object_storage_server.so +0 -0
- scaler/protocol/__init__.py +0 -0
- scaler/protocol/capnp/__init__.py +0 -0
- scaler/protocol/capnp/_python.py +6 -0
- scaler/protocol/capnp/common.capnp +68 -0
- scaler/protocol/capnp/message.capnp +218 -0
- scaler/protocol/capnp/object_storage.capnp +57 -0
- scaler/protocol/capnp/status.capnp +73 -0
- scaler/protocol/introduction.md +105 -0
- scaler/protocol/python/__init__.py +0 -0
- scaler/protocol/python/common.py +140 -0
- scaler/protocol/python/message.py +751 -0
- scaler/protocol/python/mixins.py +13 -0
- scaler/protocol/python/object_storage.py +118 -0
- scaler/protocol/python/status.py +279 -0
- scaler/protocol/worker.md +228 -0
- scaler/scheduler/__init__.py +0 -0
- scaler/scheduler/allocate_policy/__init__.py +0 -0
- scaler/scheduler/allocate_policy/allocate_policy.py +9 -0
- scaler/scheduler/allocate_policy/capability_allocate_policy.py +280 -0
- scaler/scheduler/allocate_policy/even_load_allocate_policy.py +159 -0
- scaler/scheduler/allocate_policy/mixins.py +55 -0
- scaler/scheduler/controllers/__init__.py +0 -0
- scaler/scheduler/controllers/balance_controller.py +65 -0
- scaler/scheduler/controllers/client_controller.py +131 -0
- scaler/scheduler/controllers/config_controller.py +31 -0
- scaler/scheduler/controllers/graph_controller.py +424 -0
- scaler/scheduler/controllers/information_controller.py +81 -0
- scaler/scheduler/controllers/mixins.py +194 -0
- scaler/scheduler/controllers/object_controller.py +147 -0
- scaler/scheduler/controllers/scaling_policies/__init__.py +0 -0
- scaler/scheduler/controllers/scaling_policies/fixed_elastic.py +145 -0
- scaler/scheduler/controllers/scaling_policies/mixins.py +10 -0
- scaler/scheduler/controllers/scaling_policies/null.py +14 -0
- scaler/scheduler/controllers/scaling_policies/types.py +9 -0
- scaler/scheduler/controllers/scaling_policies/utility.py +20 -0
- scaler/scheduler/controllers/scaling_policies/vanilla.py +95 -0
- scaler/scheduler/controllers/task_controller.py +376 -0
- scaler/scheduler/controllers/worker_controller.py +169 -0
- scaler/scheduler/object_usage/__init__.py +0 -0
- scaler/scheduler/object_usage/object_tracker.py +131 -0
- scaler/scheduler/scheduler.py +251 -0
- scaler/scheduler/task/__init__.py +0 -0
- scaler/scheduler/task/task_state_machine.py +92 -0
- scaler/scheduler/task/task_state_manager.py +61 -0
- scaler/ui/__init__.py +0 -0
- scaler/ui/common/__init__.py +0 -0
- scaler/ui/common/constants.py +9 -0
- scaler/ui/common/live_display.py +147 -0
- scaler/ui/common/memory_window.py +146 -0
- scaler/ui/common/setting_page.py +40 -0
- scaler/ui/common/task_graph.py +840 -0
- scaler/ui/common/task_log.py +111 -0
- scaler/ui/common/utility.py +66 -0
- scaler/ui/common/webui.py +80 -0
- scaler/ui/common/worker_processors.py +104 -0
- scaler/ui/v1.py +76 -0
- scaler/ui/v2.py +102 -0
- scaler/ui/webui.py +21 -0
- scaler/utility/__init__.py +0 -0
- scaler/utility/debug.py +19 -0
- scaler/utility/event_list.py +63 -0
- scaler/utility/event_loop.py +58 -0
- scaler/utility/exceptions.py +42 -0
- scaler/utility/formatter.py +44 -0
- scaler/utility/graph/__init__.py +0 -0
- scaler/utility/graph/optimization.py +27 -0
- scaler/utility/graph/topological_sorter.py +11 -0
- scaler/utility/graph/topological_sorter_graphblas.py +174 -0
- scaler/utility/identifiers.py +107 -0
- scaler/utility/logging/__init__.py +0 -0
- scaler/utility/logging/decorators.py +25 -0
- scaler/utility/logging/scoped_logger.py +33 -0
- scaler/utility/logging/utility.py +183 -0
- scaler/utility/many_to_many_dict.py +123 -0
- scaler/utility/metadata/__init__.py +0 -0
- scaler/utility/metadata/profile_result.py +31 -0
- scaler/utility/metadata/task_flags.py +30 -0
- scaler/utility/mixins.py +13 -0
- scaler/utility/network_util.py +7 -0
- scaler/utility/one_to_many_dict.py +72 -0
- scaler/utility/queues/__init__.py +0 -0
- scaler/utility/queues/async_indexed_queue.py +37 -0
- scaler/utility/queues/async_priority_queue.py +70 -0
- scaler/utility/queues/async_sorted_priority_queue.py +45 -0
- scaler/utility/queues/indexed_queue.py +114 -0
- scaler/utility/serialization.py +9 -0
- scaler/version.txt +1 -0
- scaler/worker/__init__.py +0 -0
- scaler/worker/agent/__init__.py +0 -0
- scaler/worker/agent/heartbeat_manager.py +110 -0
- scaler/worker/agent/mixins.py +137 -0
- scaler/worker/agent/processor/__init__.py +0 -0
- scaler/worker/agent/processor/object_cache.py +107 -0
- scaler/worker/agent/processor/processor.py +285 -0
- scaler/worker/agent/processor/streaming_buffer.py +28 -0
- scaler/worker/agent/processor_holder.py +147 -0
- scaler/worker/agent/processor_manager.py +369 -0
- scaler/worker/agent/profiling_manager.py +109 -0
- scaler/worker/agent/task_manager.py +150 -0
- scaler/worker/agent/timeout_manager.py +19 -0
- scaler/worker/preload.py +84 -0
- scaler/worker/worker.py +265 -0
- scaler/worker_adapter/__init__.py +0 -0
- scaler/worker_adapter/common.py +26 -0
- scaler/worker_adapter/ecs.py +241 -0
- scaler/worker_adapter/native.py +138 -0
- scaler/worker_adapter/symphony/__init__.py +0 -0
- scaler/worker_adapter/symphony/callback.py +45 -0
- scaler/worker_adapter/symphony/heartbeat_manager.py +82 -0
- scaler/worker_adapter/symphony/message.py +24 -0
- scaler/worker_adapter/symphony/task_manager.py +289 -0
- scaler/worker_adapter/symphony/worker.py +204 -0
- scaler/worker_adapter/symphony/worker_adapter.py +123 -0
|
@@ -0,0 +1,751 @@
|
|
|
1
|
+
import dataclasses
|
|
2
|
+
import enum
|
|
3
|
+
from typing import Dict, List, Optional, Set, Type, Union
|
|
4
|
+
|
|
5
|
+
import bidict
|
|
6
|
+
|
|
7
|
+
from scaler.protocol.capnp._python import _message # noqa
|
|
8
|
+
from scaler.protocol.python.common import (
|
|
9
|
+
ObjectMetadata,
|
|
10
|
+
ObjectStorageAddress,
|
|
11
|
+
TaskCancelConfirmType,
|
|
12
|
+
TaskCapability,
|
|
13
|
+
TaskResultType,
|
|
14
|
+
TaskState,
|
|
15
|
+
WorkerState,
|
|
16
|
+
)
|
|
17
|
+
from scaler.protocol.python.mixins import Message
|
|
18
|
+
from scaler.protocol.python.status import (
|
|
19
|
+
BinderStatus,
|
|
20
|
+
ClientManagerStatus,
|
|
21
|
+
ObjectManagerStatus,
|
|
22
|
+
ProcessorStatus,
|
|
23
|
+
Resource,
|
|
24
|
+
ScalingManagerStatus,
|
|
25
|
+
TaskManagerStatus,
|
|
26
|
+
WorkerManagerStatus,
|
|
27
|
+
)
|
|
28
|
+
from scaler.utility.identifiers import ClientID, ObjectID, TaskID, WorkerID
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class Task(Message):
|
|
32
|
+
def __init__(self, msg):
|
|
33
|
+
super().__init__(msg)
|
|
34
|
+
|
|
35
|
+
def __repr__(self):
|
|
36
|
+
return (
|
|
37
|
+
f"Task(task_id={self.task_id!r}, source={self.source!r}, metadata={self.metadata.hex()},"
|
|
38
|
+
f"func_object_id={self.func_object_id!r}, function_args={self.function_args})"
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
@property
|
|
42
|
+
def task_id(self) -> TaskID:
|
|
43
|
+
return TaskID(self._msg.taskId)
|
|
44
|
+
|
|
45
|
+
@property
|
|
46
|
+
def source(self) -> ClientID:
|
|
47
|
+
return ClientID(self._msg.source)
|
|
48
|
+
|
|
49
|
+
@property
|
|
50
|
+
def metadata(self) -> bytes:
|
|
51
|
+
return self._msg.metadata
|
|
52
|
+
|
|
53
|
+
@property
|
|
54
|
+
def func_object_id(self) -> Optional[ObjectID]:
|
|
55
|
+
if len(self._msg.funcObjectId) > 0:
|
|
56
|
+
return ObjectID(self._msg.funcObjectId)
|
|
57
|
+
else:
|
|
58
|
+
return None
|
|
59
|
+
|
|
60
|
+
@property
|
|
61
|
+
def function_args(self) -> List[Union[ObjectID, TaskID]]:
|
|
62
|
+
return [self._from_capnp_task_argument(arg) for arg in self._msg.functionArgs]
|
|
63
|
+
|
|
64
|
+
@property
|
|
65
|
+
def capabilities(self) -> Dict[str, int]:
|
|
66
|
+
return {capability.name: capability.value for capability in self._msg.capabilities}
|
|
67
|
+
|
|
68
|
+
@staticmethod
|
|
69
|
+
def new_msg(
|
|
70
|
+
task_id: TaskID,
|
|
71
|
+
source: ClientID,
|
|
72
|
+
metadata: bytes,
|
|
73
|
+
func_object_id: Optional[ObjectID],
|
|
74
|
+
function_args: List[Union[ObjectID, TaskID]],
|
|
75
|
+
capabilities: Dict[str, int],
|
|
76
|
+
) -> "Task":
|
|
77
|
+
return Task(
|
|
78
|
+
_message.Task(
|
|
79
|
+
taskId=bytes(task_id),
|
|
80
|
+
source=bytes(source),
|
|
81
|
+
metadata=metadata,
|
|
82
|
+
funcObjectId=bytes(func_object_id) if func_object_id is not None else b"",
|
|
83
|
+
functionArgs=[Task._to_capnp_task_argument(arg) for arg in function_args],
|
|
84
|
+
capabilities=[
|
|
85
|
+
TaskCapability.new_msg(name, value).get_message() for name, value in capabilities.items()
|
|
86
|
+
],
|
|
87
|
+
)
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
@staticmethod
|
|
91
|
+
def _from_capnp_task_argument(value: _message.Task.Argument) -> Union[ObjectID, TaskID]:
|
|
92
|
+
if value.type.raw == _message.Task.Argument.ArgumentType.task:
|
|
93
|
+
return TaskID(value.data)
|
|
94
|
+
else:
|
|
95
|
+
assert value.type.raw == _message.Task.Argument.ArgumentType.objectID
|
|
96
|
+
return ObjectID(value.data)
|
|
97
|
+
|
|
98
|
+
@staticmethod
|
|
99
|
+
def _to_capnp_task_argument(value: Union[ObjectID, TaskID]) -> _message.Task.Argument:
|
|
100
|
+
if isinstance(value, TaskID):
|
|
101
|
+
return _message.Task.Argument(type=_message.Task.Argument.ArgumentType.task, data=bytes(value))
|
|
102
|
+
else:
|
|
103
|
+
assert isinstance(value, ObjectID)
|
|
104
|
+
return _message.Task.Argument(type=_message.Task.Argument.ArgumentType.objectID, data=bytes(value))
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
class TaskCancel(Message):
|
|
108
|
+
def __init__(self, msg):
|
|
109
|
+
super().__init__(msg)
|
|
110
|
+
|
|
111
|
+
@dataclasses.dataclass
|
|
112
|
+
class TaskCancelFlags:
|
|
113
|
+
force: bool
|
|
114
|
+
|
|
115
|
+
@property
|
|
116
|
+
def task_id(self) -> TaskID:
|
|
117
|
+
return TaskID(self._msg.taskId)
|
|
118
|
+
|
|
119
|
+
@property
|
|
120
|
+
def flags(self) -> TaskCancelFlags:
|
|
121
|
+
return TaskCancel.TaskCancelFlags(force=self._msg.flags.force)
|
|
122
|
+
|
|
123
|
+
@staticmethod
|
|
124
|
+
def new_msg(task_id: TaskID, flags: Optional[TaskCancelFlags] = None) -> "TaskCancel":
|
|
125
|
+
if flags is None:
|
|
126
|
+
flags = TaskCancel.TaskCancelFlags(force=False)
|
|
127
|
+
|
|
128
|
+
return TaskCancel(
|
|
129
|
+
_message.TaskCancel(taskId=bytes(task_id), flags=_message.TaskCancel.TaskCancelFlags(force=flags.force))
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
class TaskLog(Message):
|
|
134
|
+
class LogType(enum.Enum):
|
|
135
|
+
Stdout = _message.TaskLog.LogType.stdout
|
|
136
|
+
Stderr = _message.TaskLog.LogType.stderr
|
|
137
|
+
|
|
138
|
+
def __init__(self, msg):
|
|
139
|
+
super().__init__(msg)
|
|
140
|
+
|
|
141
|
+
@property
|
|
142
|
+
def task_id(self) -> TaskID:
|
|
143
|
+
return TaskID(self._msg.taskId)
|
|
144
|
+
|
|
145
|
+
@property
|
|
146
|
+
def log_type(self) -> "TaskLog.LogType":
|
|
147
|
+
return TaskLog.LogType(self._msg.logType.raw)
|
|
148
|
+
|
|
149
|
+
@property
|
|
150
|
+
def content(self) -> str:
|
|
151
|
+
return self._msg.content
|
|
152
|
+
|
|
153
|
+
@staticmethod
|
|
154
|
+
def new_msg(task_id: TaskID, log_type: "TaskLog.LogType", content: str) -> "TaskLog":
|
|
155
|
+
return TaskLog(_message.TaskLog(taskId=bytes(task_id), logType=log_type.value, content=content))
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
class TaskResult(Message):
|
|
159
|
+
def __init__(self, msg):
|
|
160
|
+
super().__init__(msg)
|
|
161
|
+
|
|
162
|
+
@property
|
|
163
|
+
def task_id(self) -> TaskID:
|
|
164
|
+
return TaskID(self._msg.taskId)
|
|
165
|
+
|
|
166
|
+
@property
|
|
167
|
+
def result_type(self) -> TaskResultType:
|
|
168
|
+
return TaskResultType(self._msg.resultType.raw)
|
|
169
|
+
|
|
170
|
+
@property
|
|
171
|
+
def metadata(self) -> bytes:
|
|
172
|
+
return self._msg.metadata
|
|
173
|
+
|
|
174
|
+
@property
|
|
175
|
+
def results(self) -> List[bytes]:
|
|
176
|
+
return self._msg.results
|
|
177
|
+
|
|
178
|
+
@staticmethod
|
|
179
|
+
def new_msg(
|
|
180
|
+
task_id: TaskID,
|
|
181
|
+
result_type: TaskResultType,
|
|
182
|
+
metadata: Optional[bytes] = None,
|
|
183
|
+
results: Optional[List[bytes]] = None,
|
|
184
|
+
) -> "TaskResult":
|
|
185
|
+
if metadata is None:
|
|
186
|
+
metadata = bytes()
|
|
187
|
+
|
|
188
|
+
if results is None:
|
|
189
|
+
results = list()
|
|
190
|
+
|
|
191
|
+
return TaskResult(
|
|
192
|
+
_message.TaskResult(taskId=bytes(task_id), resultType=result_type.value, metadata=metadata, results=results)
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
class TaskCancelConfirm(Message):
|
|
197
|
+
def __init__(self, msg):
|
|
198
|
+
super().__init__(msg)
|
|
199
|
+
|
|
200
|
+
@property
|
|
201
|
+
def task_id(self) -> TaskID:
|
|
202
|
+
return TaskID(self._msg.taskId)
|
|
203
|
+
|
|
204
|
+
@property
|
|
205
|
+
def cancel_confirm_type(self) -> TaskCancelConfirmType:
|
|
206
|
+
return TaskCancelConfirmType(self._msg.cancelConfirmType.raw)
|
|
207
|
+
|
|
208
|
+
@staticmethod
|
|
209
|
+
def new_msg(task_id: TaskID, cancel_confirm_type: TaskCancelConfirmType) -> "TaskCancelConfirm":
|
|
210
|
+
return TaskCancelConfirm(
|
|
211
|
+
_message.TaskCancelConfirm(taskId=bytes(task_id), cancelConfirmType=cancel_confirm_type.value)
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
class GraphTask(Message):
|
|
216
|
+
def __init__(self, msg):
|
|
217
|
+
super().__init__(msg)
|
|
218
|
+
|
|
219
|
+
def __repr__(self):
|
|
220
|
+
return (
|
|
221
|
+
f"GraphTask(\n"
|
|
222
|
+
f" task_id={self.task_id!r},\n"
|
|
223
|
+
f" targets=[\n"
|
|
224
|
+
f" {', '.join(repr(target) for target in self.targets)}\n"
|
|
225
|
+
f" ]\n"
|
|
226
|
+
f" graph={self.graph!r}\n"
|
|
227
|
+
f")"
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
@property
|
|
231
|
+
def task_id(self) -> TaskID:
|
|
232
|
+
return TaskID(self._msg.taskId)
|
|
233
|
+
|
|
234
|
+
@property
|
|
235
|
+
def source(self) -> ClientID:
|
|
236
|
+
return ClientID(self._msg.source)
|
|
237
|
+
|
|
238
|
+
@property
|
|
239
|
+
def targets(self) -> List[TaskID]:
|
|
240
|
+
return [TaskID(target) for target in self._msg.targets]
|
|
241
|
+
|
|
242
|
+
@property
|
|
243
|
+
def graph(self) -> List[Task]:
|
|
244
|
+
return [Task(task) for task in self._msg.graph]
|
|
245
|
+
|
|
246
|
+
@staticmethod
|
|
247
|
+
def new_msg(task_id: TaskID, source: ClientID, targets: List[TaskID], graph: List[Task]) -> "GraphTask":
|
|
248
|
+
return GraphTask(
|
|
249
|
+
_message.GraphTask(
|
|
250
|
+
taskId=bytes(task_id),
|
|
251
|
+
source=bytes(source),
|
|
252
|
+
targets=[bytes(target) for target in targets],
|
|
253
|
+
graph=[task.get_message() for task in graph],
|
|
254
|
+
)
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
class ClientHeartbeat(Message):
|
|
259
|
+
def __init__(self, msg):
|
|
260
|
+
super().__init__(msg)
|
|
261
|
+
|
|
262
|
+
@property
|
|
263
|
+
def resource(self) -> Resource:
|
|
264
|
+
return Resource(self._msg.resource)
|
|
265
|
+
|
|
266
|
+
@property
|
|
267
|
+
def latency_us(self) -> int:
|
|
268
|
+
return self._msg.latencyUS
|
|
269
|
+
|
|
270
|
+
@staticmethod
|
|
271
|
+
def new_msg(resource: Resource, latency_us: int) -> "ClientHeartbeat":
|
|
272
|
+
return ClientHeartbeat(_message.ClientHeartbeat(resource=resource.get_message(), latencyUS=latency_us))
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
class ClientHeartbeatEcho(Message):
|
|
276
|
+
def __init__(self, msg):
|
|
277
|
+
super().__init__(msg)
|
|
278
|
+
|
|
279
|
+
def object_storage_address(self) -> ObjectStorageAddress:
|
|
280
|
+
return ObjectStorageAddress(self._msg.objectStorageAddress)
|
|
281
|
+
|
|
282
|
+
@staticmethod
|
|
283
|
+
def new_msg(object_storage_address: ObjectStorageAddress) -> "ClientHeartbeatEcho":
|
|
284
|
+
return ClientHeartbeatEcho(
|
|
285
|
+
_message.ClientHeartbeatEcho(objectStorageAddress=object_storage_address.get_message())
|
|
286
|
+
)
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
class WorkerHeartbeat(Message):
|
|
290
|
+
def __init__(self, msg):
|
|
291
|
+
super().__init__(msg)
|
|
292
|
+
|
|
293
|
+
@property
|
|
294
|
+
def agent(self) -> Resource:
|
|
295
|
+
return Resource(self._msg.agent)
|
|
296
|
+
|
|
297
|
+
@property
|
|
298
|
+
def rss_free(self) -> int:
|
|
299
|
+
return self._msg.rssFree
|
|
300
|
+
|
|
301
|
+
@property
|
|
302
|
+
def queue_size(self) -> int:
|
|
303
|
+
return self._msg.queueSize
|
|
304
|
+
|
|
305
|
+
@property
|
|
306
|
+
def queued_tasks(self) -> int:
|
|
307
|
+
return self._msg.queuedTasks
|
|
308
|
+
|
|
309
|
+
@property
|
|
310
|
+
def latency_us(self) -> int:
|
|
311
|
+
return self._msg.latencyUS
|
|
312
|
+
|
|
313
|
+
@property
|
|
314
|
+
def task_lock(self) -> bool:
|
|
315
|
+
return self._msg.taskLock
|
|
316
|
+
|
|
317
|
+
@property
|
|
318
|
+
def processors(self) -> List[ProcessorStatus]:
|
|
319
|
+
return [ProcessorStatus(p) for p in self._msg.processors]
|
|
320
|
+
|
|
321
|
+
@property
|
|
322
|
+
def capabilities(self) -> Dict[str, int]:
|
|
323
|
+
return {capability.name: capability.value for capability in self._msg.capabilities}
|
|
324
|
+
|
|
325
|
+
@staticmethod
|
|
326
|
+
def new_msg(
|
|
327
|
+
agent: Resource,
|
|
328
|
+
rss_free: int,
|
|
329
|
+
queue_size: int,
|
|
330
|
+
queued_tasks: int,
|
|
331
|
+
latency_us: int,
|
|
332
|
+
task_lock: bool,
|
|
333
|
+
processors: List[ProcessorStatus],
|
|
334
|
+
capabilities: Dict[str, int],
|
|
335
|
+
) -> "WorkerHeartbeat":
|
|
336
|
+
return WorkerHeartbeat(
|
|
337
|
+
_message.WorkerHeartbeat(
|
|
338
|
+
agent=agent.get_message(),
|
|
339
|
+
rssFree=rss_free,
|
|
340
|
+
queueSize=queue_size,
|
|
341
|
+
queuedTasks=queued_tasks,
|
|
342
|
+
latencyUS=latency_us,
|
|
343
|
+
taskLock=task_lock,
|
|
344
|
+
processors=[p.get_message() for p in processors],
|
|
345
|
+
capabilities=[
|
|
346
|
+
TaskCapability.new_msg(name, value).get_message() for name, value in capabilities.items()
|
|
347
|
+
],
|
|
348
|
+
)
|
|
349
|
+
)
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
class WorkerHeartbeatEcho(Message):
|
|
353
|
+
def __init__(self, msg):
|
|
354
|
+
super().__init__(msg)
|
|
355
|
+
|
|
356
|
+
def object_storage_address(self) -> ObjectStorageAddress:
|
|
357
|
+
return ObjectStorageAddress(self._msg.objectStorageAddress)
|
|
358
|
+
|
|
359
|
+
@staticmethod
|
|
360
|
+
def new_msg(object_storage_address: ObjectStorageAddress) -> "WorkerHeartbeatEcho":
|
|
361
|
+
return WorkerHeartbeatEcho(
|
|
362
|
+
_message.WorkerHeartbeatEcho(objectStorageAddress=object_storage_address.get_message())
|
|
363
|
+
)
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
class ObjectInstruction(Message):
|
|
367
|
+
class ObjectInstructionType(enum.Enum):
|
|
368
|
+
Create = _message.ObjectInstruction.ObjectInstructionType.create
|
|
369
|
+
Delete = _message.ObjectInstruction.ObjectInstructionType.delete
|
|
370
|
+
Clear = _message.ObjectInstruction.ObjectInstructionType.clear
|
|
371
|
+
|
|
372
|
+
def __init__(self, msg):
|
|
373
|
+
super().__init__(msg)
|
|
374
|
+
|
|
375
|
+
@property
|
|
376
|
+
def instruction_type(self) -> ObjectInstructionType:
|
|
377
|
+
return ObjectInstruction.ObjectInstructionType(self._msg.instructionType.raw)
|
|
378
|
+
|
|
379
|
+
@property
|
|
380
|
+
def object_user(self) -> Optional[ClientID]:
|
|
381
|
+
return ClientID(self._msg.objectUser) if len(self._msg.objectUser) > 0 else None
|
|
382
|
+
|
|
383
|
+
@property
|
|
384
|
+
def object_metadata(self) -> ObjectMetadata:
|
|
385
|
+
return ObjectMetadata(self._msg.objectMetadata)
|
|
386
|
+
|
|
387
|
+
@staticmethod
|
|
388
|
+
def new_msg(
|
|
389
|
+
instruction_type: ObjectInstructionType, object_user: Optional[ClientID], object_metadata: ObjectMetadata
|
|
390
|
+
) -> "ObjectInstruction":
|
|
391
|
+
return ObjectInstruction(
|
|
392
|
+
_message.ObjectInstruction(
|
|
393
|
+
instructionType=instruction_type.value,
|
|
394
|
+
objectUser=bytes(object_user) if object_user is not None else b"",
|
|
395
|
+
objectMetadata=object_metadata.get_message(),
|
|
396
|
+
)
|
|
397
|
+
)
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
class DisconnectRequest(Message):
|
|
401
|
+
def __init__(self, msg):
|
|
402
|
+
super().__init__(msg)
|
|
403
|
+
|
|
404
|
+
@property
|
|
405
|
+
def worker(self) -> WorkerID:
|
|
406
|
+
return WorkerID(self._msg.worker)
|
|
407
|
+
|
|
408
|
+
@staticmethod
|
|
409
|
+
def new_msg(worker: WorkerID) -> "DisconnectRequest":
|
|
410
|
+
return DisconnectRequest(_message.DisconnectRequest(worker=bytes(worker)))
|
|
411
|
+
|
|
412
|
+
|
|
413
|
+
@dataclasses.dataclass
|
|
414
|
+
class DisconnectResponse(Message):
|
|
415
|
+
def __init__(self, msg):
|
|
416
|
+
super().__init__(msg)
|
|
417
|
+
|
|
418
|
+
@property
|
|
419
|
+
def worker(self) -> WorkerID:
|
|
420
|
+
return WorkerID(self._msg.worker)
|
|
421
|
+
|
|
422
|
+
@staticmethod
|
|
423
|
+
def new_msg(worker: WorkerID) -> "DisconnectResponse":
|
|
424
|
+
return DisconnectResponse(_message.DisconnectResponse(worker=bytes(worker)))
|
|
425
|
+
|
|
426
|
+
|
|
427
|
+
class ClientDisconnect(Message):
|
|
428
|
+
class DisconnectType(enum.Enum):
|
|
429
|
+
Disconnect = _message.ClientDisconnect.DisconnectType.disconnect
|
|
430
|
+
Shutdown = _message.ClientDisconnect.DisconnectType.shutdown
|
|
431
|
+
|
|
432
|
+
def __init__(self, msg):
|
|
433
|
+
super().__init__(msg)
|
|
434
|
+
|
|
435
|
+
@property
|
|
436
|
+
def disconnect_type(self) -> DisconnectType:
|
|
437
|
+
return ClientDisconnect.DisconnectType(self._msg.disconnectType.raw)
|
|
438
|
+
|
|
439
|
+
@staticmethod
|
|
440
|
+
def new_msg(disconnect_type: DisconnectType) -> "ClientDisconnect":
|
|
441
|
+
return ClientDisconnect(_message.ClientDisconnect(disconnectType=disconnect_type.value))
|
|
442
|
+
|
|
443
|
+
|
|
444
|
+
class ClientShutdownResponse(Message):
|
|
445
|
+
def __init__(self, msg):
|
|
446
|
+
super().__init__(msg)
|
|
447
|
+
|
|
448
|
+
@property
|
|
449
|
+
def accepted(self) -> bool:
|
|
450
|
+
return self._msg.accepted
|
|
451
|
+
|
|
452
|
+
@staticmethod
|
|
453
|
+
def new_msg(accepted: bool) -> "ClientShutdownResponse":
|
|
454
|
+
return ClientShutdownResponse(_message.ClientShutdownResponse(accepted=accepted))
|
|
455
|
+
|
|
456
|
+
|
|
457
|
+
class StateClient(Message):
|
|
458
|
+
def __init__(self, msg):
|
|
459
|
+
super().__init__(msg)
|
|
460
|
+
|
|
461
|
+
@staticmethod
|
|
462
|
+
def new_msg() -> "StateClient":
|
|
463
|
+
return StateClient(_message.StateClient())
|
|
464
|
+
|
|
465
|
+
|
|
466
|
+
class StateObject(Message):
|
|
467
|
+
def __init__(self, msg):
|
|
468
|
+
super().__init__(msg)
|
|
469
|
+
|
|
470
|
+
@staticmethod
|
|
471
|
+
def new_msg() -> "StateObject":
|
|
472
|
+
return StateObject(_message.StateObject())
|
|
473
|
+
|
|
474
|
+
|
|
475
|
+
class StateBalanceAdvice(Message):
|
|
476
|
+
def __init__(self, msg):
|
|
477
|
+
super().__init__(msg)
|
|
478
|
+
|
|
479
|
+
@property
|
|
480
|
+
def worker_id(self) -> WorkerID:
|
|
481
|
+
return WorkerID(self._msg.workerId)
|
|
482
|
+
|
|
483
|
+
@property
|
|
484
|
+
def task_ids(self) -> List[TaskID]:
|
|
485
|
+
return [TaskID(task_id) for task_id in self._msg.taskIds]
|
|
486
|
+
|
|
487
|
+
@staticmethod
|
|
488
|
+
def new_msg(worker_id: WorkerID, task_ids: List[TaskID]) -> "StateBalanceAdvice":
|
|
489
|
+
return StateBalanceAdvice(
|
|
490
|
+
_message.StateBalanceAdvice(workerId=bytes(worker_id), taskIds=[bytes(task_id) for task_id in task_ids])
|
|
491
|
+
)
|
|
492
|
+
|
|
493
|
+
|
|
494
|
+
class StateScheduler(Message):
|
|
495
|
+
def __init__(self, msg):
|
|
496
|
+
super().__init__(msg)
|
|
497
|
+
|
|
498
|
+
@property
|
|
499
|
+
def binder(self) -> BinderStatus:
|
|
500
|
+
return BinderStatus(self._msg.binder)
|
|
501
|
+
|
|
502
|
+
@property
|
|
503
|
+
def scheduler(self) -> Resource:
|
|
504
|
+
return Resource(self._msg.scheduler)
|
|
505
|
+
|
|
506
|
+
@property
|
|
507
|
+
def rss_free(self) -> int:
|
|
508
|
+
return self._msg.rssFree
|
|
509
|
+
|
|
510
|
+
@property
|
|
511
|
+
def client_manager(self) -> ClientManagerStatus:
|
|
512
|
+
return ClientManagerStatus(self._msg.clientManager)
|
|
513
|
+
|
|
514
|
+
@property
|
|
515
|
+
def object_manager(self) -> ObjectManagerStatus:
|
|
516
|
+
return ObjectManagerStatus(self._msg.objectManager)
|
|
517
|
+
|
|
518
|
+
@property
|
|
519
|
+
def task_manager(self) -> TaskManagerStatus:
|
|
520
|
+
return TaskManagerStatus(self._msg.taskManager)
|
|
521
|
+
|
|
522
|
+
@property
|
|
523
|
+
def worker_manager(self) -> WorkerManagerStatus:
|
|
524
|
+
return WorkerManagerStatus(self._msg.workerManager)
|
|
525
|
+
|
|
526
|
+
@property
|
|
527
|
+
def scaling_manager(self) -> ScalingManagerStatus:
|
|
528
|
+
return ScalingManagerStatus(self._msg.scalingManager)
|
|
529
|
+
|
|
530
|
+
@staticmethod
|
|
531
|
+
def new_msg(
|
|
532
|
+
binder: BinderStatus,
|
|
533
|
+
scheduler: Resource,
|
|
534
|
+
rss_free: int,
|
|
535
|
+
client_manager: ClientManagerStatus,
|
|
536
|
+
object_manager: ObjectManagerStatus,
|
|
537
|
+
task_manager: TaskManagerStatus,
|
|
538
|
+
worker_manager: WorkerManagerStatus,
|
|
539
|
+
scaling_manager: ScalingManagerStatus,
|
|
540
|
+
) -> "StateScheduler":
|
|
541
|
+
return StateScheduler(
|
|
542
|
+
_message.StateScheduler(
|
|
543
|
+
binder=binder.get_message(),
|
|
544
|
+
scheduler=scheduler.get_message(),
|
|
545
|
+
rssFree=rss_free,
|
|
546
|
+
clientManager=client_manager.get_message(),
|
|
547
|
+
objectManager=object_manager.get_message(),
|
|
548
|
+
taskManager=task_manager.get_message(),
|
|
549
|
+
workerManager=worker_manager.get_message(),
|
|
550
|
+
scalingManager=scaling_manager.get_message(),
|
|
551
|
+
)
|
|
552
|
+
)
|
|
553
|
+
|
|
554
|
+
|
|
555
|
+
class StateWorker(Message):
|
|
556
|
+
def __init__(self, msg):
|
|
557
|
+
super().__init__(msg)
|
|
558
|
+
|
|
559
|
+
@property
|
|
560
|
+
def worker_id(self) -> WorkerID:
|
|
561
|
+
return WorkerID(self._msg.workerId)
|
|
562
|
+
|
|
563
|
+
@property
|
|
564
|
+
def state(self) -> WorkerState:
|
|
565
|
+
return WorkerState(self._msg.state.raw)
|
|
566
|
+
|
|
567
|
+
@property
|
|
568
|
+
def capabilities(self) -> Dict[str, int]:
|
|
569
|
+
return {capability.name: capability.value for capability in self._msg.capabilities}
|
|
570
|
+
|
|
571
|
+
@staticmethod
|
|
572
|
+
def new_msg(worker_id: WorkerID, state: WorkerState, capabilities: Dict[str, int]) -> "StateWorker":
|
|
573
|
+
return StateWorker(
|
|
574
|
+
_message.StateWorker(
|
|
575
|
+
workerId=bytes(worker_id),
|
|
576
|
+
state=state.value,
|
|
577
|
+
capabilities=[
|
|
578
|
+
TaskCapability.new_msg(name, value).get_message() for name, value in capabilities.items()
|
|
579
|
+
],
|
|
580
|
+
)
|
|
581
|
+
)
|
|
582
|
+
|
|
583
|
+
|
|
584
|
+
class StateTask(Message):
|
|
585
|
+
def __init__(self, msg):
|
|
586
|
+
super().__init__(msg)
|
|
587
|
+
|
|
588
|
+
@property
|
|
589
|
+
def task_id(self) -> TaskID:
|
|
590
|
+
return TaskID(self._msg.taskId)
|
|
591
|
+
|
|
592
|
+
@property
|
|
593
|
+
def function_name(self) -> bytes:
|
|
594
|
+
return self._msg.functionName
|
|
595
|
+
|
|
596
|
+
@property
|
|
597
|
+
def state(self) -> TaskState:
|
|
598
|
+
return TaskState(self._msg.state.raw)
|
|
599
|
+
|
|
600
|
+
@property
|
|
601
|
+
def worker(self) -> WorkerID:
|
|
602
|
+
return WorkerID(self._msg.worker)
|
|
603
|
+
|
|
604
|
+
@property
|
|
605
|
+
def capabilities(self) -> Dict[str, int]:
|
|
606
|
+
return {capability.name: capability.value for capability in self._msg.capabilities}
|
|
607
|
+
|
|
608
|
+
@property
|
|
609
|
+
def metadata(self) -> bytes:
|
|
610
|
+
return self._msg.metadata
|
|
611
|
+
|
|
612
|
+
@staticmethod
|
|
613
|
+
def new_msg(
|
|
614
|
+
task_id: TaskID,
|
|
615
|
+
function_name: bytes,
|
|
616
|
+
task_state: TaskState,
|
|
617
|
+
worker: WorkerID,
|
|
618
|
+
capabilities: Dict[str, int],
|
|
619
|
+
metadata: bytes = b"",
|
|
620
|
+
) -> "StateTask":
|
|
621
|
+
return StateTask(
|
|
622
|
+
_message.StateTask(
|
|
623
|
+
taskId=bytes(task_id),
|
|
624
|
+
functionName=function_name,
|
|
625
|
+
state=task_state.value,
|
|
626
|
+
worker=bytes(worker),
|
|
627
|
+
capabilities=[
|
|
628
|
+
TaskCapability.new_msg(name, value).get_message() for name, value in capabilities.items()
|
|
629
|
+
],
|
|
630
|
+
metadata=metadata,
|
|
631
|
+
)
|
|
632
|
+
)
|
|
633
|
+
|
|
634
|
+
|
|
635
|
+
class StateGraphTask(Message):
|
|
636
|
+
class NodeTaskType(enum.Enum):
|
|
637
|
+
Normal = _message.StateGraphTask.NodeTaskType.normal
|
|
638
|
+
Target = _message.StateGraphTask.NodeTaskType.target
|
|
639
|
+
|
|
640
|
+
def __init__(self, msg):
|
|
641
|
+
super().__init__(msg)
|
|
642
|
+
|
|
643
|
+
@property
|
|
644
|
+
def graph_task_id(self) -> TaskID:
|
|
645
|
+
return self._msg.graphTaskId
|
|
646
|
+
|
|
647
|
+
@property
|
|
648
|
+
def task_id(self) -> TaskID:
|
|
649
|
+
return self._msg.taskId
|
|
650
|
+
|
|
651
|
+
@property
|
|
652
|
+
def node_task_type(self) -> NodeTaskType:
|
|
653
|
+
return StateGraphTask.NodeTaskType(self._msg.nodeTaskType.raw)
|
|
654
|
+
|
|
655
|
+
@property
|
|
656
|
+
def parent_task_ids(self) -> Set[TaskID]:
|
|
657
|
+
return {TaskID(parent_task_id) for parent_task_id in self._msg.parentTaskIds}
|
|
658
|
+
|
|
659
|
+
@staticmethod
|
|
660
|
+
def new_msg(
|
|
661
|
+
graph_task_id: TaskID, task_id: TaskID, node_task_type: NodeTaskType, parent_task_ids: Set[TaskID]
|
|
662
|
+
) -> "StateGraphTask":
|
|
663
|
+
return StateGraphTask(
|
|
664
|
+
_message.StateGraphTask(
|
|
665
|
+
graphTaskId=bytes(graph_task_id),
|
|
666
|
+
taskId=bytes(task_id),
|
|
667
|
+
nodeTaskType=node_task_type.value,
|
|
668
|
+
parentTaskIds=[bytes(parent_task_id) for parent_task_id in parent_task_ids],
|
|
669
|
+
)
|
|
670
|
+
)
|
|
671
|
+
|
|
672
|
+
|
|
673
|
+
class ProcessorInitialized(Message):
|
|
674
|
+
def __init__(self, msg):
|
|
675
|
+
super().__init__(msg)
|
|
676
|
+
|
|
677
|
+
@staticmethod
|
|
678
|
+
def new_msg() -> "ProcessorInitialized":
|
|
679
|
+
return ProcessorInitialized(_message.ProcessorInitialized())
|
|
680
|
+
|
|
681
|
+
|
|
682
|
+
class InformationRequest(Message):
|
|
683
|
+
def __init__(self, msg):
|
|
684
|
+
super().__init__(msg)
|
|
685
|
+
|
|
686
|
+
@property
|
|
687
|
+
def request(self) -> bytes:
|
|
688
|
+
return self._msg.request
|
|
689
|
+
|
|
690
|
+
@staticmethod
|
|
691
|
+
def new_msg(request: bytes) -> "InformationRequest":
|
|
692
|
+
return InformationRequest(_message.InformationRequest(request=request))
|
|
693
|
+
|
|
694
|
+
|
|
695
|
+
class InformationResponse(Message):
|
|
696
|
+
def __init__(self, msg):
|
|
697
|
+
super().__init__(msg)
|
|
698
|
+
|
|
699
|
+
@property
|
|
700
|
+
def response(self) -> bytes:
|
|
701
|
+
return self._msg.response
|
|
702
|
+
|
|
703
|
+
@staticmethod
|
|
704
|
+
def new_msg(response: bytes) -> "InformationResponse":
|
|
705
|
+
return InformationResponse(_message.InformationResponse(response=response))
|
|
706
|
+
|
|
707
|
+
|
|
708
|
+
# NOTE: This class is not a Message and does not have serialization methods. This is intentional.
|
|
709
|
+
class InformationSnapshot:
|
|
710
|
+
def __init__(self, tasks: Dict[TaskID, Task], workers: Dict[WorkerID, WorkerHeartbeat]):
|
|
711
|
+
self._tasks = tasks
|
|
712
|
+
self._workers = workers
|
|
713
|
+
|
|
714
|
+
@property
|
|
715
|
+
def tasks(self) -> Dict[TaskID, Task]:
|
|
716
|
+
return self._tasks
|
|
717
|
+
|
|
718
|
+
@property
|
|
719
|
+
def workers(self) -> Dict[WorkerID, WorkerHeartbeat]:
|
|
720
|
+
return self._workers
|
|
721
|
+
|
|
722
|
+
|
|
723
|
+
PROTOCOL: bidict.bidict[str, Type[Message]] = bidict.bidict(
|
|
724
|
+
{
|
|
725
|
+
"task": Task,
|
|
726
|
+
"taskCancel": TaskCancel,
|
|
727
|
+
"taskCancelConfirm": TaskCancelConfirm,
|
|
728
|
+
"taskResult": TaskResult,
|
|
729
|
+
"taskLog": TaskLog,
|
|
730
|
+
"graphTask": GraphTask,
|
|
731
|
+
"objectInstruction": ObjectInstruction,
|
|
732
|
+
"clientHeartbeat": ClientHeartbeat,
|
|
733
|
+
"clientHeartbeatEcho": ClientHeartbeatEcho,
|
|
734
|
+
"workerHeartbeat": WorkerHeartbeat,
|
|
735
|
+
"workerHeartbeatEcho": WorkerHeartbeatEcho,
|
|
736
|
+
"disconnectRequest": DisconnectRequest,
|
|
737
|
+
"disconnectResponse": DisconnectResponse,
|
|
738
|
+
"stateClient": StateClient,
|
|
739
|
+
"stateObject": StateObject,
|
|
740
|
+
"stateBalanceAdvice": StateBalanceAdvice,
|
|
741
|
+
"stateScheduler": StateScheduler,
|
|
742
|
+
"stateWorker": StateWorker,
|
|
743
|
+
"stateTask": StateTask,
|
|
744
|
+
"stateGraphTask": StateGraphTask,
|
|
745
|
+
"clientDisconnect": ClientDisconnect,
|
|
746
|
+
"clientShutdownResponse": ClientShutdownResponse,
|
|
747
|
+
"processorInitialized": ProcessorInitialized,
|
|
748
|
+
"informationRequest": InformationRequest,
|
|
749
|
+
"informationResponse": InformationResponse,
|
|
750
|
+
}
|
|
751
|
+
)
|