{"id":21446912,"url":"https://github.com/zerlok/brokrpc","last_synced_at":"2025-07-14T19:31:35.228Z","repository":{"id":259292099,"uuid":"872029592","full_name":"zerlok/BrokRPC","owner":"zerlok","description":"framework for gRPC like server-client communication over message brokers","archived":false,"fork":false,"pushed_at":"2024-11-21T17:00:15.000Z","size":251,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-11-21T18:18:07.053Z","etag":null,"topics":["amqp","grpc","message-broker","message-queue","protobuf","python"],"latest_commit_sha":null,"homepage":"","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/zerlok.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":"2024-10-13T15:50:20.000Z","updated_at":"2024-11-14T22:41:58.000Z","dependencies_parsed_at":"2024-10-24T05:45:26.376Z","dependency_job_id":"4600c1bd-9f85-4740-9edd-4358e0dfac5b","html_url":"https://github.com/zerlok/BrokRPC","commit_stats":null,"previous_names":["zerlok/protomq","zerlok/brokrpc"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zerlok%2FBrokRPC","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zerlok%2FBrokRPC/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zerlok%2FBrokRPC/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zerlok%2FBrokRPC/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zerlok","download_url":"https://codeload.github.com/zerlok/BrokRPC/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225994870,"owners_count":17556830,"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","grpc","message-broker","message-queue","protobuf","python"],"created_at":"2024-11-23T03:08:17.444Z","updated_at":"2025-07-14T19:31:35.222Z","avatar_url":"https://github.com/zerlok.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# BrokRPC\n\n[![Latest Version](https://img.shields.io/pypi/v/BrokRPC.svg)](https://pypi.python.org/pypi/BrokRPC)\n[![Python Supported versions](https://img.shields.io/pypi/pyversions/BrokRPC.svg)](https://pypi.python.org/pypi/BrokRPC)\n[![MyPy Strict](https://img.shields.io/badge/mypy-strict-blue)](https://mypy.readthedocs.io/en/stable/getting_started.html#strict-mode-and-configuration)\n[![Test Coverage](https://codecov.io/gh/zerlok/BrokRPC/branch/main/graph/badge.svg)](https://codecov.io/gh/zerlok/BrokRPC)\n[![Downloads](https://img.shields.io/pypi/dm/BrokRPC.svg)](https://pypistats.org/packages/BrokRPC)\n[![GitHub stars](https://img.shields.io/github/stars/zerlok/BrokRPC)](https://github.com/zerlok/BrokRPC/stargazers)\n\nBrokRPC (**Brok**er **R**emote **P**rocedure **C**all) is a framework for gRPC like server-client communication over \nmessage brokers.\n\n## key features\n\n* strict typing (even `disallow_any_expr=true`)\n* same protobuf structures as in gRPC\n* similar calls as in gRPC\n  * unary-unary\n  * (TODO) unary-stream\n  * (TODO) stream-unary\n  * (TODO) stream-stream\n* declarative style, abstract from broker commands (such as declare_exchange / queue_bind)\n* publisher \u0026 consumer middlewares\n* message serializers\n\n## codegen\n\nYou can generate python code for server \u0026 client from `.proto` files. \nThe [pyprotostuben](https://github.com/zerlok/pyprotostuben) project provides protoc plugin `protoc-gen-brokrpc`. See \npyprotostuben project example for more details.\n\nYou may configure codegen output using protobuf extensions from [buf schema registry](https://buf.build/zerlok/brokrpc).\n\n## supported brokers \u0026 protocols\n\n* [AMQP](https://www.rabbitmq.com/tutorials/amqp-concepts)\n  * [aiormq](https://github.com/mosquito/aiormq)\n* (TODO) redis\n* (TODO) kafka\n* (TODO) NATS\n\n## usage\n\n[pypi package](https://pypi.python.org/pypi/BrokRPC)\n\ninstall with your favorite python package manager\n\n```shell\npip install BrokRPC[aiormq]\n```\n\n### Broker\n\nuse Broker as high level API to create consumers \u0026 publishers\n\n```python\nfrom brokrpc.broker import Broker\n\n# create \u0026 connect to broker with specified params\nasync with Broker(...) as broker:\n    assert broker.is_connected\n    # work with broker\n    ...\n```\n\n### Consumer\n\n```python\nimport asyncio\nfrom brokrpc.broker import Broker\nfrom brokrpc.message import Message\nfrom brokrpc.options import BindingOptions, QueueOptions, ExchangeOptions\nfrom brokrpc.serializer.json import JSONSerializer\n\n\nasync def register_consumer(broker: Broker) -\u003e None:\n    # define consumer function (you also can use async function \u0026 `Consumer` interface).\n    def consume_binary_message(message: Message[bytes]) -\u003e None:\n        print(message)\n  \n    # consumer is not attached yet\n  \n    async with broker.consumer(consume_binary_message, BindingOptions(binding_keys=[\"my-consumer\"])):\n        # in this code block consumer is attached to broker and can receive messages\n        ...\n  \n    # outside CM consumer is detached from broker and cannot receive messages\n  \n    async def consume_json(message: Message[object]) -\u003e bool:\n        obj = message.body\n        if not isinstance(obj, dict):\n            return False\n    \n        username = obj.get(\"username\")\n        if not username:\n            return False\n        \n        print(f\"Hello, {username}\")\n        await asyncio.sleep(1.0)  # simulate long processing\n    \n        return True\n  \n    async with broker.consumer(\n        consume_json,\n        BindingOptions(\n            exchange=ExchangeOptions(name=\"json\"),\n            binding_keys=[\"my-json-consumer\"],\n            queue=QueueOptions(name=\"jsons\", auto_delete=True),\n        ),\n        serializer=JSONSerializer(),\n    ):\n        ...\n```\n\n### ConsumerMiddlewares\n\n...\n\n### Publisher\n\n```python\nfrom brokrpc.broker import Broker\nfrom brokrpc.message import create_message\nfrom brokrpc.serializer.json import JSONSerializer\n\n\nasync def publish_messages(broker: Broker) -\u003e None:\n    async with broker.publisher() as pub:\n        # in this code block publisher is attached to broker and can send messages\n        await pub.publish(create_message(body=b\"this is a binary message\", routing_key=\"test-consumer\"))\n\n    async with broker.publisher(serializer=JSONSerializer()) as json_pub:\n        await json_pub.publish(create_message(body={\"username\": \"John Smith\"}, routing_key=\"my-json-consumer\"))\n```\n\n### Publisher Middlewares\n\n...\n\n### Message\n\n* `Message`\n* `SomeMessage`\n* `EncodedMessage`\n* `DecodedMessage`\n\n### Serializer\n\n* `JSONSerializer`\n* `ProtobufSerializer`\n\n### RPC Server\n\n* `Server`\n\n### RPC Handler\n\n...\n\n### RPC Client\n\n* `Client`\n\n### RPC Caller\n\n...\n\n## RPC example\n\n### RPC server\n\nrun server process with following code\n\n```python\nimport asyncio\n\nfrom brokrpc.broker import Broker\nfrom brokrpc.options import ExchangeOptions\nfrom brokrpc.rpc.model import Request\nfrom brokrpc.rpc.server import Server\nfrom brokrpc.serializer.json import JSONSerializer\n\n\n# define app RPC handler\nasync def handle_request(request: Request[object]) -\u003e str:\n    print(f\"{request=!s}\")\n    print(f\"{request.body=}\")\n    return f\"I greet you, {request.body}\"\n\n\nasync def main() -\u003e None:\n    # create broker \u0026 RPC server\n    broker = Broker(\n        options=\"amqp://guest:guest@localhost:5672/\",\n        default_exchange=ExchangeOptions(name=\"simple-test-app\"),\n    )\n    server = Server(broker)\n\n    # register RPC handler\n    server.register_unary_unary_handler(\n        func=handle_request,\n        routing_key=\"test-greeting\",\n        serializer=JSONSerializer(),\n    )\n\n    # connect to broker\n    async with broker:\n        # start RPC server until SIGINT or SIGTERM\n        await server.run_until_terminated()\n\n\nif __name__ == \"__main__\":\n    asyncio.run(main())\n```\n\n### RPC client\n\nmake a call to RPC server via RPC client with following code\n\n```python\nimport asyncio\n\nfrom brokrpc.broker import Broker\nfrom brokrpc.options import ExchangeOptions\nfrom brokrpc.rpc.client import Client\nfrom brokrpc.serializer.json import JSONSerializer\n\n\nasync def main() -\u003e None:\n    async with (\n        # create \u0026 connect to broker\n        Broker(\n            options=\"amqp://guest:guest@localhost:5672/\",\n            default_exchange=ExchangeOptions(name=\"simple-test-app\"),\n        ) as broker,\n        # create RPC client \u0026 get RPC caller\n        Client(broker).unary_unary_caller(\n            routing_key=\"test-greeting\",\n            serializer=JSONSerializer(),\n        ) as caller,\n    ):\n        # publish app message \u0026 receive RPC response\n        response = await caller.invoke(\"John\")\n\n        print(response)\n        print(f\"{response.body=}\")\n\n\nif __name__ == \"__main__\":\n    asyncio.run(main())\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzerlok%2Fbrokrpc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzerlok%2Fbrokrpc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzerlok%2Fbrokrpc/lists"}