DefStream-RabbitMQ 0.1.24__110-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/Implements/RabbitMQ/Configuration.py +49 -0
- DefStream/Broker/Implements/RabbitMQ/Connection.py +550 -0
- DefStream/Broker/Implements/RabbitMQ/Consumer.py +416 -0
- DefStream/Broker/Implements/RabbitMQ/Event.py +146 -0
- DefStream/Broker/Implements/RabbitMQ/Exchange.py +277 -0
- DefStream/Broker/Implements/RabbitMQ/Queue.py +321 -0
- DefStream/Broker/Implements/RabbitMQ/Serializer.py +75 -0
- DefStream/Broker/Implements/RabbitMQ/Stream.py +181 -0
- DefStream/Broker/Implements/RabbitMQ/Subscription.py +90 -0
- DefStream/Broker/Implements/RabbitMQ/__init__.py +45 -0
- defstream_rabbitmq-0.1.24.dist-info/METADATA +92 -0
- defstream_rabbitmq-0.1.24.dist-info/RECORD +15 -0
- defstream_rabbitmq-0.1.24.dist-info/WHEEL +6 -0
- defstream_rabbitmq-0.1.24.dist-info/licenses/LICENSE +674 -0
- defstream_rabbitmq-0.1.24.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
from DefStream.Broker import Configuration as BaseConfiguration
|
|
4
|
+
|
|
5
|
+
from .Serializer import (
|
|
6
|
+
Encoder,
|
|
7
|
+
Decoder,
|
|
8
|
+
JavaScriptObjectNotationEncoder,
|
|
9
|
+
JavaScriptObjectNotationDecoder,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
from pika import SSLOptions
|
|
14
|
+
from ssl import create_default_context
|
|
15
|
+
from typing import Optional
|
|
16
|
+
|
|
17
|
+
__all__ = (
|
|
18
|
+
'Configuration',
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class Configuration(BaseConfiguration):
|
|
23
|
+
"""
|
|
24
|
+
Configuration of Event Broker for RabbitMQ
|
|
25
|
+
"""
|
|
26
|
+
def __init__(
|
|
27
|
+
self,
|
|
28
|
+
host: str,
|
|
29
|
+
port: int,
|
|
30
|
+
username: str,
|
|
31
|
+
password: str,
|
|
32
|
+
ssl: bool = False,
|
|
33
|
+
vhost: str = '/',
|
|
34
|
+
timeout: Optional[int] = None,
|
|
35
|
+
heartbeat: Optional[int] = None,
|
|
36
|
+
encode: Encoder = JavaScriptObjectNotationEncoder(),
|
|
37
|
+
decode: Decoder = JavaScriptObjectNotationDecoder(),
|
|
38
|
+
):
|
|
39
|
+
self.host = host
|
|
40
|
+
self.port = port
|
|
41
|
+
self.username = username
|
|
42
|
+
self.password = password
|
|
43
|
+
self.ssl = SSLOptions(create_default_context(), host) if ssl else None
|
|
44
|
+
self.vhost = vhost
|
|
45
|
+
self.timeout = timeout/1000 if timeout else None
|
|
46
|
+
self.heartbeat = int(heartbeat*2/1000) if heartbeat else None
|
|
47
|
+
self.encode = encode
|
|
48
|
+
self.decode = decode
|
|
49
|
+
return
|
|
@@ -0,0 +1,550 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
from DefStream.Broker import (
|
|
4
|
+
Connection as BaseConnection,
|
|
5
|
+
GetExchange,
|
|
6
|
+
GetQueue,
|
|
7
|
+
GetStream,
|
|
8
|
+
GetConsumer,
|
|
9
|
+
Declarable,
|
|
10
|
+
PrioritySupport,
|
|
11
|
+
EventHandler,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
from .Configuration import Configuration
|
|
15
|
+
|
|
16
|
+
from .Exchange import Exchange
|
|
17
|
+
from .Queue import Queue
|
|
18
|
+
from .Stream import Stream
|
|
19
|
+
from .Consumer import Consumer
|
|
20
|
+
from .Subscription import Subscription
|
|
21
|
+
|
|
22
|
+
from pika import (
|
|
23
|
+
BlockingConnection,
|
|
24
|
+
ConnectionParameters,
|
|
25
|
+
PlainCredentials,
|
|
26
|
+
BasicProperties,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
from collections.abc import (
|
|
30
|
+
Mapping,
|
|
31
|
+
KeysView,
|
|
32
|
+
ItemsView,
|
|
33
|
+
ValuesView,
|
|
34
|
+
)
|
|
35
|
+
from operator import (
|
|
36
|
+
eq,
|
|
37
|
+
ne,
|
|
38
|
+
)
|
|
39
|
+
from enum import Enum
|
|
40
|
+
from uuid import uuid4
|
|
41
|
+
from contextlib import contextmanager
|
|
42
|
+
from logging import getLogger
|
|
43
|
+
|
|
44
|
+
from typing import (
|
|
45
|
+
Any as AnyValue,
|
|
46
|
+
Dict,
|
|
47
|
+
Iterator,
|
|
48
|
+
Union,
|
|
49
|
+
Optional,
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
__all__ = (
|
|
53
|
+
'Connection',
|
|
54
|
+
'ExchangeType',
|
|
55
|
+
'Parameters',
|
|
56
|
+
'All',
|
|
57
|
+
'Any',
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class ExchangeType(str, Enum):
|
|
62
|
+
Direct = 'direct'
|
|
63
|
+
FanOut = 'fanout'
|
|
64
|
+
Topic = 'topic'
|
|
65
|
+
Header = 'headers'
|
|
66
|
+
def __str__(self): return str(self.value)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class Parameters(Mapping):
|
|
70
|
+
"""Bind Parameters Event Broker for RabbitMQ"""
|
|
71
|
+
def __init__(self, **kwargs):
|
|
72
|
+
self.args = kwargs
|
|
73
|
+
return
|
|
74
|
+
|
|
75
|
+
def __iter__(self) -> Iterator:
|
|
76
|
+
return self.args.__iter__()
|
|
77
|
+
|
|
78
|
+
def __reversed__(self) -> Iterator:
|
|
79
|
+
return self.args.__reversed__()
|
|
80
|
+
|
|
81
|
+
def __len__(self) -> int:
|
|
82
|
+
return self.args.__len__()
|
|
83
|
+
|
|
84
|
+
def __getitem__(
|
|
85
|
+
self,
|
|
86
|
+
key: AnyValue,
|
|
87
|
+
) -> AnyValue:
|
|
88
|
+
return self.args.__getitem__(key)
|
|
89
|
+
|
|
90
|
+
def __contains__(self, key: object) -> bool:
|
|
91
|
+
return self.args.__contains__(key)
|
|
92
|
+
|
|
93
|
+
def __eq__(self, other) -> bool:
|
|
94
|
+
return eq(self.args, other)
|
|
95
|
+
|
|
96
|
+
def __ne__(self, other) -> bool:
|
|
97
|
+
return ne(self.args, other)
|
|
98
|
+
|
|
99
|
+
def keys(self) -> KeysView:
|
|
100
|
+
return self.args.keys()
|
|
101
|
+
|
|
102
|
+
def items(self) -> ItemsView:
|
|
103
|
+
return self.args.items()
|
|
104
|
+
|
|
105
|
+
def values(self) -> ValuesView:
|
|
106
|
+
return self.args.values()
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
class Connection(
|
|
110
|
+
BaseConnection,
|
|
111
|
+
GetExchange,
|
|
112
|
+
GetQueue,
|
|
113
|
+
GetStream,
|
|
114
|
+
GetConsumer,
|
|
115
|
+
Declarable,
|
|
116
|
+
PrioritySupport,
|
|
117
|
+
):
|
|
118
|
+
"""Connection of Event Broker for RabbitMQ"""
|
|
119
|
+
logger = getLogger('Broker.RabbitMQ.Connection')
|
|
120
|
+
|
|
121
|
+
def __init__(self, conf: Configuration):
|
|
122
|
+
self.conf = conf
|
|
123
|
+
self.parameters = ConnectionParameters(
|
|
124
|
+
host=self.conf.host,
|
|
125
|
+
port=self.conf.port,
|
|
126
|
+
credentials=PlainCredentials(self.conf.username, self.conf.password),
|
|
127
|
+
virtual_host=self.conf.vhost,
|
|
128
|
+
ssl_options=self.conf.ssl,
|
|
129
|
+
blocked_connection_timeout=self.conf.timeout,
|
|
130
|
+
heartbeat=self.conf.heartbeat
|
|
131
|
+
)
|
|
132
|
+
self.connection = None
|
|
133
|
+
self.publisher = None
|
|
134
|
+
return
|
|
135
|
+
|
|
136
|
+
def __del__(self):
|
|
137
|
+
self.close()
|
|
138
|
+
return
|
|
139
|
+
|
|
140
|
+
def connect(self):
|
|
141
|
+
if self.connection and self.connection.is_open:
|
|
142
|
+
self.logger.debug('Reusing open connection')
|
|
143
|
+
return
|
|
144
|
+
self.logger.debug('Connecting to RabbitMQ: host=%s port=%s vhost=%s', self.conf.host, self.conf.port, self.conf.vhost)
|
|
145
|
+
with self.observe('RabbitMQ connection'):
|
|
146
|
+
self.connection = BlockingConnection(parameters=self.parameters)
|
|
147
|
+
return
|
|
148
|
+
|
|
149
|
+
@contextmanager
|
|
150
|
+
def observe(
|
|
151
|
+
self,
|
|
152
|
+
operation: str,
|
|
153
|
+
*context,
|
|
154
|
+
):
|
|
155
|
+
"""Log failures only at I/O boundaries owned by this class, without exposing exception details."""
|
|
156
|
+
try:
|
|
157
|
+
yield
|
|
158
|
+
except Exception as error:
|
|
159
|
+
self.logger.error(operation + ' failed: error_type=%s', *context, type(error).__name__)
|
|
160
|
+
raise
|
|
161
|
+
else:
|
|
162
|
+
self.logger.debug(operation + ' completed', *context)
|
|
163
|
+
return
|
|
164
|
+
|
|
165
|
+
def connected(self):
|
|
166
|
+
if self.connection is None or not self.connection.is_open:
|
|
167
|
+
self.logger.error('RabbitMQ connection is not open')
|
|
168
|
+
raise RuntimeError('Connect the RabbitMQ connection before use')
|
|
169
|
+
return self.connection
|
|
170
|
+
|
|
171
|
+
def declare(
|
|
172
|
+
self,
|
|
173
|
+
parameters: AnyValue,
|
|
174
|
+
) -> None:
|
|
175
|
+
subscription: Subscription = Subscription.parse(parameters)
|
|
176
|
+
self.logger.debug('Task queue declaration: queue=%s error_queue=%s max_priority=%s durable=True', subscription.queue, subscription.error, subscription.max_priority)
|
|
177
|
+
connection = self.connected()
|
|
178
|
+
with self.observe('Task queue declaration'):
|
|
179
|
+
channel = connection.channel()
|
|
180
|
+
try:
|
|
181
|
+
arguments: Dict[str, AnyValue] = {}
|
|
182
|
+
if subscription.error is not None:
|
|
183
|
+
channel.queue_declare(
|
|
184
|
+
subscription.error,
|
|
185
|
+
durable=True,
|
|
186
|
+
)
|
|
187
|
+
arguments = {
|
|
188
|
+
'x-dead-letter-exchange': '',
|
|
189
|
+
'x-dead-letter-routing-key': subscription.error,
|
|
190
|
+
}
|
|
191
|
+
if subscription.max_priority is not None:
|
|
192
|
+
arguments['x-max-priority'] = subscription.max_priority
|
|
193
|
+
if subscription.timeout is not None:
|
|
194
|
+
arguments['x-consumer-timeout'] = subscription.timeout
|
|
195
|
+
channel.queue_declare(
|
|
196
|
+
subscription.queue,
|
|
197
|
+
durable=True,
|
|
198
|
+
arguments=arguments,
|
|
199
|
+
)
|
|
200
|
+
finally:
|
|
201
|
+
if channel.is_open:
|
|
202
|
+
channel.close()
|
|
203
|
+
return
|
|
204
|
+
|
|
205
|
+
def priority_parameters(
|
|
206
|
+
self,
|
|
207
|
+
parameters: AnyValue,
|
|
208
|
+
) -> Subscription:
|
|
209
|
+
"""작업 기본값을 검증하고 선언·발행에 사용할 구독 설정을 반환한다."""
|
|
210
|
+
return Subscription.parse(parameters)
|
|
211
|
+
|
|
212
|
+
def emit(
|
|
213
|
+
self,
|
|
214
|
+
body: AnyValue,
|
|
215
|
+
parameters: AnyValue,
|
|
216
|
+
*,
|
|
217
|
+
priority: Optional[int] = None,
|
|
218
|
+
) -> str:
|
|
219
|
+
subscription = Subscription.parse(parameters)
|
|
220
|
+
if priority is None:
|
|
221
|
+
priority = subscription.priority
|
|
222
|
+
subscription.validate_priority(priority)
|
|
223
|
+
connection = self.connected()
|
|
224
|
+
channel = self.publisher
|
|
225
|
+
if channel is None or not channel.is_open:
|
|
226
|
+
try:
|
|
227
|
+
channel = connection.channel()
|
|
228
|
+
channel.confirm_delivery()
|
|
229
|
+
self.logger.debug('Publisher channel created: publisher_confirm=True')
|
|
230
|
+
except Exception as error:
|
|
231
|
+
self.logger.error('Publisher channel creation failed: queue=%s error_type=%s', subscription.queue, type(error).__name__)
|
|
232
|
+
if channel is not None and channel.is_open:
|
|
233
|
+
channel.close()
|
|
234
|
+
raise
|
|
235
|
+
self.publisher = channel
|
|
236
|
+
else:
|
|
237
|
+
self.logger.debug('Reusing publisher channel: publisher_confirm=True')
|
|
238
|
+
id = uuid4().hex
|
|
239
|
+
self.logger.debug('Publishing directly: queue=%s message_id=%s priority=%s publisher_confirm=True', subscription.queue, id, priority)
|
|
240
|
+
try:
|
|
241
|
+
channel.basic_publish(
|
|
242
|
+
exchange='',
|
|
243
|
+
routing_key=subscription.queue,
|
|
244
|
+
body=self.conf.encode(body),
|
|
245
|
+
properties=BasicProperties(
|
|
246
|
+
message_id=id,
|
|
247
|
+
headers={},
|
|
248
|
+
content_type=self.conf.encode.format,
|
|
249
|
+
content_encoding=self.conf.encode.charset,
|
|
250
|
+
delivery_mode=2,
|
|
251
|
+
priority=priority,
|
|
252
|
+
),
|
|
253
|
+
mandatory=True,
|
|
254
|
+
)
|
|
255
|
+
except Exception as error:
|
|
256
|
+
self.logger.error('Direct publication failed: queue=%s message_id=%s error_type=%s', subscription.queue, id, type(error).__name__)
|
|
257
|
+
raise
|
|
258
|
+
self.logger.debug('Direct publication confirmed: queue=%s message_id=%s', subscription.queue, id)
|
|
259
|
+
return id
|
|
260
|
+
|
|
261
|
+
def request(
|
|
262
|
+
self,
|
|
263
|
+
body: AnyValue,
|
|
264
|
+
parameters: AnyValue,
|
|
265
|
+
timeout: float = 5,
|
|
266
|
+
*,
|
|
267
|
+
priority: Optional[int] = None,
|
|
268
|
+
) -> AnyValue:
|
|
269
|
+
subscription = Subscription.parse(parameters)
|
|
270
|
+
if priority is None:
|
|
271
|
+
priority = subscription.priority
|
|
272
|
+
subscription.validate_priority(priority)
|
|
273
|
+
self.connected()
|
|
274
|
+
queue = self.queue(subscription.queue)
|
|
275
|
+
self.logger.debug('Delegating RPC to Queue: queue=%s timeout=%s priority=%s', subscription.queue, timeout, priority)
|
|
276
|
+
try:
|
|
277
|
+
if priority is not None:
|
|
278
|
+
return queue.call(
|
|
279
|
+
body,
|
|
280
|
+
timeout=timeout,
|
|
281
|
+
priority=priority,
|
|
282
|
+
)
|
|
283
|
+
return queue.call(
|
|
284
|
+
body,
|
|
285
|
+
timeout=timeout,
|
|
286
|
+
)
|
|
287
|
+
finally:
|
|
288
|
+
try:
|
|
289
|
+
if queue.channel.is_open:
|
|
290
|
+
queue.channel.close()
|
|
291
|
+
self.logger.debug('RPC delegated channel cleanup completed: queue=%s', subscription.queue)
|
|
292
|
+
except Exception as error:
|
|
293
|
+
self.logger.error('RPC delegated channel cleanup failed: queue=%s error_type=%s', subscription.queue, type(error).__name__)
|
|
294
|
+
raise
|
|
295
|
+
|
|
296
|
+
def exchange(self, exchange: str) -> Exchange:
|
|
297
|
+
self.logger.debug('Creating Exchange: exchange=%s', exchange)
|
|
298
|
+
return Exchange(
|
|
299
|
+
self.connected(),
|
|
300
|
+
self.conf.encode,
|
|
301
|
+
exchange,
|
|
302
|
+
decode=self.conf.decode,
|
|
303
|
+
rpc_parameters=self.parameters,
|
|
304
|
+
)
|
|
305
|
+
|
|
306
|
+
def queue(self, queue: str) -> Queue:
|
|
307
|
+
self.logger.debug('Creating Queue: queue=%s', queue)
|
|
308
|
+
return Queue(
|
|
309
|
+
self.connected(),
|
|
310
|
+
self.conf.encode,
|
|
311
|
+
self.conf.decode,
|
|
312
|
+
queue,
|
|
313
|
+
rpc_parameters=self.parameters,
|
|
314
|
+
)
|
|
315
|
+
|
|
316
|
+
def stream(self, queue: str) -> Stream:
|
|
317
|
+
self.logger.debug('Creating Stream: queue=%s', queue)
|
|
318
|
+
return Stream(self.connected(), self.conf.encode, self.conf.decode, queue)
|
|
319
|
+
|
|
320
|
+
def consumer(
|
|
321
|
+
self,
|
|
322
|
+
handler: Optional[EventHandler] = None,
|
|
323
|
+
qos: int = 1,
|
|
324
|
+
offset: Optional[int] = None,
|
|
325
|
+
) -> Consumer:
|
|
326
|
+
self.logger.debug('Creating Consumer: qos=%s offset=%s', qos, offset)
|
|
327
|
+
return Consumer(
|
|
328
|
+
self.connected(),
|
|
329
|
+
self.conf.decode,
|
|
330
|
+
handler,
|
|
331
|
+
qos=qos,
|
|
332
|
+
offset=offset,
|
|
333
|
+
encode=self.conf.encode,
|
|
334
|
+
)
|
|
335
|
+
|
|
336
|
+
def close(self):
|
|
337
|
+
connection = self.connection
|
|
338
|
+
self.connection = None
|
|
339
|
+
self.publisher = None
|
|
340
|
+
if connection and connection.is_open:
|
|
341
|
+
with self.observe('RabbitMQ connection close'):
|
|
342
|
+
connection.close()
|
|
343
|
+
return
|
|
344
|
+
|
|
345
|
+
def create_exchange(
|
|
346
|
+
self,
|
|
347
|
+
name: str,
|
|
348
|
+
type: ExchangeType,
|
|
349
|
+
durable: bool = True,
|
|
350
|
+
autodelete: bool = False,
|
|
351
|
+
alter: Optional[Union[str, Exchange]] = None,
|
|
352
|
+
):
|
|
353
|
+
args: Dict[str, AnyValue] = {}
|
|
354
|
+
if alter:
|
|
355
|
+
args['alternate-exchange'] = str(alter)
|
|
356
|
+
self.logger.debug('Exchange declaration: exchange=%s type=%s durable=%s auto_delete=%s alternate_exchange=%s', name, type, durable, autodelete, str(alter) if alter else None)
|
|
357
|
+
with self.observe('Exchange declaration: exchange=%s', name):
|
|
358
|
+
channel = self.connected().channel()
|
|
359
|
+
try:
|
|
360
|
+
channel.exchange_declare(
|
|
361
|
+
name,
|
|
362
|
+
str(type),
|
|
363
|
+
durable=durable,
|
|
364
|
+
auto_delete=autodelete,
|
|
365
|
+
arguments=args
|
|
366
|
+
)
|
|
367
|
+
finally:
|
|
368
|
+
if channel.is_open:
|
|
369
|
+
channel.close()
|
|
370
|
+
return
|
|
371
|
+
|
|
372
|
+
def delete_exchange(
|
|
373
|
+
self,
|
|
374
|
+
name: str,
|
|
375
|
+
):
|
|
376
|
+
with self.observe('Exchange deletion: exchange=%s', name):
|
|
377
|
+
channel = self.connected().channel()
|
|
378
|
+
channel.exchange_delete(name)
|
|
379
|
+
return
|
|
380
|
+
|
|
381
|
+
def bind_exchange_to_exchange(
|
|
382
|
+
self,
|
|
383
|
+
src: Union[str, Exchange],
|
|
384
|
+
to: Union[str, Exchange],
|
|
385
|
+
event: Optional[str] = None,
|
|
386
|
+
parameters: Optional[Parameters] = None,
|
|
387
|
+
):
|
|
388
|
+
with self.observe('Exchange binding: src=%s to=%s routing_key=%s', str(src), str(to), event):
|
|
389
|
+
channel = self.connected().channel()
|
|
390
|
+
channel.exchange_bind(
|
|
391
|
+
str(src),
|
|
392
|
+
str(to),
|
|
393
|
+
routing_key=event if event else '',
|
|
394
|
+
arguments=dict(parameters) if parameters is not None else None
|
|
395
|
+
)
|
|
396
|
+
return
|
|
397
|
+
|
|
398
|
+
def unbind_exchange_to_exchange(
|
|
399
|
+
self,
|
|
400
|
+
src: Union[str, Exchange],
|
|
401
|
+
to: Union[str, Exchange],
|
|
402
|
+
event: Optional[str] = None,
|
|
403
|
+
parameters: Optional[Parameters] = None,
|
|
404
|
+
):
|
|
405
|
+
with self.observe('Exchange unbinding: src=%s to=%s routing_key=%s', str(src), str(to), event):
|
|
406
|
+
channel = self.connected().channel()
|
|
407
|
+
channel.exchange_unbind(
|
|
408
|
+
str(src),
|
|
409
|
+
str(to),
|
|
410
|
+
routing_key=event if event else '',
|
|
411
|
+
arguments=dict(parameters) if parameters is not None else None,
|
|
412
|
+
)
|
|
413
|
+
return
|
|
414
|
+
|
|
415
|
+
def create_queue(
|
|
416
|
+
self,
|
|
417
|
+
name: str,
|
|
418
|
+
expires: Optional[int] = None,
|
|
419
|
+
ttl: Optional[int] = None,
|
|
420
|
+
limit: Optional[int] = None,
|
|
421
|
+
size: Optional[int] = None,
|
|
422
|
+
maxPriority: Optional[int] = None,
|
|
423
|
+
durable: bool = True,
|
|
424
|
+
autodelete: bool = False,
|
|
425
|
+
errorQueue: Optional[Union[str, Queue]] = None,
|
|
426
|
+
errorExchange: Optional[Union[str, Exchange]] = None,
|
|
427
|
+
):
|
|
428
|
+
args: Dict[str, AnyValue] = {}
|
|
429
|
+
if errorQueue:
|
|
430
|
+
args['x-dead-letter-exchange'] = ''
|
|
431
|
+
args['x-dead-letter-routing-key'] = str(errorQueue)
|
|
432
|
+
if errorExchange:
|
|
433
|
+
args['x-dead-letter-exchange'] = str(errorExchange)
|
|
434
|
+
if expires:
|
|
435
|
+
args['x-expires'] = expires
|
|
436
|
+
if ttl:
|
|
437
|
+
args['x-message-ttl'] = ttl
|
|
438
|
+
if limit:
|
|
439
|
+
args['x-max-length'] = limit
|
|
440
|
+
if size:
|
|
441
|
+
args['x-max-length-bytes'] = size
|
|
442
|
+
if maxPriority:
|
|
443
|
+
args['x-max-priority'] = maxPriority
|
|
444
|
+
self.logger.debug('Queue declaration options: queue=%s durable=%s auto_delete=%s expires=%s ttl=%s limit=%s size=%s max_priority=%s error_queue=%s error_exchange=%s', name, durable, autodelete, expires, ttl, limit, size, maxPriority, str(errorQueue) if errorQueue else None, str(errorExchange) if errorExchange else None)
|
|
445
|
+
with self.observe('Queue declaration: queue=%s', name):
|
|
446
|
+
channel = self.connected().channel()
|
|
447
|
+
channel.queue_declare(
|
|
448
|
+
name,
|
|
449
|
+
durable=durable,
|
|
450
|
+
auto_delete=autodelete,
|
|
451
|
+
arguments=args
|
|
452
|
+
)
|
|
453
|
+
return
|
|
454
|
+
|
|
455
|
+
def delete_queue(
|
|
456
|
+
self,
|
|
457
|
+
queue: str,
|
|
458
|
+
):
|
|
459
|
+
with self.observe('Queue deletion: queue=%s', queue):
|
|
460
|
+
channel = self.connected().channel()
|
|
461
|
+
channel.queue_delete(queue)
|
|
462
|
+
return
|
|
463
|
+
|
|
464
|
+
def bind_exchange_to_queue(
|
|
465
|
+
self,
|
|
466
|
+
src: Union[str, Exchange],
|
|
467
|
+
to: Union[str, Queue],
|
|
468
|
+
event: Optional[str] = None,
|
|
469
|
+
parameters: Optional[Parameters] = None,
|
|
470
|
+
):
|
|
471
|
+
with self.observe('Queue binding: exchange=%s queue=%s routing_key=%s', str(src), str(to), event):
|
|
472
|
+
channel = self.connected().channel()
|
|
473
|
+
channel.queue_bind(
|
|
474
|
+
str(to),
|
|
475
|
+
str(src),
|
|
476
|
+
routing_key=event if event else '',
|
|
477
|
+
arguments=dict(parameters) if parameters is not None else None
|
|
478
|
+
)
|
|
479
|
+
return
|
|
480
|
+
|
|
481
|
+
def unbind_exchange_to_queue(
|
|
482
|
+
self,
|
|
483
|
+
src: Union[str, Exchange],
|
|
484
|
+
to: Union[str, Queue],
|
|
485
|
+
event: Optional[str] = None,
|
|
486
|
+
parameters: Optional[Parameters] = None,
|
|
487
|
+
):
|
|
488
|
+
with self.observe('Queue unbinding: exchange=%s queue=%s routing_key=%s', str(src), str(to), event):
|
|
489
|
+
channel = self.connected().channel()
|
|
490
|
+
channel.queue_unbind(
|
|
491
|
+
str(to),
|
|
492
|
+
str(src),
|
|
493
|
+
routing_key=event if event else '',
|
|
494
|
+
arguments=dict(parameters) if parameters is not None else None,
|
|
495
|
+
)
|
|
496
|
+
return
|
|
497
|
+
|
|
498
|
+
def create_stream(
|
|
499
|
+
self,
|
|
500
|
+
name: str,
|
|
501
|
+
size: Optional[int] = None,
|
|
502
|
+
durable: bool = True,
|
|
503
|
+
autodelete: bool = False,
|
|
504
|
+
):
|
|
505
|
+
args: Dict[str, AnyValue] = {
|
|
506
|
+
'x-queue-type': 'stream',
|
|
507
|
+
}
|
|
508
|
+
if size:
|
|
509
|
+
args['x-max-length-bytes'] = size
|
|
510
|
+
self.logger.debug('Stream declaration options: queue=%s durable=%s auto_delete=%s size=%s', name, durable, autodelete, size)
|
|
511
|
+
with self.observe('Stream declaration: queue=%s', name):
|
|
512
|
+
channel = self.connected().channel()
|
|
513
|
+
channel.queue_declare(
|
|
514
|
+
name,
|
|
515
|
+
durable=durable,
|
|
516
|
+
auto_delete=autodelete,
|
|
517
|
+
arguments=args
|
|
518
|
+
)
|
|
519
|
+
return
|
|
520
|
+
|
|
521
|
+
def delete_stream(
|
|
522
|
+
self,
|
|
523
|
+
queue: str,
|
|
524
|
+
):
|
|
525
|
+
with self.observe('Stream deletion: queue=%s', queue):
|
|
526
|
+
channel = self.connected().channel()
|
|
527
|
+
channel.queue_delete(queue)
|
|
528
|
+
return
|
|
529
|
+
|
|
530
|
+
|
|
531
|
+
class All(Parameters):
|
|
532
|
+
"""All Bind Parameters Event Broker for RabbitMQ"""
|
|
533
|
+
def __init__(self, **kwargs):
|
|
534
|
+
headers = {
|
|
535
|
+
'x-match': 'all-with-x'
|
|
536
|
+
}
|
|
537
|
+
headers.update(kwargs)
|
|
538
|
+
super().__init__(**headers)
|
|
539
|
+
return
|
|
540
|
+
|
|
541
|
+
|
|
542
|
+
class Any(Parameters):
|
|
543
|
+
"""Any Bind Parameters Event Broker for RabbitMQ"""
|
|
544
|
+
def __init__(self, **kwargs):
|
|
545
|
+
headers = {
|
|
546
|
+
'x-match': 'any-with-x'
|
|
547
|
+
}
|
|
548
|
+
headers.update(kwargs)
|
|
549
|
+
super().__init__(**headers)
|
|
550
|
+
return
|