chub-dev 0.1.0 → 0.1.2-beta.0

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 (139) hide show
  1. package/README.md +55 -0
  2. package/bin/chub-mcp +2 -0
  3. package/dist/airtable/docs/database/javascript/DOC.md +1437 -0
  4. package/dist/airtable/docs/database/python/DOC.md +1735 -0
  5. package/dist/amplitude/docs/analytics/javascript/DOC.md +1282 -0
  6. package/dist/amplitude/docs/analytics/python/DOC.md +1199 -0
  7. package/dist/anthropic/docs/claude-api/javascript/DOC.md +503 -0
  8. package/dist/anthropic/docs/claude-api/python/DOC.md +389 -0
  9. package/dist/asana/docs/tasks/DOC.md +1396 -0
  10. package/dist/assemblyai/docs/transcription/DOC.md +1043 -0
  11. package/dist/atlassian/docs/confluence/javascript/DOC.md +1347 -0
  12. package/dist/atlassian/docs/confluence/python/DOC.md +1604 -0
  13. package/dist/auth0/docs/identity/javascript/DOC.md +968 -0
  14. package/dist/auth0/docs/identity/python/DOC.md +1199 -0
  15. package/dist/aws/docs/s3/javascript/DOC.md +1773 -0
  16. package/dist/aws/docs/s3/python/DOC.md +1807 -0
  17. package/dist/binance/docs/trading/javascript/DOC.md +1315 -0
  18. package/dist/binance/docs/trading/python/DOC.md +1454 -0
  19. package/dist/braintree/docs/gateway/javascript/DOC.md +1278 -0
  20. package/dist/braintree/docs/gateway/python/DOC.md +1179 -0
  21. package/dist/chromadb/docs/embeddings-db/javascript/DOC.md +1263 -0
  22. package/dist/chromadb/docs/embeddings-db/python/DOC.md +1707 -0
  23. package/dist/clerk/docs/auth/javascript/DOC.md +1220 -0
  24. package/dist/clerk/docs/auth/python/DOC.md +274 -0
  25. package/dist/cloudflare/docs/workers/javascript/DOC.md +918 -0
  26. package/dist/cloudflare/docs/workers/python/DOC.md +994 -0
  27. package/dist/cockroachdb/docs/distributed-db/DOC.md +1500 -0
  28. package/dist/cohere/docs/llm/DOC.md +1335 -0
  29. package/dist/datadog/docs/monitoring/javascript/DOC.md +1740 -0
  30. package/dist/datadog/docs/monitoring/python/DOC.md +1815 -0
  31. package/dist/deepgram/docs/speech/javascript/DOC.md +885 -0
  32. package/dist/deepgram/docs/speech/python/DOC.md +685 -0
  33. package/dist/deepl/docs/translation/javascript/DOC.md +887 -0
  34. package/dist/deepl/docs/translation/python/DOC.md +944 -0
  35. package/dist/deepseek/docs/llm/DOC.md +1220 -0
  36. package/dist/directus/docs/headless-cms/javascript/DOC.md +1128 -0
  37. package/dist/directus/docs/headless-cms/python/DOC.md +1276 -0
  38. package/dist/discord/docs/bot/javascript/DOC.md +1090 -0
  39. package/dist/discord/docs/bot/python/DOC.md +1130 -0
  40. package/dist/elasticsearch/docs/search/DOC.md +1634 -0
  41. package/dist/elevenlabs/docs/text-to-speech/javascript/DOC.md +336 -0
  42. package/dist/elevenlabs/docs/text-to-speech/python/DOC.md +552 -0
  43. package/dist/firebase/docs/auth/DOC.md +1015 -0
  44. package/dist/gemini/docs/genai/javascript/DOC.md +691 -0
  45. package/dist/gemini/docs/genai/python/DOC.md +555 -0
  46. package/dist/github/docs/octokit/DOC.md +1560 -0
  47. package/dist/google/docs/bigquery/javascript/DOC.md +1688 -0
  48. package/dist/google/docs/bigquery/python/DOC.md +1503 -0
  49. package/dist/hubspot/docs/crm/javascript/DOC.md +1805 -0
  50. package/dist/hubspot/docs/crm/python/DOC.md +2033 -0
  51. package/dist/huggingface/docs/transformers/DOC.md +948 -0
  52. package/dist/intercom/docs/messaging/javascript/DOC.md +1844 -0
  53. package/dist/intercom/docs/messaging/python/DOC.md +1797 -0
  54. package/dist/jira/docs/issues/javascript/DOC.md +1420 -0
  55. package/dist/jira/docs/issues/python/DOC.md +1492 -0
  56. package/dist/kafka/docs/streaming/javascript/DOC.md +1671 -0
  57. package/dist/kafka/docs/streaming/python/DOC.md +1464 -0
  58. package/dist/landingai-ade/docs/api/DOC.md +620 -0
  59. package/dist/landingai-ade/docs/sdk/python/DOC.md +489 -0
  60. package/dist/landingai-ade/docs/sdk/typescript/DOC.md +542 -0
  61. package/dist/landingai-ade/skills/SKILL.md +489 -0
  62. package/dist/launchdarkly/docs/feature-flags/javascript/DOC.md +1191 -0
  63. package/dist/launchdarkly/docs/feature-flags/python/DOC.md +1671 -0
  64. package/dist/linear/docs/tracker/DOC.md +1554 -0
  65. package/dist/livekit/docs/realtime/javascript/DOC.md +303 -0
  66. package/dist/livekit/docs/realtime/python/DOC.md +163 -0
  67. package/dist/mailchimp/docs/marketing/DOC.md +1420 -0
  68. package/dist/meilisearch/docs/search/DOC.md +1241 -0
  69. package/dist/microsoft/docs/onedrive/javascript/DOC.md +1421 -0
  70. package/dist/microsoft/docs/onedrive/python/DOC.md +1549 -0
  71. package/dist/mongodb/docs/atlas/DOC.md +2041 -0
  72. package/dist/notion/docs/workspace-api/javascript/DOC.md +1435 -0
  73. package/dist/notion/docs/workspace-api/python/DOC.md +1400 -0
  74. package/dist/okta/docs/identity/javascript/DOC.md +1171 -0
  75. package/dist/okta/docs/identity/python/DOC.md +1401 -0
  76. package/dist/openai/docs/chat/javascript/DOC.md +407 -0
  77. package/dist/openai/docs/chat/python/DOC.md +568 -0
  78. package/dist/paypal/docs/checkout/DOC.md +278 -0
  79. package/dist/pinecone/docs/sdk/javascript/DOC.md +984 -0
  80. package/dist/pinecone/docs/sdk/python/DOC.md +1395 -0
  81. package/dist/plaid/docs/banking/javascript/DOC.md +1163 -0
  82. package/dist/plaid/docs/banking/python/DOC.md +1203 -0
  83. package/dist/playwright-community/skills/login-flows/SKILL.md +108 -0
  84. package/dist/postmark/docs/transactional-email/DOC.md +1168 -0
  85. package/dist/prisma/docs/orm/javascript/DOC.md +1419 -0
  86. package/dist/prisma/docs/orm/python/DOC.md +1317 -0
  87. package/dist/qdrant/docs/vector-search/javascript/DOC.md +1221 -0
  88. package/dist/qdrant/docs/vector-search/python/DOC.md +1653 -0
  89. package/dist/rabbitmq/docs/message-queue/javascript/DOC.md +1193 -0
  90. package/dist/rabbitmq/docs/message-queue/python/DOC.md +1243 -0
  91. package/dist/razorpay/docs/payments/javascript/DOC.md +1219 -0
  92. package/dist/razorpay/docs/payments/python/DOC.md +1330 -0
  93. package/dist/redis/docs/key-value/javascript/DOC.md +1851 -0
  94. package/dist/redis/docs/key-value/python/DOC.md +2054 -0
  95. package/dist/registry.json +2817 -0
  96. package/dist/replicate/docs/model-hosting/DOC.md +1318 -0
  97. package/dist/resend/docs/email/DOC.md +1271 -0
  98. package/dist/salesforce/docs/crm/javascript/DOC.md +1241 -0
  99. package/dist/salesforce/docs/crm/python/DOC.md +1183 -0
  100. package/dist/search-index.json +1 -0
  101. package/dist/sendgrid/docs/email-api/javascript/DOC.md +371 -0
  102. package/dist/sendgrid/docs/email-api/python/DOC.md +656 -0
  103. package/dist/sentry/docs/error-tracking/javascript/DOC.md +1073 -0
  104. package/dist/sentry/docs/error-tracking/python/DOC.md +1309 -0
  105. package/dist/shopify/docs/storefront/DOC.md +457 -0
  106. package/dist/slack/docs/workspace/javascript/DOC.md +933 -0
  107. package/dist/slack/docs/workspace/python/DOC.md +271 -0
  108. package/dist/square/docs/payments/javascript/DOC.md +1855 -0
  109. package/dist/square/docs/payments/python/DOC.md +1728 -0
  110. package/dist/stripe/docs/api/DOC.md +1727 -0
  111. package/dist/stripe/docs/payments/DOC.md +1726 -0
  112. package/dist/stytch/docs/auth/javascript/DOC.md +1813 -0
  113. package/dist/stytch/docs/auth/python/DOC.md +1962 -0
  114. package/dist/supabase/docs/client/DOC.md +1606 -0
  115. package/dist/twilio/docs/messaging/python/DOC.md +469 -0
  116. package/dist/twilio/docs/messaging/typescript/DOC.md +946 -0
  117. package/dist/vercel/docs/platform/DOC.md +1940 -0
  118. package/dist/weaviate/docs/vector-db/javascript/DOC.md +1268 -0
  119. package/dist/weaviate/docs/vector-db/python/DOC.md +1388 -0
  120. package/dist/zendesk/docs/support/javascript/DOC.md +2150 -0
  121. package/dist/zendesk/docs/support/python/DOC.md +2297 -0
  122. package/package.json +22 -6
  123. package/skills/get-api-docs/SKILL.md +84 -0
  124. package/src/commands/annotate.js +83 -0
  125. package/src/commands/build.js +12 -1
  126. package/src/commands/feedback.js +150 -0
  127. package/src/commands/get.js +83 -42
  128. package/src/commands/search.js +7 -0
  129. package/src/index.js +43 -17
  130. package/src/lib/analytics.js +90 -0
  131. package/src/lib/annotations.js +57 -0
  132. package/src/lib/bm25.js +170 -0
  133. package/src/lib/cache.js +69 -6
  134. package/src/lib/config.js +8 -3
  135. package/src/lib/identity.js +99 -0
  136. package/src/lib/registry.js +103 -20
  137. package/src/lib/telemetry.js +86 -0
  138. package/src/mcp/server.js +177 -0
  139. package/src/mcp/tools.js +251 -0
