Skip to content

Commit 8bcc1c4

Browse files
authored
feat(protoc-gen-elixir-gprc): add elixir grpc plugin (#11)
Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
1 parent c526a63 commit 8bcc1c4

File tree

6 files changed

+997
-5
lines changed

6 files changed

+997
-5
lines changed

.github/.release-please-config.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424
"packages": {
2525
"cmd/protoc-gen-connect-go-servicestruct": {
2626
"component": "protoc-gen-connect-go-servicestruct"
27+
},
28+
"cmd/protoc-gen-elixir-grpc": {
29+
"component": "protoc-gen-elixir-grpc"
2730
}
2831
},
2932
"plugins": [

.gitignore

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,6 @@ go.work.sum
3131
# .idea/
3232
# .vscode/
3333

34-
# Generated build files
35-
protoc-gen-connect-go-servicestruct
36-
protoc-gen-connect-go-servicestruct.wasm
34+
# Generated protoc plugin binaries (root directory only)
35+
/protoc-gen-*
36+
/protoc-gen-*.wasm

Taskfile.yml

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,23 @@ tasks:
6969
- go build ./...
7070

7171
build-plugin:
72-
desc: Build the protoc plugin binary
72+
desc: Build all protoc plugin binaries
7373
cmds:
74-
- echo "Building protoc plugin binary..."
74+
- echo "Building protoc plugin binaries..."
7575
- go build -o protoc-gen-connect-go-servicestruct ./cmd/protoc-gen-connect-go-servicestruct
76+
- go build -o protoc-gen-elixir-grpc ./cmd/protoc-gen-elixir-grpc
77+
78+
build-plugin-go:
79+
desc: Build the Go Connect protoc plugin binary
80+
cmds:
81+
- echo "Building Go Connect protoc plugin binary..."
82+
- go build -o protoc-gen-connect-go-servicestruct ./cmd/protoc-gen-connect-go-servicestruct
83+
84+
build-plugin-elixir:
85+
desc: Build the Elixir gRPC protoc plugin binary
86+
cmds:
87+
- echo "Building Elixir gRPC protoc plugin binary..."
88+
- go build -o protoc-gen-elixir-grpc ./cmd/protoc-gen-elixir-grpc
7689

7790
dev-test:
7891
desc: Development workflow - fmt, vet, and generate coverage HTML
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
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

Comments
 (0)