{"id":19168445,"url":"https://github.com/bloomberg/rmqcpp","last_synced_at":"2025-04-06T14:10:55.223Z","repository":{"id":201063135,"uuid":"693249084","full_name":"bloomberg/rmqcpp","owner":"bloomberg","description":"A batteries included C++ RabbitMQ Client Library/API.","archived":false,"fork":false,"pushed_at":"2024-12-08T17:28:54.000Z","size":1543,"stargazers_count":78,"open_issues_count":19,"forks_count":20,"subscribers_count":15,"default_branch":"main","last_synced_at":"2025-03-30T13:09:16.953Z","etag":null,"topics":["amqp","amqp0-9-1","cpp","cpp-library","rabbitmq"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bloomberg.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-09-18T16:39:41.000Z","updated_at":"2025-03-29T22:22:00.000Z","dependencies_parsed_at":"2023-11-17T14:42:58.458Z","dependency_job_id":"3ece12f7-15db-4679-a559-e564601fca8e","html_url":"https://github.com/bloomberg/rmqcpp","commit_stats":{"total_commits":48,"total_committers":7,"mean_commits":6.857142857142857,"dds":0.6458333333333333,"last_synced_commit":"38b5fd8deb975cb042359e44f5f631576e9d87dc"},"previous_names":["bloomberg/rmqcpp"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bloomberg%2Frmqcpp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bloomberg%2Frmqcpp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bloomberg%2Frmqcpp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bloomberg%2Frmqcpp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bloomberg","download_url":"https://codeload.github.com/bloomberg/rmqcpp/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247492513,"owners_count":20947544,"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":["amqp","amqp0-9-1","cpp","cpp-library","rabbitmq"],"created_at":"2024-11-09T09:42:40.906Z","updated_at":"2025-04-06T14:10:55.204Z","avatar_url":"https://github.com/bloomberg.png","language":"C++","readme":"# rmqcpp - A C++ library for RabbitMQ\n\n## Menu\n\n- [Rationale](#rationale)\n- [Quick Start](#quick-start)\n- [Basic Usage](#usage)\n- [Documentation](#documentation)\n- [Building](#building)\n- [Installation](#installation)\n- [Contributions](#contributions)\n- [License](#license)\n- [Code of Conduct](#code-of-conduct)\n- [Security Vulnerability Reporting](#security-vulnerability-reporting)\n\n\n\n## Rationale\n`rmqcpp` provides a testable, data-safety-focused and async-capable API that strives to be easy to use.\n\nOut of the box, `rmqcpp` will never silently drop messages, and will always reconnect.\n\n### Features\nThis library has been built from experience learned while supporting other RabbitMQ libraries for many years. Using `rmqcpp` straightaway ticks a lot of boxes in our internal RabbitMQ best practices, as well as those suggested by [CloudAMQP](https://www.cloudamqp.com/blog/part1-rabbitmq-best-practice.html), and [AWS](https://docs.aws.amazon.com/amazon-mq/latest/developer-guide/best-practices-rabbitmq.html).\n\n1. ❤ Heartbeats are always enabled, and they are handled in the background.\n    + Heartbeats catch many network faults, yet some applications avoid them because existing libraries make heartbeats hard to implement. `rmqcpp` has these implemented out of the box.\n2. 🔁 Out-of-the-box reconnection logic\n    + Clients using `rmqcpp` do not need to implement any retry logic. The library will attempt to reconnect in the background forever. This aims to improve recovery times after network outages.\n3. 🏔 Topology declaration as part of Connection\n    + `rmqcpp` always declares topology when creating consumers \u0026 producers, as per RabbitMQ best practices.\n4. ✉ Reliable Message Delivery 'on' by default\n    + Publisher confirmations. This ensures clients are aware when messages are owned by RabbitMQ, and avoids messages being silently black holed.\n    + Consumer acknowledgements. Switching these on manually helps avoid messages being silently dropped during restart/outages, as would be the case with 'autoack'. \n    + Durable queues and persistent delivery mode ensure messages always persist during broker restarts and total datacenter shutdowns.\n    + [Mandatory flag](https://www.rabbitmq.com/amqp-0-9-1-reference.html#basic.publish.mandatory) is defaulted to 'true' for all messages to ensure none are silently dropped due to missed bindings.\n    + All of the above properties are used by default. Publisher confirms and consumer acknowledgements are required.\n5. 🚦 Publishing and Consuming happens on different connections\n    + A common application pitfall is to consume \u0026 produce on the same connection. This can cause slow-downs in consumption rate, as RabbitMQ applies backpressure to fast publishers - depending on the exact queues being consumed/published from this can cause a vicious cycle.\n6. ✂ Reconnect cancelled consumers\n    + Very occasionally, RabbitMQ consumers are cancelled by the broker. This case is rarely implemented properly when using other libraries. `rmqcpp` will redeclare any consumers that have been cancelled.\n\n### Library structure\n`rmqcpp` is made up of a library which builds to `librmq.a`. Internally, this library contains a hierarchy of packages, of which `rmqa`, `rmqt`, and `rmqp` are the public-facing packages.\n\n\n### Internal packages\n```mermaid\ngraph TD;\n    rmqamqpt--\u003ermqt;\n    rmqamqp--\u003ermqamqpt;\n    rmqamqp--\u003ermqio;\n    rmqamqp--\u003ermqt;\n    rmqio--\u003ermqamqpt;\n    rmqa--\u003ermqamqp;\n    rmqa--\u003ermqt;\n    rmqa--\u003ermqp;\n    rmqp--\u003ermqt;\n```\n\n**Library** | **Purpose** | **Examples** \n :--- | :---- | :----\n[rmqp](src/rmq/rmqp) | RabbitMQ library interface (protocol) | Interfaces used to allow testing/mocking of `rmqcpp` applications\n[rmqa](src/rmq/rmqa) | RabbitMQ Library interface implementation | The main concrete objects used by applications\n[rmqt](src/rmq/rmqt) | Data types | The currency(data types used) between rmqa/b and rmqamqp layers\n[rmqtestmocks](src/rmqtestmocks) | gmock types  | Objects useful for testing applications using `rmqcpp`\n[rmqamqp](src/rmq/rmqamqp) | AMQP abstraction layer | All logic relating to amqp communication, framing, classes and state machines - connection, channel queue\n[rmqamqpt](src/rmq/rmqamqpt) | Low-level AMQP data types (from 0-9-1 spec) | Primitives of the AMQP standard, methods, frame, amqp types to C++ types mapping\n[rmqio](src/rmq/rmqio) | IO abstraction layer | Raw socket connections management, reads/writes AMQP frames from/to the wire. Contains a set of async io interfaces, and an implementation using `boost::asio`\n\n## Quick Start\nThe quickest way to get started is to take a look at our integration tests and sample 'hello world' program, which is possible by following the Docker [Build](#building) steps and then: from the interactive shell window running `./build/examples/helloworld/rmqhelloworld_producer`\n \n\n## Usage\n\n```cpp\n// Holds required threads, and other resources.\n// The context must live longer than objects created from it.\nrmqa::RabbitContext rabbit;\n\n// Create topology to be declared on every reconnection\nrmqa::Topology topology;\nrmqt::QueueHandle q1    = topology.addQueue(\"queue-name\");\nrmqt::ExchangeHandle e1 = topology.addExchange(\"exch-name\");\n\n// Bind e1 and q1 using binding key 'key'\ntopology.bind(e1, q1, \"key\");\n\n// To create an auto-generated queue\nrmqt::QueueHandle q2 = topology.addQueue();\ntopology.bind(e1, q2, \"key2\");\n\n// Each `Producer`/`Consumer` has a reference to a `Topology` object\n// which can be updated with updateTopology.\nbsl::shared_ptr\u003crmqa::VHost\u003e vhost = rabbit.createVHostConnection(\n    \"my-connection\",\n    bsl::make_shared\u003crmqt::SimpleEndpoint\u003e(\n        \"localhost\", \"rmqcpp\", 5762),\n    bsl::make_shared\u003crmqt::PlainCredentials\u003e(\n        \"guest\", \"guest\")); // returns immediately\n\n// Get a producer\n// How many messages can be awaiting confirmation before `send` blocks\nconst uint16_t maxOutstandingConfirms = 10;\n\nrmqt::Result\u003crmqa::Producer\u003e producerResult = vhost-\u003ecreateProducer(topology, e1, maxOutstandingConfirms);\n\nif (!producerResult) {\n    // handle errors.\n    bsl::cout \u003c\u003c \"Error creating connection: \" \u003c\u003c producerResult.error();\n    return -1;\n}\n\nbsl::shared_ptr\u003crmqa::Producer\u003e producer = producerResult.value();\n\nvoid receiveConfirmation(const rmqt::Message\u0026 message,\n                         const bsl::string\u0026 routingKey,\n                         const rmqt::ConfirmResponse\u0026 response)\n{\n    if (response.status() == rmqt::ConfirmResponse::ACK) {\n        // Message is now guaranteed to be safe with the broker\n    }\n    else {\n        // REJECT / RETURN indicate problem with the send request (bad routing\n        // key?)\n    }\n}\n\nbsl::string json    = \"[5, 3, 1]\";\nrmqt::Message message(\n    bsl::make_shared\u003cbsl::vector\u003cuint8_t\u003e \u003e(json.cbegin(), json.cend()));\n\n// `send` returns immediately unless there are `maxOutstandingConfirms`\n// oustanding messages already. In which case it waits until at least one\n// confirm comes back.\n// User must wait until the confirm callback is executed before considering\n// the send to be committed.\nconst rmqp::Producer::SendStatus sendResult =\n    producer-\u003esend(message, \"key\", \u0026receiveConfirmation);\n\nif (sendResult != rmqp::Producer::SENDING) {\n    // Unable to enqueue this send\n    return -1;\n}\n\n// Consumer callback\nclass MessageConsumer {\n  private:\n    bool processMessage(const rmqt::Message\u0026 message)\n    {\n        // process Message here\n        return true;\n    }\n\n  public:\n    void operator()(rmqp::MessageGuard\u0026 messageGuard)\n    {\n        if (processMessage(messageGuard.message())) {\n            messageGuard.ack();\n        }\n        else {\n            messageGuard.nack();\n            // Would automatically nack if it goes out of scope\n        }\n    }\n};\n\nrmqt::Result\u003crmqa::Consumer\u003e consumerResult =\n    vhost-\u003ecreateConsumer(\n        topology,            // topology\n        q1,                  // queue\n        MessageConsumer(),   // Consumer callback invoked on each message\n        \"my consumer label\", // Consumer Label (shows in Management UI)\n        500                  // prefetch count\n    );\n\nif (!consumerResult) {\n    // An argument passed to the consumer was bad, retrying will have no effect\n    return -1;\n}\n\nbsl::shared_ptr\u003crmqa::Consumer\u003e consumer = consumerResult.value();\n\n// Shutdown\n\n// Blocks until `timeout` expires or all confirmations have been received\n// Note this could block forever if a separate thread continues publishing\nif (!producer-\u003ewaitForConfirms(/* timeout */)) {\n    // Timeout expired\n}\n\nconsumer-\u003ecancelAndDrain();\n```\n\n## Documentation\nDoxygen generated API documentation can be found [here](https://bloomberg.github.io/rmqcpp/index.html)\n \n## Building\n\n### Prerequisites\n\n \u003e These prerequisites can be skipped when using the docker build environment. Otherwise it is important to set these up.\n\n`vcpkg` is the primary prerequisite for building `rmqcpp`. [Follow the instructions here](https://vcpkg.io/en/getting-started.html) and set the environment variable `VCPKG_ROOT` to the install location, i.e. `export VCPKG_ROOT=/build/vcpkg`.\n\nThere are build configuration options which can be specified using the environment variable `CMAKE_PRESET` (choose from configurations in `CMakePresets.json`) - eg. `export CMAKE_PRESET=macos-arm64-vcpkg`.\n\n### Build Steps\nOnce the prerequisites are configured:\n\nBuild the project and run the tests from your source root directory using the following commands:\n\n1. `make init` - Initialize your build environment using the configured cmake and vcpkg setup - see above.\n2. `make` - Incremental build and run the tests.\n3. `make build` - Incremental build.\n4. `make unit` - Run built unit tests.\n\n### Docker Build\nWe also provide Dockerfiles for building and running this in an isolated\nenvironment. If you don't wish to get vcpkg set up on your build machine, this can be an alternative\nquick way to get started.\n\n1. `make docker-setup` - Build required base images and setup vcpkg, prerequisite for running commands below \n2. `make docker-build` - Build rmqcpp in the container using vcpkg \n3. `make docker-unit`  - Build rmqcpp and run unit tests in the container\n4. `make docker-shell` - Get an interactive shell within the build environment container\n\n## Installation\n\nAt present, we do not provide any pre-built releases and we expect users to\nbuild from source. If you are interested in having a pre-built release for your\npreferred package management system, please open an [issue](../../issues/new/choose) to let us know.\n\n## Using `rmqcpp` in your Application\n\n### With vcpkg\n\n1. Add `rmqcpp` in your `vcpkg.json` file to specify dependency:\n```\n{\n    \"$schema\": \"https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json\",\n    \"name\": \"testproj\",\n    \"version\": \"1.0.0\",\n    \"dependencies\": [\n      \"rmqcpp\"\n    ]\n}\n```\n\n2. In your `CMakeLists.txt` add `find_package(rmqcpp REQUIRED)` - which will install `rmqcpp` with all its dependencies.\n\n3. Use the namespace `rmqcpp::` to link to the library, for example - `target_link_libraries(testproj PUBLIC rmqcpp::rmq)`\n\n### With git submodule\n\nSetup your project with a git submodule to this repository:\n\n```\n$ tree\n.\n`-- myapplication\n|   |-- CMakeLists.txt\n|   |-- main.cpp\n|   `-- rmqcpp\n|   |   |-- CMakeLists.txt\n|   |   |-- CMakePresets.json\n|   |   |-- CONTRIBUTING.md\n|   |   |-- LICENSE\n|   |   |-- Makefile\n|   |   |-- README.md\n|   |   |-- ...\n|   |-- vcpkg.json\n```\n\nSample `CMakeLists.txt`:\n```\ncmake_minimum_required(VERSION 3.25)\nproject(myapp)\n\nfind_package(bal REQUIRED)\nadd_subdirectory(rmqcpp)\n\nadd_executable(myapplication main.cpp)\n\ntarget_link_libraries(myapplication rmq bal)\n```\n\nExample cmake command to configure this application build:\n\n```\n$ cmake -DCMAKE_TOOLCHAIN_FILE=${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake -DCMAKE_INSTALL_LIBDIR=lib64 -DCMAKE_CXX_STANDARD=17 ..\n```\n\n## Contributions\n\nWe ❤️ contributions.\n\nHave you had a good experience with this project? Why not share some love and contribute code, or just let us know about any issues you had with it?\n\nWe welcome issue reports [here](../../issues); be sure to choose the proper issue template for your issue, so that we can be sure you're providing the necessary information.\n\nBefore sending a [Pull Request](../../pulls), please make sure you read our\n[Contribution Guidelines](https://github.com/bloomberg/.github/blob/main/CONTRIBUTING.md).\n\n## License\n\nPlease read the [LICENSE](LICENSE) file.\n\n## Code of Conduct\n\nThis project has adopted a [Code of Conduct](https://github.com/bloomberg/.github/blob/main/CODE_OF_CONDUCT.md).\nIf you have any concerns about the Code, or behavior which you have experienced in the project, please\ncontact us at opensource@bloomberg.net.\n\n## Security Vulnerability Reporting\n\nPlease refer to the project [Security Policy](SECURITY.md).\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbloomberg%2Frmqcpp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbloomberg%2Frmqcpp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbloomberg%2Frmqcpp/lists"}