{"id":24732631,"url":"https://github.com/gonzalo123/rabbit_examples","last_synced_at":"2025-03-22T16:16:27.905Z","repository":{"id":66582148,"uuid":"163685564","full_name":"gonzalo123/rabbit_examples","owner":"gonzalo123","description":"Playing with RabbitMQ. Usage examples","archived":false,"fork":false,"pushed_at":"2019-01-01T19:39:05.000Z","size":7,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-01-27T17:59:25.849Z","etag":null,"topics":["python","queues","rabbit"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gonzalo123.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-12-31T17:10:54.000Z","updated_at":"2019-01-01T19:39:07.000Z","dependencies_parsed_at":null,"dependency_job_id":"dccc9158-8db1-43d8-8e0a-c531d5202565","html_url":"https://github.com/gonzalo123/rabbit_examples","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gonzalo123%2Frabbit_examples","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gonzalo123%2Frabbit_examples/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gonzalo123%2Frabbit_examples/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gonzalo123%2Frabbit_examples/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gonzalo123","download_url":"https://codeload.github.com/gonzalo123/rabbit_examples/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244982060,"owners_count":20542301,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["python","queues","rabbit"],"created_at":"2025-01-27T17:53:13.345Z","updated_at":"2025-03-22T16:16:27.894Z","avatar_url":"https://github.com/gonzalo123.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Playing with RabbitMQ. Usage examples\n\nThe RabbitMQ documentation is great. You can copy and paste one example in your favourite language and all is up and running. That's great but sometimes we need to master a little bit. In this post I want to show different examples that I've playing with. Basically because I don't want to forget them. My computer isn't the best place to store my documentation.\n\n### Example 1\n\nIt's the simpler example.\n\n\u003e Producer -\u003e Queue -\u003e Consumer.\n\nI've started to understand RabbitMQ when I realized that this picture is impossible. One producer cannot write directly to a queue. We always need an Exchange. The trick here is that we're not creating the Exchange. We're using the default one (''). This exchange put the message in one queue named like the routing_key.\n\nThe Producer:\n```python\nimport pika\nimport sys\nimport logging\nfrom dotenv import load_dotenv\nimport os\n\ncurrent_dir = os.path.dirname(os.path.abspath(__file__))\nload_dotenv(dotenv_path=\"{}/../.env\".format(current_dir))\n\nlogging.basicConfig(level=logging.WARNING)\n\n\ndef event(queue_name, data):\n    logging.info(\"emit message: {} to queue: {}\".format(data, queue_name))\n\n    # Connect to Rabbit using credentials\n    broker_connection = pika.BlockingConnection(pika.URLParameters(os.getenv('AMQP_URI')))\n\n    # create a new channel\n    channel = broker_connection.channel()\n    # create the queue if doesn't exits\n    channel.queue_declare(queue=queue_name)\n    # emit message to the default exchange\n    # that means message will be deliver to the a queue called like the routing key\n    channel.basic_publish(exchange='', routing_key=queue_name, body=data)\n    broker_connection.close()\n\n\nif __name__ == '__main__':\n    event('example1', sys.argv[1])\n```\n\nAnd the consumer:\n```python\nimport pika\nimport logging\nfrom dotenv import load_dotenv\nimport os\n\ncurrent_dir = os.path.dirname(os.path.abspath(__file__))\nload_dotenv(dotenv_path=\"{}/../.env\".format(current_dir))\n\nqueue_name = 'example1'\n\nlogging.basicConfig(level=logging.WARNING)\n\n\ndef callback(ch, method, properties, body):\n    logging.warning(\"body {}\".format(body))\n\n\n# Connect to Rabbit using credentials\nbroker_connection = pika.BlockingConnection(pika.URLParameters(os.getenv('AMQP_URI')))\n\n# create a new channel\nchannel = broker_connection.channel()\n# create the queue if doesn't exits\nchannel.queue_declare(queue=queue_name)\n\n# register callback to the queue\n# no_ack=True means auto ack will be sent\nchannel.basic_consume(consumer_callback=callback, queue=queue_name, no_ack=True)\nchannel.basic_qos(prefetch_count=1)\nchannel.start_consuming()\n```\n\n### Example 2\nNow the same example than the previous one but using a fanout Exchange instead of the default one.\n\nThe producer\n```python\nimport pika\nimport sys\nimport logging\nfrom dotenv import load_dotenv\nimport os\n\ncurrent_dir = os.path.dirname(os.path.abspath(__file__))\nload_dotenv(dotenv_path=\"{}/../.env\".format(current_dir))\n\nlogging.basicConfig(level=logging.WARNING)\n\n\ndef event(data):\n    queue_name = 'example2_queue'\n    exchange_name = 'example2_exchange'\n\n    logging.info(\"emit message: {} to exchange: {}\".format(data, exchange_name))\n\n    # Connect to Rabbit using credentials\n    broker_connection = pika.BlockingConnection(pika.URLParameters(os.getenv('AMQP_URI')))\n\n    # create a new channel\n    channel = broker_connection.channel()\n    # create the queue if doesn't exits\n    channel.queue_declare(queue=queue_name)\n    # create the exchange if it doesn't exists\n    channel.exchange_declare(exchange=exchange_name, exchange_type='fanout', durable=True)\n    # emit message to the exchange\n    channel.basic_publish(exchange=exchange_name, routing_key='', body=data)\n    broker_connection.close()\n\n\nif __name__ == '__main__':\n    event(sys.argv[1])\n```\n\nThe consumer needs to use a binding to join exchange and queue.\n```python\nimport pika\nimport logging\nfrom dotenv import load_dotenv\nimport os\n\ncurrent_dir = os.path.dirname(os.path.abspath(__file__))\nload_dotenv(dotenv_path=\"{}/../.env\".format(current_dir))\n\nqueue_name = 'example2_queue'\nexchange_name = 'example2_exchange'\n\nlogging.basicConfig(level=logging.WARNING)\n\n\ndef callback(ch, method, properties, body):\n    logging.warning(\"body {}\".format(body))\n    # emit ack manually\n    # we need to specify the delivery_tag\n    # delivery_tag is an autoincrement number\n    # depends on the channel. If I stop the scrip and start again\n    # delivery_tag will start again\n    ch.basic_ack(delivery_tag=method.delivery_tag)\n\n\n# Connect to Rabbit using credentials\nbroker_connection = pika.BlockingConnection(pika.URLParameters(os.getenv('AMQP_URI')))\n\n# create a new channel\nchannel = broker_connection.channel()\n# create the queue if doesn't exits\nchannel.queue_declare(queue=queue_name)\n# create the exchange if it doesn't exists\nchannel.exchange_declare(exchange=exchange_name, exchange_type='fanout', durable=True)\n# bind exchange to queue\nchannel.queue_bind(exchange=exchange_name, queue=queue_name)\n\n# register callback to the queue\n# no_ack=False means that I need to send ack manually\nchannel.basic_consume(consumer_callback=callback, queue=queue_name, no_ack=False)\nchannel.basic_qos(prefetch_count=1)\nchannel.start_consuming()\n```\n\n### Example 3\nThe first two examples came from the official documentation. \nNow we're going to do something \"more complicated\". We'll retry each message 5 times. \nThe idea is create a header with the retry count.\nThe Producer:\n```python\nimport pika\nimport sys\nimport logging\nfrom dotenv import load_dotenv\nimport os\n\ncurrent_dir = os.path.dirname(os.path.abspath(__file__))\nload_dotenv(dotenv_path=\"{}/../.env\".format(current_dir))\n\nlogging.basicConfig(level=logging.WARNING)\n\nqueue_name = 'example3'\n\n\ndef event(data):\n    logging.info(\"emit message: {} to queue: {}\".format(data, queue_name))\n\n    # Connect to Rabbit using credentials\n    broker_connection = pika.BlockingConnection(pika.URLParameters(os.getenv('AMQP_URI')))\n\n    # create a new channel\n    channel = broker_connection.channel()\n    # create the queue if doesn't exits\n    channel.queue_declare(queue=queue_name)\n\n    # emit message to the default exchange\n    # we add a header with retry count\n    channel.basic_publish(exchange='',\n                          routing_key=queue_name,\n                          body=data,\n                          properties=pika.BasicProperties(\n                              headers={'retries': 0}\n                          ))\n    broker_connection.close()\n\n\nif __name__ == '__main__':\n    event(sys.argv[1])\n```\n\nIn the Consumer we can see how we re-send a new message with the same body and headers but incrementing the counter.\n\n```python\nimport pika\nimport sys\nimport logging\nfrom dotenv import load_dotenv\nimport os\n\ncurrent_dir = os.path.dirname(os.path.abspath(__file__))\nload_dotenv(dotenv_path=\"{}/../.env\".format(current_dir))\n\nlogging.basicConfig(level=logging.WARNING)\n\nqueue_name = 'example3'\n\n\ndef event(data):\n    logging.info(\"emit message: {} to queue: {}\".format(data, queue_name))\n\n    # Connect to Rabbit using credentials\n    broker_connection = pika.BlockingConnection(pika.URLParameters(os.getenv('AMQP_URI')))\n\n    # create a new channel\n    channel = broker_connection.channel()\n    # create the queue if doesn't exits\n    channel.queue_declare(queue=queue_name)\n\n    # emit message to the default exchange\n    # we add a header with retry count\n    channel.basic_publish(exchange='',\n                          routing_key=queue_name,\n                          body=data,\n                          properties=pika.BasicProperties(\n                              headers={'retries': 0}\n                          ))\n    broker_connection.close()\n\n\nif __name__ == '__main__':\n    event(sys.argv[1])\n```\n\n### Example 4\nNow the idea is the same than the previous example but now we're going to send the message to a dead-letter queue after 3 retries.\nProducer:\n```python\nimport pika\nimport sys\nimport logging\nfrom dotenv import load_dotenv\nimport os\n\ncurrent_dir = os.path.dirname(os.path.abspath(__file__))\nload_dotenv(dotenv_path=\"{}/../.env\".format(current_dir))\n\nlogging.basicConfig(level=logging.WARNING)\n\nqueue_name = 'example4'\n\n\ndef event(data):\n    logging.info(\"emit message: {} to queue: {}\".format(data, queue_name))\n\n    # Connect to Rabbit using credentials\n    broker_connection = pika.BlockingConnection(pika.URLParameters(os.getenv('AMQP_URI')))\n\n    # create a new channel\n    channel = broker_connection.channel()\n    # create the queue if doesn't exits\n    channel.queue_declare(queue=queue_name)\n\n    # emit message to the default exchange\n    # we add a header with retry count\n    # also we add dead letter queue\n    channel.basic_publish(exchange='',\n                          routing_key=queue_name,\n                          body=data,\n                          properties=pika.BasicProperties(\n                              headers={\n                                  'retries': 0,\n                                  'x-dead-letter-queue': 'dlx'\n                              }\n                          ))\n    broker_connection.close()\n\n\nif __name__ == '__main__':\n    event(sys.argv[1])\n```\n\nConsumer\n```python\nimport pika\nimport logging\nfrom dotenv import load_dotenv\nimport os\n\ncurrent_dir = os.path.dirname(os.path.abspath(__file__))\nload_dotenv(dotenv_path=\"{}/../.env\".format(current_dir))\n\nqueue_name = 'example4'\n\nlogging.basicConfig(level=logging.WARNING)\n\n\ndef callback(ch, method, properties, body):\n    # get retry header from properties\n    retries = properties.headers['retries']\n    logging.warning(\"retry: {}\".format(retries))\n\n    # if retry count en minor than 3\n    if retries \u003c 3:\n        properties.headers['retries'] = retries + 1\n        logging.warning(\"reject\")\n        # we reject the message\n        ch.basic_reject(delivery_tag=method.delivery_tag, requeue=False)\n        pika.BlockingConnection.sleep(broker_connection, duration=1)\n        # and re-publish a new one in the same queue\n        channel.basic_publish(exchange=method.exchange,\n                              routing_key=method.routing_key,\n                              body=body,\n                              properties=properties)\n    else:\n        logging.warning(\"ack\")\n        dead_letter_queue = properties.headers['x-dead-letter-queue']\n        ch.basic_nack(delivery_tag=method.delivery_tag, requeue=False)\n        channel.basic_publish(exchange='',\n                              routing_key=dead_letter_queue,\n                              body=body,\n                              properties=pika.BasicProperties(\n                                  headers=properties.headers\n                              ))\n\n\n# Connect to Rabbit using credentials\nbroker_connection = pika.BlockingConnection(pika.URLParameters(os.getenv('AMQP_URI')))\n\n# create a new channel\nchannel = broker_connection.channel()\n# create the queue if doesn't exits\nchannel.queue_declare(queue=queue_name)\nchannel.basic_consume(consumer_callback=callback, queue=queue_name, no_ack=False)\nchannel.start_consuming()\n```\n\nAnd Dead letter consumer\n```python\nimport pika\nimport logging\nimport json\nfrom dotenv import load_dotenv\nimport os\n\ncurrent_dir = os.path.dirname(os.path.abspath(__file__))\nload_dotenv(dotenv_path=\"{}/../.env\".format(current_dir))\n\nqueue_name = 'dlx'\n\nlogging.basicConfig(level=logging.WARNING)\n\n\ndef callback(ch, method, properties, body):\n    logging.warning(\"body\".format(body))\n    logging.warning(\"headers: {}\".format(json.dumps(properties.headers)))\n\n\n# Connect to Rabbit using credentials\nbroker_connection = pika.BlockingConnection(pika.URLParameters(os.getenv('AMQP_URI')))\n\n# create a new channel\nchannel = broker_connection.channel()\n# create the queue if doesn't exits\nchannel.queue_declare(queue=queue_name)\n\n# register callback to the queue\nchannel.basic_consume(consumer_callback=callback, queue=queue_name, no_ack=True)\nchannel.basic_qos(prefetch_count=1)\nchannel.start_consuming()\n```\n\n### Example 5\nIn the last example we're going to work with delayed sends. The idea is send messages to random generated queue. This queue has a ttl and after this time messages are resent to a dead-letter queue. If we listen to this dead-letter queue we'll see the messages with the ttl delay. \n\nThe producer:\n\n```python\nimport pika\nimport sys\nimport logging\nfrom dotenv import load_dotenv\nimport os\n\ncurrent_dir = os.path.dirname(os.path.abspath(__file__))\nload_dotenv(dotenv_path=\"{}/../.env\".format(current_dir))\n\nlogging.basicConfig(level=logging.WARNING)\n\nqueue_name = 'deadqueue'\n\n\ndef delayed_sent(data, ttl):\n    logging.info(\"emit message: {} to queue: {}\".format(data, queue_name))\n\n    # Connect to Rabbit using credentials\n    broker_connection = pika.BlockingConnection(pika.URLParameters(os.getenv('AMQP_URI')))\n\n    # create a new channel\n    channel = broker_connection.channel()\n    # create the queue if doesn't exits\n    # we define also the ttl and dead-letter queue\n    result = channel.queue_declare(arguments={\n        'x-message-ttl': ttl,\n        'x-dead-letter-exchange': '',\n        'x-dead-letter-routing-key': queue_name\n    })\n    queue = result.method.queue\n\n    # emit message via default exchange to the temporary queue\n    # nobody will listen to this queue. We only want it to fordward\n    # the message to the dead-letter queue\n    channel.basic_publish(exchange='',\n                          routing_key=queue,\n                          body=data\n                          )\n    broker_connection.close()\n\n\nif __name__ == '__main__':\n    delayed_sent(sys.argv[1], int(sys.argv[2]))\n```\n\nAnd the consumer:\n```python\nimport pika\nimport logging\nfrom dotenv import load_dotenv\nimport os\n\ncurrent_dir = os.path.dirname(os.path.abspath(__file__))\nload_dotenv(dotenv_path=\"{}/../.env\".format(current_dir))\n\nqueue_name = 'deadqueue'\n\nlogging.basicConfig(level=logging.WARNING)\n\n\ndef callback(ch, method, properties, body):\n    logging.warning(\"body {}\".format(body))\n\n\n# Connect to Rabbit using credentials\nbroker_connection = pika.BlockingConnection(pika.URLParameters(os.getenv('AMQP_URI')))\n\n# create a new channel\nchannel = broker_connection.channel()\n# create the queue if doesn't exits\nchannel.queue_declare(queue=queue_name)\n\n# register callback to the queue\n# no_ack=True means auto ack will be sent\nchannel.basic_consume(consumer_callback=callback, queue=queue_name, no_ack=True)\nchannel.basic_qos(prefetch_count=1)\nchannel.start_consuming()\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgonzalo123%2Frabbit_examples","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgonzalo123%2Frabbit_examples","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgonzalo123%2Frabbit_examples/lists"}