Simple RPC with Protobuf Services
Go to file
Luke Murphy afeb033e89
All checks were successful
continuous-integration/drone/push Build is passing
Fix up tox config
2020-08-09 03:46:59 +02:00
example Add a complete greeter example 2020-08-09 03:35:01 +02:00
hrpc Add generaton cli entrypoint 2020-08-09 02:52:58 +02:00
.drone.yml Add drone config 2020-08-09 01:34:56 +02:00
.gitignore Init hrpc 2020-08-09 01:33:07 +02:00
CHANGELOG.md Init hrpc 2020-08-09 01:33:07 +02:00
LICENSE Init hrpc 2020-08-09 01:33:07 +02:00
poetry.lock Add protoc and purerpc plugin 2020-08-09 01:39:44 +02:00
pyproject.toml Fix up tox config 2020-08-09 03:46:59 +02:00
README.md Add a complete greeter example 2020-08-09 03:35:01 +02:00

hrpc

Build Status

Simple RPC with Protobuf Services

Install

$ pip install hrpc

Example

TLDR; See the example directory

Define an RPC service in a greeter.proto.

syntax = "proto3";

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply) {}
  rpc SayHelloGoodbye (HelloRequest) returns (stream HelloReply) {}
  rpc SayHelloToMany (stream HelloRequest) returns (stream HelloReply) {}
  rpc SayHelloToManyAtOnce (stream HelloRequest) returns (HelloReply) {}
}

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}

Then generate the services and stubs with hrpc.

$ pip install hrpc
$ hrpc greeter.proto

This creates greeter_gprc.py (services) and greeter_pb2.py (stubs) files.

You can then write a async-ready server.

"""Greeter server."""

from greeter_grpc import GreeterServicer
from greeter_pb2 import HelloReply, HelloRequest
from purerpc import Server


class Greeter(GreeterServicer):
    async def SayHello(self, message):
        return HelloReply(message="Hello, " + message.name)

    async def SayHelloToMany(self, input_messages):
        async for message in input_messages:
            yield HelloReply(message=f"Hello, {message.name}")


if __name__ == "__main__":
    server = Server(50055)
    server.add_service(Greeter().service)
    server.serve(backend="trio")

And a client.

"""Greeter client."""

import anyio
import purerpc
from greeter_grpc import GreeterStub
from greeter_pb2 import HelloReply, HelloRequest


async def gen():
    for i in range(5):
        yield HelloRequest(name=str(i))


async def main():
    async with purerpc.insecure_channel("localhost", 50055) as channel:
        stub = GreeterStub(channel)
        reply = await stub.SayHello(HelloRequest(name="World"))
        print(reply.message)

        async for reply in stub.SayHelloToMany(gen()):
            print(reply.message)


if __name__ == "__main__":
    anyio.run(main, backend="trio")

And run them in separate terminals to see the output.

$ python server.py # terminal 1
$ python client.py # terminal 2

Output:

Hello, World
Hello, 0
Hello, 1
Hello, 2
Hello, 3
Hello, 4

Go forth and Remote Procedure Call.

The person who invented the term RPC