@@ -0,0 +1,1243 @@
1
+ ---
2
+ name: message-queue
3
+ description: "RabbitMQ Pika coding guidelines for Python message broker interactions"
4
+ metadata:
5
+ languages: "python"
6
+ versions: "1.3.2"
7
+ updated-on: "2026-03-02"
8
+ source: maintainer
9
+ tags: "rabbitmq,queue,amqp,messaging,async"
10
+ ---
11
+
12
+ # RabbitMQ Pika Coding Guidelines (Python)
13
+
14
+ You are a RabbitMQ Pika coding expert. Help me with writing code using RabbitMQ message broker via the official Pika library.
15
+
16
+ ## Golden Rule: Use the Correct and Current SDK
17
+
18
+ Always use the official Pika library for all RabbitMQ (AMQP 0-9-1) interactions in Python.
19
+
20
+ - **Library Name:** Pika
21
+ - **PyPI Package:** `pika`
22
+ - **Current Version:** 1.3.2 or higher
23
+ - **Python Support:** Python 3.9+
24
+
25
+ **Installation:**
26
+
27
+ ```bash
28
+ pip install pika
29
+ ```
30
+
31
+ **IMPORTANT:** Pika is the official pure-Python RabbitMQ/AMQP 0-9-1 client library. Do not use deprecated alternatives.
32
+
33
+ **Import Pattern:**
34
+
35
+ ```python
36
+ import pika
37
+ ```
38
+
39
+ ## Initialization and Connection
40
+
41
+ ### Environment Variables
42
+
43
+ Configure RabbitMQ connection using environment variables:
44
+
45
+ ```python
46
+ import os
47
+ from dotenv import load_dotenv
48
+
49
+ load_dotenv()
50
+
51
+ # .env file
52
+ RABBITMQ_HOST=localhost
53
+ RABBITMQ_PORT=5672
54
+ RABBITMQ_USER=guest
55
+ RABBITMQ_PASS=guest
56
+ RABBITMQ_VHOST=/
57
+ ```
58
+
59
+ ### Basic Connection (Blocking)
60
+
61
+ ```python
62
+ import pika
63
+
64
+ # Simple connection to localhost
65
+ connection = pika.BlockingConnection(
66
+ pika.ConnectionParameters('localhost')
67
+ )
68
+ channel = connection.channel()
69
+
70
+ print("Connected to RabbitMQ")
71
+ ```
72
+
73
+ ### Connection with Parameters
74
+
75
+ ```python
76
+ import pika
77
+ import os
78
+
79
+ credentials = pika.PlainCredentials(
80
+ username=os.getenv('RABBITMQ_USER', 'guest'),
81
+ password=os.getenv('RABBITMQ_PASS', 'guest')
82
+ )
83
+
84
+ parameters = pika.ConnectionParameters(
85
+ host=os.getenv('RABBITMQ_HOST', 'localhost'),
86
+ port=int(os.getenv('RABBITMQ_PORT', 5672)),
87
+ virtual_host=os.getenv('RABBITMQ_VHOST', '/'),
88
+ credentials=credentials,
89
+ heartbeat=30, # Heartbeat interval in seconds
90
+ blocked_connection_timeout=300
91
+ )
92
+
93
+ connection = pika.BlockingConnection(parameters)
94
+ channel = connection.channel()
95
+ ```
96
+
97
+ ### Connection with URL
98
+
99
+ ```python
100
+ import pika
101
+ import os
102
+
103
+ # Connection URL format: amqp://username:password@host:port/vhost
104
+ url = os.getenv('RABBITMQ_URL', 'amqp://guest:guest@localhost:5672/')
105
+
106
+ parameters = pika.URLParameters(url)
107
+ connection = pika.BlockingConnection(parameters)
108
+ channel = connection.channel()
109
+ ```
110
+
111
+ ### Connection Options
112
+
113
+ ```python
114
+ import pika
115
+
116
+ parameters = pika.ConnectionParameters(
117
+ host='localhost',
118
+ port=5672,
119
+ virtual_host='/',
120
+ credentials=pika.PlainCredentials('guest', 'guest'),
121
+ heartbeat=30, # Heartbeat interval in seconds
122
+ blocked_connection_timeout=300, # Timeout for blocked connection
123
+ connection_attempts=3, # Number of connection attempts
124
+ retry_delay=2, # Delay between retries in seconds
125
+ socket_timeout=10, # Socket timeout in seconds
126
+ stack_timeout=15, # Stack timeout in seconds
127
+ channel_max=2047, # Maximum number of channels
128
+ frame_max=131072, # Maximum frame size
129
+ locale='en_US' # Locale for error messages
130
+ )
131
+
132
+ connection = pika.BlockingConnection(parameters)
133
+ channel = connection.channel()
134
+ ```
135
+
136
+ ## Core Messaging Patterns
137
+
138
+ ### 1. Simple Queue - Producer
139
+
140
+ ```python
141
+ import pika
142
+
143
+ connection = pika.BlockingConnection(
144
+ pika.ConnectionParameters('localhost')
145
+ )
146
+ channel = connection.channel()
147
+
148
+ # Declare queue (create if it doesn't exist)
149
+ channel.queue_declare(queue='hello', durable=True)
150
+
151
+ # Send message
152
+ message = 'Hello World!'
153
+ channel.basic_publish(
154
+ exchange='',
155
+ routing_key='hello',
156
+ body=message,
157
+ properties=pika.BasicProperties(
158
+ delivery_mode=pika.DeliveryMode.Persistent # Make message persistent
159
+ )
160
+ )
161
+
162
+ print(f"Sent: {message}")
163
+
164
+ connection.close()
165
+ ```
166
+
167
+ ### 2. Simple Queue - Consumer
168
+
169
+ ```python
170
+ import pika
171
+
172
+ connection = pika.BlockingConnection(
173
+ pika.ConnectionParameters('localhost')
174
+ )
175
+ channel = connection.channel()
176
+
177
+ # Declare queue
178
+ channel.queue_declare(queue='hello', durable=True)
179
+
180
+ # Callback function for message processing
181
+ def callback(ch, method, properties, body):
182
+ message = body.decode('utf-8')
183
+ print(f"Received: {message}")
184
+
185
+ # Acknowledge message
186
+ ch.basic_ack(delivery_tag=method.delivery_tag)
187
+
188
+ # Consume messages
189
+ channel.basic_consume(
190
+ queue='hello',
191
+ on_message_callback=callback,
192
+ auto_ack=False # Manual acknowledgment
193
+ )
194
+
195
+ print('Waiting for messages. Press CTRL+C to exit.')
196
+ channel.start_consuming()
197
+ ```
198
+
199
+ ### 3. Work Queue with Prefetch
200
+
201
+ ```python
202
+ import pika
203
+ import time
204
+
205
+ connection = pika.BlockingConnection(
206
+ pika.ConnectionParameters('localhost')
207
+ )
208
+ channel = connection.channel()
209
+
210
+ channel.queue_declare(queue='task_queue', durable=True)
211
+
212
+ # Fair dispatch - only send one message at a time
213
+ channel.basic_qos(prefetch_count=1)
214
+
215
+ def callback(ch, method, properties, body):
216
+ message = body.decode('utf-8')
217
+ print(f"Processing: {message}")
218
+
219
+ # Simulate work (one dot = 1 second)
220
+ time.sleep(message.count('.'))
221
+
222
+ print(f"Done: {message}")
223
+ ch.basic_ack(delivery_tag=method.delivery_tag)
224
+
225
+ channel.basic_consume(
226
+ queue='task_queue',
227
+ on_message_callback=callback
228
+ )
229
+
230
+ print('Worker waiting for tasks. Press CTRL+C to exit.')
231
+ channel.start_consuming()
232
+ ```
233
+
234
+ ### 4. Publish/Subscribe with Fanout Exchange
235
+
236
+ **Publisher:**
237
+
238
+ ```python
239
+ import pika
240
+ import sys
241
+
242
+ connection = pika.BlockingConnection(
243
+ pika.ConnectionParameters('localhost')
244
+ )
245
+ channel = connection.channel()
246
+
247
+ # Declare fanout exchange
248
+ channel.exchange_declare(exchange='logs', exchange_type='fanout')
249
+
250
+ message = ' '.join(sys.argv[1:]) or "info: Hello World!"
251
+
252
+ # Publish to exchange
253
+ channel.basic_publish(
254
+ exchange='logs',
255
+ routing_key='', # Ignored for fanout exchange
256
+ body=message
257
+ )
258
+
259
+ print(f"Sent: {message}")
260
+ connection.close()
261
+ ```
262
+
263
+ **Subscriber:**
264
+
265
+ ```python
266
+ import pika
267
+
268
+ connection = pika.BlockingConnection(
269
+ pika.ConnectionParameters('localhost')
270
+ )
271
+ channel = connection.channel()
272
+
273
+ # Declare exchange
274
+ channel.exchange_declare(exchange='logs', exchange_type='fanout')
275
+
276
+ # Create exclusive queue (auto-delete when consumer disconnects)
277
+ result = channel.queue_declare(queue='', exclusive=True)
278
+ queue_name = result.method.queue
279
+
280
+ # Bind queue to exchange
281
+ channel.queue_bind(exchange='logs', queue=queue_name)
282
+
283
+ print(f'Waiting for logs. Queue: {queue_name}')
284
+
285
+ def callback(ch, method, properties, body):
286
+ print(f"Received: {body.decode('utf-8')}")
287
+
288
+ channel.basic_consume(
289
+ queue=queue_name,
290
+ on_message_callback=callback,
291
+ auto_ack=True
292
+ )
293
+
294
+ channel.start_consuming()
295
+ ```
296
+
297
+ ### 5. Routing with Direct Exchange
298
+
299
+ **Emitter:**
300
+
301
+ ```python
302
+ import pika
303
+ import sys
304
+
305
+ connection = pika.BlockingConnection(
306
+ pika.ConnectionParameters('localhost')
307
+ )
308
+ channel = connection.channel()
309
+
310
+ # Declare direct exchange
311
+ channel.exchange_declare(exchange='direct_logs', exchange_type='direct')
312
+
313
+ severity = sys.argv[1] if len(sys.argv) > 1 else 'info'
314
+ message = ' '.join(sys.argv[2:]) or 'Hello World!'
315
+
316
+ # Publish with routing key
317
+ channel.basic_publish(
318
+ exchange='direct_logs',
319
+ routing_key=severity,
320
+ body=message
321
+ )
322
+
323
+ print(f"Sent [{severity}]: {message}")
324
+ connection.close()
325
+ ```
326
+
327
+ **Receiver:**
328
+
329
+ ```python
330
+ import pika
331
+ import sys
332
+
333
+ connection = pika.BlockingConnection(
334
+ pika.ConnectionParameters('localhost')
335
+ )
336
+ channel = connection.channel()
337
+
338
+ channel.exchange_declare(exchange='direct_logs', exchange_type='direct')
339
+
340
+ result = channel.queue_declare(queue='', exclusive=True)
341
+ queue_name = result.method.queue
342
+
343
+ # Severities to listen for
344
+ severities = sys.argv[1:] if len(sys.argv) > 1 else ['error', 'warning']
345
+
346
+ # Bind queue for each severity
347
+ for severity in severities:
348
+ channel.queue_bind(
349
+ exchange='direct_logs',
350
+ queue=queue_name,
351
+ routing_key=severity
352
+ )
353
+
354
+ print(f'Waiting for logs with severities: {", ".join(severities)}')
355
+
356
+ def callback(ch, method, properties, body):
357
+ print(f"[{method.routing_key}]: {body.decode('utf-8')}")
358
+
359
+ channel.basic_consume(
360
+ queue=queue_name,
361
+ on_message_callback=callback,
362
+ auto_ack=True
363
+ )
364
+
365
+ channel.start_consuming()
366
+ ```
367
+
368
+ ### 6. Topics with Topic Exchange
369
+
370
+ **Emit Log Topic:**
371
+
372
+ ```python
373
+ import pika
374
+ import sys
375
+
376
+ connection = pika.BlockingConnection(
377
+ pika.ConnectionParameters('localhost')
378
+ )
379
+ channel = connection.channel()
380
+
381
+ # Declare topic exchange
382
+ channel.exchange_declare(exchange='topic_logs', exchange_type='topic')
383
+
384
+ routing_key = sys.argv[1] if len(sys.argv) > 1 else 'anonymous.info'
385
+ message = ' '.join(sys.argv[2:]) or 'Hello World!'
386
+
387
+ channel.basic_publish(
388
+ exchange='topic_logs',
389
+ routing_key=routing_key,
390
+ body=message
391
+ )
392
+
393
+ print(f"Sent [{routing_key}]: {message}")
394
+ connection.close()
395
+ ```
396
+
397
+ **Receive Log Topic:**
398
+
399
+ ```python
400
+ import pika
401
+ import sys
402
+
403
+ connection = pika.BlockingConnection(
404
+ pika.ConnectionParameters('localhost')
405
+ )
406
+ channel = connection.channel()
407
+
408
+ channel.exchange_declare(exchange='topic_logs', exchange_type='topic')
409
+
410
+ result = channel.queue_declare(queue='', exclusive=True)
411
+ queue_name = result.method.queue
412
+
413
+ # Binding keys with pattern matching
414
+ # * (star) substitutes for exactly one word
415
+ # # (hash) substitutes for zero or more words
416
+ binding_keys = sys.argv[1:] if len(sys.argv) > 1 else ['#']
417
+
418
+ for binding_key in binding_keys:
419
+ channel.queue_bind(
420
+ exchange='topic_logs',
421
+ queue=queue_name,
422
+ routing_key=binding_key
423
+ )
424
+
425
+ print(f'Waiting for logs matching: {", ".join(binding_keys)}')
426
+
427
+ def callback(ch, method, properties, body):
428
+ print(f"[{method.routing_key}]: {body.decode('utf-8')}")
429
+
430
+ channel.basic_consume(
431
+ queue=queue_name,
432
+ on_message_callback=callback,
433
+ auto_ack=True
434
+ )
435
+
436
+ channel.start_consuming()
437
+ ```
438
+
439
+ ### 7. RPC (Remote Procedure Call) Pattern
440
+
441
+ **RPC Client:**
442
+
443
+ ```python
444
+ import pika
445
+ import uuid
446
+
447
+ class FibonacciRpcClient:
448
+ def __init__(self):
449
+ self.connection = pika.BlockingConnection(
450
+ pika.ConnectionParameters('localhost')
451
+ )
452
+ self.channel = self.connection.channel()
453
+
454
+ # Declare callback queue
455
+ result = self.channel.queue_declare(queue='', exclusive=True)
456
+ self.callback_queue = result.method.queue
457
+
458
+ self.channel.basic_consume(
459
+ queue=self.callback_queue,
460
+ on_message_callback=self.on_response,
461
+ auto_ack=True
462
+ )
463
+
464
+ self.response = None
465
+ self.corr_id = None
466
+
467
+ def on_response(self, ch, method, props, body):
468
+ if self.corr_id == props.correlation_id:
469
+ self.response = body
470
+
471
+ def call(self, n):
472
+ self.response = None
473
+ self.corr_id = str(uuid.uuid4())
474
+
475
+ self.channel.basic_publish(
476
+ exchange='',
477
+ routing_key='rpc_queue',
478
+ properties=pika.BasicProperties(
479
+ reply_to=self.callback_queue,
480
+ correlation_id=self.corr_id
481
+ ),
482
+ body=str(n)
483
+ )
484
+
485
+ # Wait for response
486
+ self.connection.process_data_events(time_limit=None)
487
+ while self.response is None:
488
+ self.connection.process_data_events(time_limit=None)
489
+
490
+ return int(self.response)
491
+
492
+ def close(self):
493
+ self.connection.close()
494
+
495
+ # Usage
496
+ fibonacci_rpc = FibonacciRpcClient()
497
+
498
+ print("Requesting fib(30)")
499
+ response = fibonacci_rpc.call(30)
500
+ print(f"Result: {response}")
501
+
502
+ fibonacci_rpc.close()
503
+ ```
504
+
505
+ **RPC Server:**
506
+
507
+ ```python
508
+ import pika
509
+
510
+ def fib(n):
511
+ if n == 0:
512
+ return 0
513
+ elif n == 1:
514
+ return 1
515
+ else:
516
+ return fib(n - 1) + fib(n - 2)
517
+
518
+ connection = pika.BlockingConnection(
519
+ pika.ConnectionParameters('localhost')
520
+ )
521
+ channel = connection.channel()
522
+
523
+ channel.queue_declare(queue='rpc_queue')
524
+
525
+ def on_request(ch, method, props, body):
526
+ n = int(body)
527
+ print(f"Computing fib({n})")
528
+
529
+ response = fib(n)
530
+
531
+ # Send response
532
+ ch.basic_publish(
533
+ exchange='',
534
+ routing_key=props.reply_to,
535
+ properties=pika.BasicProperties(
536
+ correlation_id=props.correlation_id
537
+ ),
538
+ body=str(response)
539
+ )
540
+
541
+ ch.basic_ack(delivery_tag=method.delivery_tag)
542
+
543
+ channel.basic_qos(prefetch_count=1)
544
+ channel.basic_consume(queue='rpc_queue', on_message_callback=on_request)
545
+
546
+ print("Awaiting RPC requests")
547
+ channel.start_consuming()
548
+ ```
549
+
550
+ ## Advanced Configuration
551
+
552
+ ### Message Properties
553
+
554
+ ```python
555
+ import pika
556
+ import time
557
+
558
+ connection = pika.BlockingConnection(
559
+ pika.ConnectionParameters('localhost')
560
+ )
561
+ channel = connection.channel()
562
+
563
+ channel.queue_declare(queue='advanced_queue', durable=True)
564
+
565
+ message = 'Important message'
566
+
567
+ # Comprehensive message properties
568
+ properties = pika.BasicProperties(
569
+ delivery_mode=pika.DeliveryMode.Persistent, # Message persistence
570
+ priority=5, # Message priority (0-255)
571
+ content_type='text/plain', # MIME type
572
+ content_encoding='utf-8', # Encoding
573
+ expiration='60000', # TTL in milliseconds
574
+ message_id='msg-123', # Application message ID
575
+ timestamp=int(time.time()), # Timestamp
576
+ type='notification', # Message type
577
+ user_id='guest', # Creating user
578
+ app_id='my-app', # Application ID
579
+ headers={ # Custom headers
580
+ 'x-custom-header': 'value',
581
+ 'retry-count': 0
582
+ }
583
+ )
584
+
585
+ channel.basic_publish(
586
+ exchange='',
587
+ routing_key='advanced_queue',
588
+ body=message,
589
+ properties=properties
590
+ )
591
+
592
+ connection.close()
593
+ ```
594
+
595
+ ### Queue Options
596
+
597
+ ```python
598
+ import pika
599
+
600
+ connection = pika.BlockingConnection(
601
+ pika.ConnectionParameters('localhost')
602
+ )
603
+ channel = connection.channel()
604
+
605
+ # Queue with advanced options
606
+ channel.queue_declare(
607
+ queue='advanced_queue',
608
+ durable=True, # Queue survives broker restart
609
+ exclusive=False, # Can be accessed by other connections
610
+ auto_delete=False, # Queue won't auto-delete
611
+ arguments={
612
+ 'x-message-ttl': 60000, # Message TTL in milliseconds
613
+ 'x-expires': 300000, # Queue expires after 5 minutes
614
+ 'x-max-length': 1000, # Maximum queue length
615
+ 'x-max-priority': 10, # Enable priority queue (0-10)
616
+ 'x-dead-letter-exchange': 'dlx', # Dead letter exchange
617
+ 'x-dead-letter-routing-key': 'dead.letter', # DLX routing key
618
+ 'x-queue-mode': 'lazy' # Lazy queue mode
619
+ }
620
+ )
621
+
622
+ connection.close()
623
+ ```
624
+
625
+ ### Exchange Options
626
+
627
+ ```python
628
+ import pika
629
+
630
+ connection = pika.BlockingConnection(
631
+ pika.ConnectionParameters('localhost')
632
+ )
633
+ channel = connection.channel()
634
+
635
+ # Exchange with advanced options
636
+ channel.exchange_declare(
637
+ exchange='advanced_exchange',
638
+ exchange_type='topic',
639
+ durable=True, # Exchange survives broker restart
640
+ auto_delete=False, # Exchange won't auto-delete
641
+ internal=False, # Can be published to by clients
642
+ arguments={
643
+ 'alternate-exchange': 'alternate_exchange' # AE for unroutable messages
644
+ }
645
+ )
646
+
647
+ connection.close()
648
+ ```
649
+
650
+ ### Dead Letter Queue (DLQ)
651
+
652
+ ```python
653
+ import pika
654
+
655
+ connection = pika.BlockingConnection(
656
+ pika.ConnectionParameters('localhost')
657
+ )
658
+ channel = connection.channel()
659
+
660
+ # Declare dead letter exchange
661
+ channel.exchange_declare(exchange='dlx', exchange_type='direct', durable=True)
662
+
663
+ # Declare dead letter queue
664
+ channel.queue_declare(queue='dead_letter_queue', durable=True)
665
+
666
+ # Bind DLQ to DLX
667
+ channel.queue_bind(
668
+ queue='dead_letter_queue',
669
+ exchange='dlx',
670
+ routing_key='dead.letter'
671
+ )
672
+
673
+ # Declare main queue with DLX
674
+ channel.queue_declare(
675
+ queue='main_queue',
676
+ durable=True,
677
+ arguments={
678
+ 'x-dead-letter-exchange': 'dlx',
679
+ 'x-dead-letter-routing-key': 'dead.letter',
680
+ 'x-message-ttl': 10000 # Messages expire after 10 seconds
681
+ }
682
+ )
683
+
684
+ print("Dead letter queue setup complete")
685
+ connection.close()
686
+ ```
687
+
688
+ ### Consuming from Dead Letter Queue
689
+
690
+ ```python
691
+ import pika
692
+
693
+ connection = pika.BlockingConnection(
694
+ pika.ConnectionParameters('localhost')
695
+ )
696
+ channel = connection.channel()
697
+
698
+ channel.queue_declare(queue='dead_letter_queue', durable=True)
699
+
700
+ def callback(ch, method, properties, body):
701
+ print(f"Dead letter received: {body.decode('utf-8')}")
702
+ print(f"Original routing key: {method.routing_key}")
703
+
704
+ # Check death reason
705
+ if properties.headers and 'x-death' in properties.headers:
706
+ print(f"Death reason: {properties.headers['x-death']}")
707
+
708
+ # Process or log dead letter
709
+ ch.basic_ack(delivery_tag=method.delivery_tag)
710
+
711
+ channel.basic_consume(
712
+ queue='dead_letter_queue',
713
+ on_message_callback=callback
714
+ )
715
+
716
+ print('Waiting for dead letter messages. Press CTRL+C to exit.')
717
+ channel.start_consuming()
718
+ ```
719
+
720
+ ### Message Rejection and Requeuing
721
+
722
+ ```python
723
+ import pika
724
+ import random
725
+
726
+ connection = pika.BlockingConnection(
727
+ pika.ConnectionParameters('localhost')
728
+ )
729
+ channel = connection.channel()
730
+
731
+ channel.queue_declare(queue='task_queue', durable=True)
732
+ channel.basic_qos(prefetch_count=1)
733
+
734
+ def callback(ch, method, properties, body):
735
+ try:
736
+ message = body.decode('utf-8')
737
+ print(f"Processing: {message}")
738
+
739
+ # Simulate processing with potential failure
740
+ if random.random() < 0.3:
741
+ raise Exception('Random failure')
742
+
743
+ # Success - acknowledge
744
+ ch.basic_ack(delivery_tag=method.delivery_tag)
745
+
746
+ except Exception as e:
747
+ print(f"Processing failed: {e}")
748
+
749
+ # Check retry count
750
+ retry_count = 0
751
+ if properties.headers and 'x-retry-count' in properties.headers:
752
+ retry_count = properties.headers['x-retry-count']
753
+
754
+ if retry_count < 3:
755
+ # Reject and requeue for retry
756
+ ch.basic_nack(delivery_tag=method.delivery_tag, requeue=True)
757
+ else:
758
+ # Max retries reached - reject without requeue (goes to DLQ)
759
+ ch.basic_nack(delivery_tag=method.delivery_tag, requeue=False)
760
+
761
+ channel.basic_consume(
762
+ queue='task_queue',
763
+ on_message_callback=callback
764
+ )
765
+
766
+ print('Consumer with retry waiting for tasks. Press CTRL+C to exit.')
767
+ channel.start_consuming()
768
+ ```
769
+
770
+ ### Publisher Confirms
771
+
772
+ ```python
773
+ import pika
774
+
775
+ connection = pika.BlockingConnection(
776
+ pika.ConnectionParameters('localhost')
777
+ )
778
+ channel = connection.channel()
779
+
780
+ # Enable publisher confirms
781
+ channel.confirm_delivery()
782
+
783
+ channel.queue_declare(queue='confirm_queue', durable=True)
784
+
785
+ message = 'Important message'
786
+
787
+ try:
788
+ channel.basic_publish(
789
+ exchange='',
790
+ routing_key='confirm_queue',
791
+ body=message,
792
+ properties=pika.BasicProperties(
793
+ delivery_mode=pika.DeliveryMode.Persistent
794
+ ),
795
+ mandatory=True
796
+ )
797
+ print("Message confirmed by broker")
798
+ except pika.exceptions.UnroutableError:
799
+ print("Message was returned (unroutable)")
800
+ except pika.exceptions.NackError:
801
+ print("Message was nacked by broker")
802
+
803
+ connection.close()
804
+ ```
805
+
806
+ ### Batch Publishing with Confirms
807
+
808
+ ```python
809
+ import pika
810
+
811
+ connection = pika.BlockingConnection(
812
+ pika.ConnectionParameters('localhost')
813
+ )
814
+ channel = connection.channel()
815
+
816
+ channel.confirm_delivery()
817
+ channel.queue_declare(queue='batch_queue', durable=True)
818
+
819
+ messages = [f'Message {i}' for i in range(100)]
820
+
821
+ confirmed = 0
822
+ nacked = 0
823
+
824
+ for message in messages:
825
+ try:
826
+ channel.basic_publish(
827
+ exchange='',
828
+ routing_key='batch_queue',
829
+ body=message,
830
+ properties=pika.BasicProperties(
831
+ delivery_mode=pika.DeliveryMode.Persistent
832
+ )
833
+ )
834
+ confirmed += 1
835
+ except (pika.exceptions.UnroutableError, pika.exceptions.NackError):
836
+ nacked += 1
837
+
838
+ print(f"Confirmed: {confirmed}, Nacked: {nacked}")
839
+ connection.close()
840
+ ```
841
+
842
+ ## Error Handling and Reconnection
843
+
844
+ ### Connection Error Handling
845
+
846
+ ```python
847
+ import pika
848
+ import time
849
+
850
+ def connect_rabbitmq():
851
+ while True:
852
+ try:
853
+ connection = pika.BlockingConnection(
854
+ pika.ConnectionParameters('localhost')
855
+ )
856
+ channel = connection.channel()
857
+ print("Connected to RabbitMQ")
858
+ return connection, channel
859
+
860
+ except pika.exceptions.AMQPConnectionError as e:
861
+ print(f"Connection failed: {e}")
862
+ print("Retrying in 5 seconds...")
863
+ time.sleep(5)
864
+
865
+ # Usage
866
+ connection, channel = connect_rabbitmq()
867
+ ```
868
+
869
+ ### Robust Connection Manager
870
+
871
+ ```python
872
+ import pika
873
+ import time
874
+ import logging
875
+
876
+ logging.basicConfig(level=logging.INFO)
877
+ logger = logging.getLogger(__name__)
878
+
879
+ class RabbitMQConnection:
880
+ def __init__(self, host='localhost', max_retries=5, retry_delay=5):
881
+ self.host = host
882
+ self.max_retries = max_retries
883
+ self.retry_delay = retry_delay
884
+ self.connection = None
885
+ self.channel = None
886
+
887
+ def connect(self):
888
+ retries = 0
889
+
890
+ while retries < self.max_retries:
891
+ try:
892
+ self.connection = pika.BlockingConnection(
893
+ pika.ConnectionParameters(self.host)
894
+ )
895
+ self.channel = self.connection.channel()
896
+ logger.info("Connected to RabbitMQ")
897
+ return self.channel
898
+
899
+ except pika.exceptions.AMQPConnectionError as e:
900
+ retries += 1
901
+ logger.error(f"Connection failed (attempt {retries}/{self.max_retries}): {e}")
902
+
903
+ if retries < self.max_retries:
904
+ logger.info(f"Retrying in {self.retry_delay} seconds...")
905
+ time.sleep(self.retry_delay)
906
+ else:
907
+ logger.error("Max retries reached. Giving up.")
908
+ raise
909
+
910
+ def close(self):
911
+ if self.connection and not self.connection.is_closed:
912
+ self.connection.close()
913
+ logger.info("Connection closed")
914
+
915
+ # Usage
916
+ manager = RabbitMQConnection(host='localhost', max_retries=5)
917
+ channel = manager.connect()
918
+
919
+ # Use channel...
920
+
921
+ manager.close()
922
+ ```
923
+
924
+ ### Graceful Shutdown
925
+
926
+ ```python
927
+ import pika
928
+ import signal
929
+ import sys
930
+
931
+ connection = None
932
+ channel = None
933
+
934
+ def setup():
935
+ global connection, channel
936
+
937
+ connection = pika.BlockingConnection(
938
+ pika.ConnectionParameters('localhost')
939
+ )
940
+ channel = connection.channel()
941
+
942
+ channel.queue_declare(queue='shutdown_queue', durable=True)
943
+
944
+ channel.basic_consume(
945
+ queue='shutdown_queue',
946
+ on_message_callback=callback
947
+ )
948
+
949
+ def callback(ch, method, properties, body):
950
+ print(f"Processing: {body.decode('utf-8')}")
951
+ ch.basic_ack(delivery_tag=method.delivery_tag)
952
+
953
+ def cleanup(sig, frame):
954
+ print("\nShutting down gracefully...")
955
+
956
+ if channel and channel.is_open:
957
+ channel.stop_consuming()
958
+ channel.close()
959
+
960
+ if connection and connection.is_open:
961
+ connection.close()
962
+
963
+ print("Cleanup complete")
964
+ sys.exit(0)
965
+
966
+ # Register signal handlers
967
+ signal.signal(signal.SIGINT, cleanup)
968
+ signal.signal(signal.SIGTERM, cleanup)
969
+
970
+ setup()
971
+ print('Waiting for messages. Press CTRL+C to exit.')
972
+ channel.start_consuming()
973
+ ```
974
+
975
+ ## Common Patterns
976
+
977
+ ### Message Retry with Delay
978
+
979
+ ```python
980
+ import pika
981
+
982
+ connection = pika.BlockingConnection(
983
+ pika.ConnectionParameters('localhost')
984
+ )
985
+ channel = connection.channel()
986
+
987
+ # Main queue
988
+ channel.queue_declare(
989
+ queue='main_queue',
990
+ durable=True,
991
+ arguments={
992
+ 'x-dead-letter-exchange': 'retry',
993
+ 'x-dead-letter-routing-key': 'retry'
994
+ }
995
+ )
996
+
997
+ # Retry exchange
998
+ channel.exchange_declare(exchange='retry', exchange_type='direct', durable=True)
999
+
1000
+ # Retry queue with delay
1001
+ channel.queue_declare(
1002
+ queue='retry_queue',
1003
+ durable=True,
1004
+ arguments={
1005
+ 'x-message-ttl': 30000, # 30 second delay
1006
+ 'x-dead-letter-exchange': '',
1007
+ 'x-dead-letter-routing-key': 'main_queue'
1008
+ }
1009
+ )
1010
+
1011
+ channel.queue_bind(queue='retry_queue', exchange='retry', routing_key='retry')
1012
+
1013
+ print("Retry queue setup complete")
1014
+ connection.close()
1015
+ ```
1016
+
1017
+ ### Priority Queue
1018
+
1019
+ ```python
1020
+ import pika
1021
+
1022
+ connection = pika.BlockingConnection(
1023
+ pika.ConnectionParameters('localhost')
1024
+ )
1025
+ channel = connection.channel()
1026
+
1027
+ # Queue with priority support
1028
+ channel.queue_declare(
1029
+ queue='priority_queue',
1030
+ durable=True,
1031
+ arguments={'x-max-priority': 10}
1032
+ )
1033
+
1034
+ # Send messages with different priorities
1035
+ messages = [
1036
+ ('Low priority', 1),
1037
+ ('High priority', 10),
1038
+ ('Medium priority', 5)
1039
+ ]
1040
+
1041
+ for message, priority in messages:
1042
+ channel.basic_publish(
1043
+ exchange='',
1044
+ routing_key='priority_queue',
1045
+ body=message,
1046
+ properties=pika.BasicProperties(priority=priority)
1047
+ )
1048
+
1049
+ print("Priority messages sent")
1050
+ connection.close()
1051
+ ```
1052
+
1053
+ ### Rate Limiting Consumer
1054
+
1055
+ ```python
1056
+ import pika
1057
+ import time
1058
+
1059
+ connection = pika.BlockingConnection(
1060
+ pika.ConnectionParameters('localhost')
1061
+ )
1062
+ channel = connection.channel()
1063
+
1064
+ channel.queue_declare(queue='rate_limited_queue', durable=True)
1065
+
1066
+ # Process only 1 message at a time
1067
+ channel.basic_qos(prefetch_count=1)
1068
+
1069
+ def callback(ch, method, properties, body):
1070
+ print(f"Processing: {body.decode('utf-8')}")
1071
+
1072
+ # Simulate rate-limited processing (2 seconds delay)
1073
+ time.sleep(2)
1074
+
1075
+ ch.basic_ack(delivery_tag=method.delivery_tag)
1076
+
1077
+ channel.basic_consume(
1078
+ queue='rate_limited_queue',
1079
+ on_message_callback=callback
1080
+ )
1081
+
1082
+ print('Rate-limited consumer started. Press CTRL+C to exit.')
1083
+ channel.start_consuming()
1084
+ ```
1085
+
1086
+ ### JSON Message Handling
1087
+
1088
+ ```python
1089
+ import pika
1090
+ import json
1091
+
1092
+ connection = pika.BlockingConnection(
1093
+ pika.ConnectionParameters('localhost')
1094
+ )
1095
+ channel = connection.channel()
1096
+
1097
+ channel.queue_declare(queue='json_queue', durable=True)
1098
+
1099
+ # Send JSON message
1100
+ data = {
1101
+ 'user': 'john',
1102
+ 'action': 'login',
1103
+ 'timestamp': 1609459200
1104
+ }
1105
+
1106
+ message = json.dumps(data)
1107
+
1108
+ channel.basic_publish(
1109
+ exchange='',
1110
+ routing_key='json_queue',
1111
+ body=message,
1112
+ properties=pika.BasicProperties(
1113
+ content_type='application/json',
1114
+ delivery_mode=pika.DeliveryMode.Persistent
1115
+ )
1116
+ )
1117
+
1118
+ print(f"Sent JSON: {data}")
1119
+
1120
+ # Receive JSON message
1121
+ def callback(ch, method, properties, body):
1122
+ try:
1123
+ data = json.loads(body)
1124
+ print(f"Received JSON: {data}")
1125
+ ch.basic_ack(delivery_tag=method.delivery_tag)
1126
+ except json.JSONDecodeError as e:
1127
+ print(f"Invalid JSON: {e}")
1128
+ ch.basic_nack(delivery_tag=method.delivery_tag, requeue=False)
1129
+
1130
+ channel.basic_consume(
1131
+ queue='json_queue',
1132
+ on_message_callback=callback
1133
+ )
1134
+
1135
+ # channel.start_consuming() # Uncomment to start consuming
1136
+ connection.close()
1137
+ ```
1138
+
1139
+ ## Async Usage with Select Connection
1140
+
1141
+ ### Async Producer
1142
+
1143
+ ```python
1144
+ import pika
1145
+
1146
+ def on_open(connection):
1147
+ connection.channel(on_open_callback=on_channel_open)
1148
+
1149
+ def on_channel_open(channel):
1150
+ channel.queue_declare(
1151
+ queue='async_queue',
1152
+ durable=True,
1153
+ callback=lambda method: on_queue_declared(channel)
1154
+ )
1155
+
1156
+ def on_queue_declared(channel):
1157
+ message = 'Hello Async World!'
1158
+
1159
+ channel.basic_publish(
1160
+ exchange='',
1161
+ routing_key='async_queue',
1162
+ body=message,
1163
+ properties=pika.BasicProperties(
1164
+ delivery_mode=pika.DeliveryMode.Persistent
1165
+ )
1166
+ )
1167
+
1168
+ print(f"Sent: {message}")
1169
+ channel.connection.close()
1170
+
1171
+ # Create async connection
1172
+ parameters = pika.ConnectionParameters('localhost')
1173
+ connection = pika.SelectConnection(parameters, on_open_callback=on_open)
1174
+
1175
+ try:
1176
+ connection.ioloop.start()
1177
+ except KeyboardInterrupt:
1178
+ connection.close()
1179
+ connection.ioloop.start()
1180
+ ```
1181
+
1182
+ ### Async Consumer
1183
+
1184
+ ```python
1185
+ import pika
1186
+
1187
+ class AsyncConsumer:
1188
+ def __init__(self, queue_name):
1189
+ self.queue_name = queue_name
1190
+ self.connection = None
1191
+ self.channel = None
1192
+
1193
+ def connect(self):
1194
+ parameters = pika.ConnectionParameters('localhost')
1195
+ return pika.SelectConnection(
1196
+ parameters,
1197
+ on_open_callback=self.on_connection_open
1198
+ )
1199
+
1200
+ def on_connection_open(self, connection):
1201
+ self.connection = connection
1202
+ self.connection.channel(on_open_callback=self.on_channel_open)
1203
+
1204
+ def on_channel_open(self, channel):
1205
+ self.channel = channel
1206
+ self.channel.queue_declare(
1207
+ queue=self.queue_name,
1208
+ durable=True,
1209
+ callback=self.on_queue_declared
1210
+ )
1211
+
1212
+ def on_queue_declared(self, method):
1213
+ self.channel.basic_qos(prefetch_count=1)
1214
+ self.channel.basic_consume(
1215
+ queue=self.queue_name,
1216
+ on_message_callback=self.on_message
1217
+ )
1218
+ print(f'Waiting for messages in {self.queue_name}')
1219
+
1220
+ def on_message(self, ch, method, properties, body):
1221
+ print(f"Received: {body.decode('utf-8')}")
1222
+ ch.basic_ack(delivery_tag=method.delivery_tag)
1223
+
1224
+ def run(self):
1225
+ self.connection = self.connect()
1226
+ try:
1227
+ self.connection.ioloop.start()
1228
+ except KeyboardInterrupt:
1229
+ self.connection.close()
1230
+ self.connection.ioloop.start()
1231
+
1232
+ # Usage
1233
+ consumer = AsyncConsumer('async_queue')
1234
+ consumer.run()
1235
+ ```
1236
+
1237
+ ## Useful Links
1238
+
1239
+ - **Official Documentation:** https://www.rabbitmq.com/docs
1240
+ - **Pika Documentation:** https://pika.readthedocs.io/
1241
+ - **Pika GitHub:** https://github.com/pika/pika
1242
+ - **RabbitMQ Tutorials (Python):** https://www.rabbitmq.com/tutorials
1243
+ - **AMQP 0-9-1 Reference:** https://www.rabbitmq.com/amqp-0-9-1-reference.html