DefStream 0.1.9__25-py3-none-any.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.
- DefStream/Broker/Configuration.py +18 -0
- DefStream/Broker/Connection.py +141 -0
- DefStream/Broker/Consumer.py +59 -0
- DefStream/Broker/Errors.py +14 -0
- DefStream/Broker/Event.py +35 -0
- DefStream/Broker/Implements/__init__.py +1 -0
- DefStream/Broker/Policies.py +25 -0
- DefStream/Broker/Priority.py +26 -0
- DefStream/Broker/Protocol.py +45 -0
- DefStream/Broker/__init__.py +59 -0
- DefStream/Descriptor/DataObject.py +409 -0
- DefStream/Descriptor/Types.py +248 -0
- DefStream/Descriptor/Value.py +188 -0
- DefStream/Descriptor/__init__.py +172 -0
- DefStream/Inspector/Extension.py +69 -0
- DefStream/Inspector/Extensions/Console.html +373 -0
- DefStream/Inspector/Extensions/Console.py +414 -0
- DefStream/Inspector/Extensions/Dashboard.html +206 -0
- DefStream/Inspector/Extensions/Dashboard.py +124 -0
- DefStream/Inspector/Extensions/HealthCheck.py +107 -0
- DefStream/Inspector/Extensions/Metrics.py +314 -0
- DefStream/Inspector/Extensions/Specifications.py +175 -0
- DefStream/Inspector/Extensions/__init__.py +13 -0
- DefStream/Inspector/Inspector.py +347 -0
- DefStream/Inspector/Response.py +14 -0
- DefStream/Inspector/__init__.py +9 -0
- DefStream/Validator/Pattern.py +36 -0
- DefStream/Validator/Patterns/Array.py +30 -0
- DefStream/Validator/Patterns/Common.py +93 -0
- DefStream/Validator/Patterns/Compare.py +180 -0
- DefStream/Validator/Patterns/Condition.py +60 -0
- DefStream/Validator/Patterns/DataObject.py +85 -0
- DefStream/Validator/Patterns/DateTime.py +111 -0
- DefStream/Validator/Patterns/Number.py +43 -0
- DefStream/Validator/Patterns/Object.py +150 -0
- DefStream/Validator/Patterns/Size.py +110 -0
- DefStream/Validator/Patterns/String.py +85 -0
- DefStream/Validator/Patterns/Type.py +350 -0
- DefStream/Validator/Patterns/__init__.py +137 -0
- DefStream/Validator/Validate.py +29 -0
- DefStream/Validator/Validator.py +30 -0
- DefStream/Validator/__init__.py +11 -0
- DefStream/Worker/Executor.py +371 -0
- DefStream/Worker/Message.py +180 -0
- DefStream/Worker/Pool.py +245 -0
- DefStream/Worker/Run.py +311 -0
- DefStream/Worker/Specification.py +91 -0
- DefStream/Worker/Startup.py +135 -0
- DefStream/Worker/Worker.py +416 -0
- DefStream/Worker/__init__.py +47 -0
- DefStream/__init__.py +0 -0
- defstream-0.1.9.dist-info/METADATA +674 -0
- defstream-0.1.9.dist-info/RECORD +56 -0
- defstream-0.1.9.dist-info/WHEEL +6 -0
- defstream-0.1.9.dist-info/licenses/LICENSE +674 -0
- defstream-0.1.9.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
from concurrent.futures import (
|
|
2
|
+
Executor as PyExecutor,
|
|
3
|
+
Future,
|
|
4
|
+
ProcessPoolExecutor,
|
|
5
|
+
ThreadPoolExecutor,
|
|
6
|
+
)
|
|
7
|
+
from multiprocessing import get_context
|
|
8
|
+
from logging import getLogger
|
|
9
|
+
from multiprocessing.managers import SyncManager
|
|
10
|
+
from pickle import (
|
|
11
|
+
dumps,
|
|
12
|
+
loads,
|
|
13
|
+
)
|
|
14
|
+
from queue import (
|
|
15
|
+
Empty,
|
|
16
|
+
Queue,
|
|
17
|
+
)
|
|
18
|
+
from signal import (
|
|
19
|
+
SIGINT,
|
|
20
|
+
SIG_IGN,
|
|
21
|
+
signal,
|
|
22
|
+
)
|
|
23
|
+
from threading import (
|
|
24
|
+
Lock,
|
|
25
|
+
Thread,
|
|
26
|
+
)
|
|
27
|
+
from traceback import format_exc
|
|
28
|
+
from typing import (
|
|
29
|
+
Any,
|
|
30
|
+
Callable,
|
|
31
|
+
Dict,
|
|
32
|
+
List,
|
|
33
|
+
Optional,
|
|
34
|
+
Sequence,
|
|
35
|
+
TypeVar,
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
__all__ = (
|
|
39
|
+
'Executor',
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
Result = TypeVar('Result')
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def initialize_process() -> None:
|
|
46
|
+
# 부모 프로세스가 종료 요청과 정리를 조정한다.
|
|
47
|
+
signal(
|
|
48
|
+
SIGINT,
|
|
49
|
+
SIG_IGN,
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def execute_loop(
|
|
54
|
+
incoming: Any,
|
|
55
|
+
outgoing: Any,
|
|
56
|
+
setups: Sequence[Callable[[], None]],
|
|
57
|
+
cleanups: Sequence[Callable[[], None]],
|
|
58
|
+
serialized: bool,
|
|
59
|
+
) -> None:
|
|
60
|
+
logger = Executor.logger
|
|
61
|
+
ready = False
|
|
62
|
+
try:
|
|
63
|
+
for setup in setups:
|
|
64
|
+
logger.debug(
|
|
65
|
+
'Starting execution environment setup: hook=%s',
|
|
66
|
+
type(setup).__qualname__,
|
|
67
|
+
)
|
|
68
|
+
setup()
|
|
69
|
+
logger.debug(
|
|
70
|
+
'Execution environment setup completed: hook=%s',
|
|
71
|
+
type(setup).__qualname__,
|
|
72
|
+
)
|
|
73
|
+
ready = True
|
|
74
|
+
logger.debug(
|
|
75
|
+
'Execution unit ready: serialized=%s',
|
|
76
|
+
serialized,
|
|
77
|
+
)
|
|
78
|
+
while True:
|
|
79
|
+
item = incoming.get()
|
|
80
|
+
if item is None:
|
|
81
|
+
return
|
|
82
|
+
key, payload = item
|
|
83
|
+
logger.debug(
|
|
84
|
+
'Execution unit task received: key=%s',
|
|
85
|
+
key,
|
|
86
|
+
)
|
|
87
|
+
try:
|
|
88
|
+
function, args, kwargs = loads(payload) if serialized else payload
|
|
89
|
+
result = function(
|
|
90
|
+
*args,
|
|
91
|
+
**kwargs,
|
|
92
|
+
)
|
|
93
|
+
except BaseException as error:
|
|
94
|
+
logger.debug(
|
|
95
|
+
'Execution unit task failed: key=%s error_type=%s',
|
|
96
|
+
key,
|
|
97
|
+
type(error).__qualname__,
|
|
98
|
+
)
|
|
99
|
+
outcome = (
|
|
100
|
+
False,
|
|
101
|
+
error,
|
|
102
|
+
format_exc() if serialized else None,
|
|
103
|
+
)
|
|
104
|
+
else:
|
|
105
|
+
outcome = (
|
|
106
|
+
True,
|
|
107
|
+
result,
|
|
108
|
+
None,
|
|
109
|
+
)
|
|
110
|
+
if serialized:
|
|
111
|
+
try:
|
|
112
|
+
outcome = dumps(outcome)
|
|
113
|
+
except Exception as error:
|
|
114
|
+
logger.error(
|
|
115
|
+
'Task outcome serialization failed: key=%s error_type=%s',
|
|
116
|
+
key,
|
|
117
|
+
type(error).__qualname__,
|
|
118
|
+
)
|
|
119
|
+
outcome = dumps((
|
|
120
|
+
False,
|
|
121
|
+
RuntimeError('Cannot serialize task outcome: ' + repr(error)),
|
|
122
|
+
format_exc(),
|
|
123
|
+
))
|
|
124
|
+
outgoing.put((
|
|
125
|
+
key,
|
|
126
|
+
outcome,
|
|
127
|
+
))
|
|
128
|
+
logger.debug(
|
|
129
|
+
'Execution unit result sent: key=%s',
|
|
130
|
+
key,
|
|
131
|
+
)
|
|
132
|
+
finally:
|
|
133
|
+
if ready:
|
|
134
|
+
logger.debug(
|
|
135
|
+
'Starting execution environment cleanup: hooks=%s',
|
|
136
|
+
len(cleanups),
|
|
137
|
+
)
|
|
138
|
+
run_cleanups(cleanups)
|
|
139
|
+
logger.debug('Execution environment cleanup completed')
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def run_cleanups(
|
|
143
|
+
cleanups: Sequence[Callable[..., None]],
|
|
144
|
+
*args: Any,
|
|
145
|
+
) -> None:
|
|
146
|
+
failure: Optional[BaseException] = None
|
|
147
|
+
for cleanup in cleanups:
|
|
148
|
+
try:
|
|
149
|
+
cleanup(*args)
|
|
150
|
+
except BaseException as error:
|
|
151
|
+
if failure is not None:
|
|
152
|
+
error.__context__ = failure
|
|
153
|
+
failure = error
|
|
154
|
+
if failure is not None:
|
|
155
|
+
raise failure
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
class Executor(PyExecutor):
|
|
159
|
+
logger = getLogger('DefStream.Executor')
|
|
160
|
+
|
|
161
|
+
def __init__(
|
|
162
|
+
self,
|
|
163
|
+
size: int,
|
|
164
|
+
setups: Sequence[Callable[[], None]],
|
|
165
|
+
cleanups: Sequence[Callable[[], None]],
|
|
166
|
+
process: bool = False,
|
|
167
|
+
):
|
|
168
|
+
self.size = size
|
|
169
|
+
self.setups = setups
|
|
170
|
+
self.cleanups = cleanups
|
|
171
|
+
self.process = process
|
|
172
|
+
self.lock = Lock()
|
|
173
|
+
self.pending: Dict[int, Future[Any]] = {}
|
|
174
|
+
self.workers: List[Future] = []
|
|
175
|
+
self.closed = False
|
|
176
|
+
self.failure: Optional[BaseException] = None
|
|
177
|
+
self.manager: Optional[SyncManager] = None
|
|
178
|
+
self.executor: Optional[PyExecutor] = None
|
|
179
|
+
self.monitor: Optional[Thread] = None
|
|
180
|
+
self.incoming: Any = None
|
|
181
|
+
self.outgoing: Any = None
|
|
182
|
+
self.sequence = 0
|
|
183
|
+
|
|
184
|
+
def start(self) -> None:
|
|
185
|
+
self.logger.info(
|
|
186
|
+
'Starting Executor: concurrency=%s process=%s',
|
|
187
|
+
self.size,
|
|
188
|
+
self.process,
|
|
189
|
+
)
|
|
190
|
+
try:
|
|
191
|
+
if self.process:
|
|
192
|
+
context = get_context('spawn')
|
|
193
|
+
self.manager = context.Manager()
|
|
194
|
+
self.incoming = self.manager.Queue()
|
|
195
|
+
self.outgoing = self.manager.Queue()
|
|
196
|
+
executor: PyExecutor = ProcessPoolExecutor(
|
|
197
|
+
self.size,
|
|
198
|
+
mp_context=context,
|
|
199
|
+
initializer=initialize_process,
|
|
200
|
+
)
|
|
201
|
+
else:
|
|
202
|
+
self.incoming = Queue()
|
|
203
|
+
self.outgoing = Queue()
|
|
204
|
+
executor = ThreadPoolExecutor(self.size)
|
|
205
|
+
self.executor = executor
|
|
206
|
+
for index in range(self.size):
|
|
207
|
+
self.workers.append(executor.submit(
|
|
208
|
+
execute_loop,
|
|
209
|
+
self.incoming,
|
|
210
|
+
self.outgoing,
|
|
211
|
+
self.setups,
|
|
212
|
+
self.cleanups,
|
|
213
|
+
self.process,
|
|
214
|
+
))
|
|
215
|
+
monitor = Thread(target=self.collect)
|
|
216
|
+
monitor.start()
|
|
217
|
+
self.monitor = monitor
|
|
218
|
+
self.logger.info('Executor execution environment ready')
|
|
219
|
+
except BaseException:
|
|
220
|
+
self.logger.exception('Executor startup failed')
|
|
221
|
+
self.closed = True
|
|
222
|
+
try:
|
|
223
|
+
for worker in self.workers:
|
|
224
|
+
self.incoming.put(None)
|
|
225
|
+
finally:
|
|
226
|
+
try:
|
|
227
|
+
if self.executor is not None:
|
|
228
|
+
self.executor.shutdown(wait=True)
|
|
229
|
+
finally:
|
|
230
|
+
if self.manager is not None:
|
|
231
|
+
self.manager.shutdown()
|
|
232
|
+
raise
|
|
233
|
+
|
|
234
|
+
def submit(
|
|
235
|
+
self,
|
|
236
|
+
fn: Callable[..., Result],
|
|
237
|
+
/,
|
|
238
|
+
*args: Any,
|
|
239
|
+
**kwargs: Any,
|
|
240
|
+
) -> Future[Result]:
|
|
241
|
+
payload = (
|
|
242
|
+
fn,
|
|
243
|
+
args,
|
|
244
|
+
kwargs,
|
|
245
|
+
)
|
|
246
|
+
if self.process:
|
|
247
|
+
payload = dumps(payload)
|
|
248
|
+
with self.lock:
|
|
249
|
+
if self.closed:
|
|
250
|
+
raise RuntimeError('Pool is closed')
|
|
251
|
+
if self.failure is not None:
|
|
252
|
+
raise RuntimeError('Pool execution environment failed') from self.failure
|
|
253
|
+
if self.executor is None:
|
|
254
|
+
self.start()
|
|
255
|
+
key = self.sequence
|
|
256
|
+
self.sequence += 1
|
|
257
|
+
future: Future[Result] = Future()
|
|
258
|
+
future.set_running_or_notify_cancel()
|
|
259
|
+
self.pending[key] = future
|
|
260
|
+
self.logger.debug(
|
|
261
|
+
'Dispatching task to execution environment: key=%s pending=%s',
|
|
262
|
+
key,
|
|
263
|
+
len(self.pending),
|
|
264
|
+
)
|
|
265
|
+
try:
|
|
266
|
+
self.incoming.put((
|
|
267
|
+
key,
|
|
268
|
+
payload,
|
|
269
|
+
))
|
|
270
|
+
except BaseException:
|
|
271
|
+
del self.pending[key]
|
|
272
|
+
raise
|
|
273
|
+
return future
|
|
274
|
+
|
|
275
|
+
def collect(self) -> None:
|
|
276
|
+
try:
|
|
277
|
+
self.collect_results()
|
|
278
|
+
except BaseException as error:
|
|
279
|
+
self.fail(error)
|
|
280
|
+
|
|
281
|
+
def fail(
|
|
282
|
+
self,
|
|
283
|
+
error: BaseException,
|
|
284
|
+
) -> None:
|
|
285
|
+
with self.lock:
|
|
286
|
+
first_failure = self.failure is None
|
|
287
|
+
self.failure = error
|
|
288
|
+
pending = tuple(self.pending.values())
|
|
289
|
+
self.pending.clear()
|
|
290
|
+
if first_failure:
|
|
291
|
+
self.logger.error(
|
|
292
|
+
'Executor execution environment failed: pending=%s',
|
|
293
|
+
len(pending),
|
|
294
|
+
exc_info=(
|
|
295
|
+
type(error),
|
|
296
|
+
error,
|
|
297
|
+
error.__traceback__,
|
|
298
|
+
),
|
|
299
|
+
)
|
|
300
|
+
for future in pending:
|
|
301
|
+
future.set_exception(error)
|
|
302
|
+
|
|
303
|
+
def collect_results(self) -> None:
|
|
304
|
+
while True:
|
|
305
|
+
try:
|
|
306
|
+
key, outcome = self.outgoing.get(timeout=0.05)
|
|
307
|
+
except Empty:
|
|
308
|
+
pass
|
|
309
|
+
else:
|
|
310
|
+
success, value, traceback = loads(outcome) if self.process else outcome
|
|
311
|
+
self.logger.debug(
|
|
312
|
+
'Execution result collected: key=%s success=%s',
|
|
313
|
+
key,
|
|
314
|
+
success,
|
|
315
|
+
)
|
|
316
|
+
with self.lock:
|
|
317
|
+
future = self.pending.pop(
|
|
318
|
+
key,
|
|
319
|
+
None,
|
|
320
|
+
)
|
|
321
|
+
if future is not None:
|
|
322
|
+
if success:
|
|
323
|
+
future.set_result(value)
|
|
324
|
+
else:
|
|
325
|
+
if traceback is not None:
|
|
326
|
+
value.__cause__ = RuntimeError('Remote execution traceback:\n' + traceback)
|
|
327
|
+
future.set_exception(value)
|
|
328
|
+
failure = next(
|
|
329
|
+
(
|
|
330
|
+
worker.exception()
|
|
331
|
+
for worker in self.workers
|
|
332
|
+
if worker.done() and worker.exception() is not None
|
|
333
|
+
),
|
|
334
|
+
None,
|
|
335
|
+
)
|
|
336
|
+
if failure is not None:
|
|
337
|
+
self.fail(failure)
|
|
338
|
+
with self.lock:
|
|
339
|
+
finished = not self.pending and all(worker.done() for worker in self.workers)
|
|
340
|
+
if finished:
|
|
341
|
+
return
|
|
342
|
+
|
|
343
|
+
def shutdown(
|
|
344
|
+
self,
|
|
345
|
+
wait: bool = True,
|
|
346
|
+
*,
|
|
347
|
+
cancel_futures: bool = False,
|
|
348
|
+
) -> None:
|
|
349
|
+
self.logger.info(
|
|
350
|
+
'Executor shutdown requested: wait=%s',
|
|
351
|
+
wait,
|
|
352
|
+
)
|
|
353
|
+
with self.lock:
|
|
354
|
+
if not self.closed:
|
|
355
|
+
self.closed = True
|
|
356
|
+
if self.executor is not None:
|
|
357
|
+
for worker in self.workers:
|
|
358
|
+
self.incoming.put(None)
|
|
359
|
+
executor = self.executor
|
|
360
|
+
if executor is None:
|
|
361
|
+
self.logger.debug('Closing an unstarted Executor')
|
|
362
|
+
return
|
|
363
|
+
executor.shutdown(wait=wait)
|
|
364
|
+
if wait:
|
|
365
|
+
if self.monitor is not None:
|
|
366
|
+
self.monitor.join()
|
|
367
|
+
if self.manager is not None:
|
|
368
|
+
self.manager.shutdown()
|
|
369
|
+
if self.failure is not None:
|
|
370
|
+
raise RuntimeError('Pool execution environment failed') from self.failure
|
|
371
|
+
self.logger.info('Executor shutdown completed')
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
from collections.abc import Mapping
|
|
2
|
+
from inspect import isabstract
|
|
3
|
+
from typing import (
|
|
4
|
+
Any,
|
|
5
|
+
Optional,
|
|
6
|
+
Type,
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
from ..Broker.Connection import (
|
|
10
|
+
Connection,
|
|
11
|
+
Declarable,
|
|
12
|
+
Emittable,
|
|
13
|
+
Requestable,
|
|
14
|
+
PrioritySupport,
|
|
15
|
+
)
|
|
16
|
+
from .Run import (
|
|
17
|
+
Run,
|
|
18
|
+
priority_setting,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
__all__ = (
|
|
22
|
+
'declare',
|
|
23
|
+
'emit',
|
|
24
|
+
'request',
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def task_parameters(
|
|
29
|
+
task: Type[Run],
|
|
30
|
+
) -> Any:
|
|
31
|
+
if not isinstance(
|
|
32
|
+
task,
|
|
33
|
+
type,
|
|
34
|
+
) or not issubclass(
|
|
35
|
+
task,
|
|
36
|
+
Run,
|
|
37
|
+
) or isabstract(task):
|
|
38
|
+
raise TypeError('A concrete Run class is required')
|
|
39
|
+
if task.parameters is None:
|
|
40
|
+
raise ValueError('Run subscription parameters are required')
|
|
41
|
+
return task.parameters
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def message_body(
|
|
45
|
+
body: Mapping,
|
|
46
|
+
) -> dict:
|
|
47
|
+
if not isinstance(
|
|
48
|
+
body,
|
|
49
|
+
Mapping,
|
|
50
|
+
) or not all(isinstance(
|
|
51
|
+
key,
|
|
52
|
+
str,
|
|
53
|
+
) for key in body):
|
|
54
|
+
raise TypeError('Task body must be a mapping with string keys')
|
|
55
|
+
return dict(body)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def priority_parameters(
|
|
59
|
+
broker: Connection,
|
|
60
|
+
parameters: Any,
|
|
61
|
+
priority: Optional[int],
|
|
62
|
+
) -> Any:
|
|
63
|
+
if priority_setting(
|
|
64
|
+
parameters,
|
|
65
|
+
'priority',
|
|
66
|
+
) is None and priority_setting(
|
|
67
|
+
parameters,
|
|
68
|
+
'max_priority',
|
|
69
|
+
) is None and priority is None:
|
|
70
|
+
return parameters
|
|
71
|
+
if not isinstance(
|
|
72
|
+
broker,
|
|
73
|
+
PrioritySupport,
|
|
74
|
+
):
|
|
75
|
+
raise NotImplementedError('This connection does not support task priorities')
|
|
76
|
+
return broker.priority_parameters(
|
|
77
|
+
parameters,
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def declare(
|
|
82
|
+
*,
|
|
83
|
+
task: Type[Run],
|
|
84
|
+
broker: Connection,
|
|
85
|
+
) -> None:
|
|
86
|
+
parameters = task_parameters(task)
|
|
87
|
+
if not isinstance(
|
|
88
|
+
broker,
|
|
89
|
+
Declarable,
|
|
90
|
+
):
|
|
91
|
+
raise NotImplementedError('This connection does not support task declarations')
|
|
92
|
+
broker.declare(priority_parameters(
|
|
93
|
+
broker,
|
|
94
|
+
parameters,
|
|
95
|
+
None,
|
|
96
|
+
))
|
|
97
|
+
return
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def emit(
|
|
101
|
+
body: Mapping,
|
|
102
|
+
*,
|
|
103
|
+
task: Type[Run],
|
|
104
|
+
broker: Connection,
|
|
105
|
+
priority: Optional[int] = None,
|
|
106
|
+
) -> Any:
|
|
107
|
+
parameters = task_parameters(task)
|
|
108
|
+
payload = message_body(body)
|
|
109
|
+
if not isinstance(
|
|
110
|
+
broker,
|
|
111
|
+
Emittable,
|
|
112
|
+
):
|
|
113
|
+
raise NotImplementedError('This connection does not support task emission')
|
|
114
|
+
parameters = priority_parameters(
|
|
115
|
+
broker,
|
|
116
|
+
parameters,
|
|
117
|
+
priority,
|
|
118
|
+
)
|
|
119
|
+
effective = priority_setting(
|
|
120
|
+
parameters,
|
|
121
|
+
'priority',
|
|
122
|
+
) if priority is None else priority
|
|
123
|
+
if effective is not None:
|
|
124
|
+
if not isinstance(
|
|
125
|
+
broker,
|
|
126
|
+
PrioritySupport,
|
|
127
|
+
):
|
|
128
|
+
raise NotImplementedError('This connection does not support task priorities')
|
|
129
|
+
return broker.emit(
|
|
130
|
+
payload,
|
|
131
|
+
parameters,
|
|
132
|
+
priority=effective,
|
|
133
|
+
)
|
|
134
|
+
return broker.emit(
|
|
135
|
+
payload,
|
|
136
|
+
parameters,
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def request(
|
|
141
|
+
body: Mapping,
|
|
142
|
+
*,
|
|
143
|
+
task: Type[Run],
|
|
144
|
+
broker: Connection,
|
|
145
|
+
timeout: float = 5,
|
|
146
|
+
priority: Optional[int] = None,
|
|
147
|
+
) -> Any:
|
|
148
|
+
parameters = task_parameters(task)
|
|
149
|
+
payload = message_body(body)
|
|
150
|
+
if not isinstance(
|
|
151
|
+
broker,
|
|
152
|
+
Requestable,
|
|
153
|
+
):
|
|
154
|
+
raise NotImplementedError('This connection does not support task RPC requests')
|
|
155
|
+
parameters = priority_parameters(
|
|
156
|
+
broker,
|
|
157
|
+
parameters,
|
|
158
|
+
priority,
|
|
159
|
+
)
|
|
160
|
+
effective = priority_setting(
|
|
161
|
+
parameters,
|
|
162
|
+
'priority',
|
|
163
|
+
) if priority is None else priority
|
|
164
|
+
if effective is not None:
|
|
165
|
+
if not isinstance(
|
|
166
|
+
broker,
|
|
167
|
+
PrioritySupport,
|
|
168
|
+
):
|
|
169
|
+
raise NotImplementedError('This connection does not support task priorities')
|
|
170
|
+
return broker.request(
|
|
171
|
+
payload,
|
|
172
|
+
parameters,
|
|
173
|
+
timeout=timeout,
|
|
174
|
+
priority=effective,
|
|
175
|
+
)
|
|
176
|
+
return broker.request(
|
|
177
|
+
payload,
|
|
178
|
+
parameters,
|
|
179
|
+
timeout=timeout,
|
|
180
|
+
)
|