DefStream-RabbitMQ 0.1.3__7-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.

Potentially problematic release.


This version of DefStream-RabbitMQ might be problematic. Click here for more details.

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