Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/.release-please-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
"packages": {
"cmd/protoc-gen-connect-go-servicestruct": {
"component": "protoc-gen-connect-go-servicestruct"
},
"cmd/protoc-gen-elixir-grpc": {
"component": "protoc-gen-elixir-grpc"
}
},
"plugins": [
Expand Down
6 changes: 3 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,6 @@ go.work.sum
# .idea/
# .vscode/

# Generated build files
protoc-gen-connect-go-servicestruct
protoc-gen-connect-go-servicestruct.wasm
# Generated protoc plugin binaries (root directory only)
/protoc-gen-*
/protoc-gen-*.wasm
17 changes: 15 additions & 2 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,23 @@ tasks:
- go build ./...

build-plugin:
desc: Build the protoc plugin binary
desc: Build all protoc plugin binaries
cmds:
- echo "Building protoc plugin binary..."
- echo "Building protoc plugin binaries..."
- go build -o protoc-gen-connect-go-servicestruct ./cmd/protoc-gen-connect-go-servicestruct
- go build -o protoc-gen-elixir-grpc ./cmd/protoc-gen-elixir-grpc

build-plugin-go:
desc: Build the Go Connect protoc plugin binary
cmds:
- echo "Building Go Connect protoc plugin binary..."
- go build -o protoc-gen-connect-go-servicestruct ./cmd/protoc-gen-connect-go-servicestruct

build-plugin-elixir:
desc: Build the Elixir gRPC protoc plugin binary
cmds:
- echo "Building Elixir gRPC protoc plugin binary..."
- go build -o protoc-gen-elixir-grpc ./cmd/protoc-gen-elixir-grpc

dev-test:
desc: Development workflow - fmt, vet, and generate coverage HTML
Expand Down
86 changes: 86 additions & 0 deletions cmd/protoc-gen-elixir-grpc/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# protoc-gen-elixir-grpc

A protobuf compiler plugin that generates Elixir gRPC server modules with `defdelegate` patterns
for clean handler organization. **Requires `protoc-gen-elixir` as a dependency.**

## How-tos

### Installation

```bash
go install github.com/TrogonStack/protoc-gen/cmd/protoc-gen-elixir-grpc@latest
```

### Basic Usage

**Required**: This plugin must be used alongside `protoc-gen-elixir` as it generates server modules that reference
the protobuf message and service definitions:

```bash
protoc --elixir_out=lib --elixir-grpc_out=lib path/to/greeter.proto
```

### With buf

**Required**: Add to your `buf.gen.yaml` alongside the required `protoc-gen-elixir` plugin:

```yaml
version: v2
plugins:
- local: protoc-gen-elixir # Required dependency
out: lib
- local: protoc-gen-elixir-grpc
out: lib
```

Server modules are generated into the same directory structure as the protobuf definitions, with `.server.pb.ex` suffix.

### Basic Service Implementation

For more realistic applications that require dependencies like database connections, implement handlers
with proper dependency injection:

```elixir
# lib/helloworld/greeter/server/say_hello_handler.ex
defmodule Helloworld.Greeter.Server.SayHelloHandler do
def handle_message(request, _stream) do
# Your business logic with dependencies
case MyApp.Users.get_user_by_name(request.name) do
{:ok, user} ->
reply = %Helloworld.HelloReply{message: "Hello #{user.display_name}!"}
{:ok, reply}
{:error, :not_found} ->
raise GRPC.RPCError, status: :not_found, message: "User not found"
end
end
end

# lib/helloworld/greeter/server/say_goodbye_handler.ex
defmodule Helloworld.Greeter.Server.SayGoodbyeHandler do
def handle_message(request, _stream) do
case MyApp.Users.log_goodbye(request.name) do
:ok ->
reply = %Helloworld.GoodbyeReply{message: "Goodbye #{request.name}!"}
{:ok, reply}
{:error, reason} ->
raise GRPC.RPCError, status: :internal, message: "Failed to log goodbye: #{reason}"
end
end
end
```

## Explanations

### Overview

This plugin generates gRPC server modules that provide a convenient way to organize handler functions using
Elixir's `defdelegate` pattern. **This plugin requires `protoc-gen-elixir` to function** - it generates
server modules that reference the protobuf message and service definitions created by the standard Elixir
protobuf plugin.

### Features

- **Handler Delegation**: Uses `defdelegate` to separate transport concerns from business logic
- **Clean Organization**: Each RPC method gets its own dedicated handler module
- **Streaming Support**: Handles all gRPC method types automatically
- **Package Structure**: Maintains protobuf package hierarchy in generated modules
Loading