|
| 1 | +# protoc-gen-elixir-grpc |
| 2 | + |
| 3 | +A protobuf compiler plugin that generates Elixir gRPC server modules with `defdelegate` patterns |
| 4 | +for clean handler organization. **Requires `protoc-gen-elixir` as a dependency.** |
| 5 | + |
| 6 | +## How-tos |
| 7 | + |
| 8 | +### Installation |
| 9 | + |
| 10 | +```bash |
| 11 | +go install github.com/TrogonStack/protoc-gen/cmd/protoc-gen-elixir-grpc@latest |
| 12 | +``` |
| 13 | + |
| 14 | +### Basic Usage |
| 15 | + |
| 16 | +**Required**: This plugin must be used alongside `protoc-gen-elixir` as it generates server modules that reference |
| 17 | +the protobuf message and service definitions: |
| 18 | + |
| 19 | +```bash |
| 20 | +protoc --elixir_out=lib --elixir-grpc_out=lib path/to/greeter.proto |
| 21 | +``` |
| 22 | + |
| 23 | +### With buf |
| 24 | + |
| 25 | +**Required**: Add to your `buf.gen.yaml` alongside the required `protoc-gen-elixir` plugin: |
| 26 | + |
| 27 | +```yaml |
| 28 | +version: v2 |
| 29 | +plugins: |
| 30 | + - local: protoc-gen-elixir # Required dependency |
| 31 | + out: lib |
| 32 | + - local: protoc-gen-elixir-grpc |
| 33 | + out: lib |
| 34 | +``` |
| 35 | +
|
| 36 | +Server modules are generated into the same directory structure as the protobuf definitions, with `.server.pb.ex` suffix. |
| 37 | + |
| 38 | +### Basic Service Implementation |
| 39 | + |
| 40 | +For more realistic applications that require dependencies like database connections, implement handlers |
| 41 | +with proper dependency injection: |
| 42 | + |
| 43 | +```elixir |
| 44 | +# lib/helloworld/greeter/server/say_hello_handler.ex |
| 45 | +defmodule Helloworld.Greeter.Server.SayHelloHandler do |
| 46 | + def handle_message(request, _stream) do |
| 47 | + # Your business logic with dependencies |
| 48 | + case MyApp.Users.get_user_by_name(request.name) do |
| 49 | + {:ok, user} -> |
| 50 | + reply = %Helloworld.HelloReply{message: "Hello #{user.display_name}!"} |
| 51 | + {:ok, reply} |
| 52 | + {:error, :not_found} -> |
| 53 | + raise GRPC.RPCError, status: :not_found, message: "User not found" |
| 54 | + end |
| 55 | + end |
| 56 | +end |
| 57 | +
|
| 58 | +# lib/helloworld/greeter/server/say_goodbye_handler.ex |
| 59 | +defmodule Helloworld.Greeter.Server.SayGoodbyeHandler do |
| 60 | + def handle_message(request, _stream) do |
| 61 | + case MyApp.Users.log_goodbye(request.name) do |
| 62 | + :ok -> |
| 63 | + reply = %Helloworld.GoodbyeReply{message: "Goodbye #{request.name}!"} |
| 64 | + {:ok, reply} |
| 65 | + {:error, reason} -> |
| 66 | + raise GRPC.RPCError, status: :internal, message: "Failed to log goodbye: #{reason}" |
| 67 | + end |
| 68 | + end |
| 69 | +end |
| 70 | +``` |
| 71 | + |
| 72 | +## Explanations |
| 73 | + |
| 74 | +### Overview |
| 75 | + |
| 76 | +This plugin generates gRPC server modules that provide a convenient way to organize handler functions using |
| 77 | +Elixir's `defdelegate` pattern. **This plugin requires `protoc-gen-elixir` to function** - it generates |
| 78 | +server modules that reference the protobuf message and service definitions created by the standard Elixir |
| 79 | +protobuf plugin. |
| 80 | + |
| 81 | +### Features |
| 82 | + |
| 83 | +- **Handler Delegation**: Uses `defdelegate` to separate transport concerns from business logic |
| 84 | +- **Clean Organization**: Each RPC method gets its own dedicated handler module |
| 85 | +- **Streaming Support**: Handles all gRPC method types automatically |
| 86 | +- **Package Structure**: Maintains protobuf package hierarchy in generated modules |
0 commit comments