Skip to content

Add gRPC support to mains plugin#215

Merged
raphael merged 1 commit into
v3from
feat/mains-grpc-support
Oct 16, 2025
Merged

Add gRPC support to mains plugin#215
raphael merged 1 commit into
v3from
feat/mains-grpc-support

Conversation

@raphael
Copy link
Copy Markdown
Member

@raphael raphael commented Oct 16, 2025

This PR enhances the mains plugin to support gRPC servers in addition to HTTP servers, addressing #209.

Summary

The mains plugin now intelligently generates server code based on what transports are actually defined in the Goa design:

  • HTTP-only services: Generates HTTP server initialization only
  • gRPC-only services: Generates gRPC server initialization only
  • Hybrid services: Generates both HTTP and gRPC servers
  • Metrics server: Always generated on a separate port for health/metrics/debug endpoints

Key Changes

1. Conditional Transport Generation

  • Scans the Goa DSL to detect which transports (HTTP/gRPC) are actually used
  • Only generates server initialization code for transports that are defined
  • Conditionally imports transport-specific packages (e.g., gorilla/websocket, google.golang.org/grpc)

2. Fixed Bugs

  • Duplicate package/import: Removed duplicate package main and import blocks from template (now handled by codegen.Header())
  • WebSocket detection: Fixed incorrect streaming detection logic (Stream value of 0 means no streaming, not NoStreamKind=1)

3. gRPC Server Support

  • Proper gRPC server initialization with OpenTelemetry instrumentation
  • gRPC interceptors for logging and debug (matching HTTP middleware pattern)
  • Server reflection for easier testing with grpcurl
  • Graceful shutdown support

4. Import Management

  • Base imports always included (context, flag, fmt, http, os, signal, sync, syscall, time)
  • OTel imports always included (for metrics server)
  • net package only imported if gRPC is used
  • google.golang.org/grpc packages only imported if gRPC is used
  • gorilla/websocket only imported if streaming endpoints are defined

Example

For a service with both HTTP and gRPC endpoints:

var _ = Service("calc", func() {
    Method("add", func() {
        Payload(func() {
            Field(1, "a", Int)
            Field(2, "b", Int)
        })
        Result(Int)
        HTTP(func() { GET("/add/{a}/{b}") })
        GRPC(func() {})
    })
})

The generated main.go now includes:

  • HTTP server on :8080
  • gRPC server on :9090
  • Metrics server on :8081
  • Proper OTel instrumentation for both
  • Graceful shutdown for both

Testing

Tested with:

  • HTTP-only service ✅
  • gRPC-only service ✅
  • HTTP + gRPC hybrid service ✅
  • Service with WebSocket streaming ✅
  • Service with no streaming ✅

All generated code compiles and runs successfully.

Fixes #209

This change enhances the mains plugin to support gRPC servers in addition to HTTP servers, addressing issue #209.

Key changes:
- Only generate HTTP server code when the service design includes HTTP endpoints
- Only generate gRPC server code when the service design includes gRPC endpoints
- Always generate the metrics HTTP server (health/metrics/debug endpoints)
- Fix duplicate package/import declarations in generated main.go
- Fix WebSocket detection bug (Stream value of 0 means no streaming, not NoStreamKind)
- Conditionally import transport-specific packages based on what's actually used
- Add proper OTel instrumentation for gRPC servers
- Implement graceful shutdown for both HTTP and gRPC servers

The plugin now:
1. Scans the DSL for HTTP and gRPC endpoint definitions
2. Conditionally generates server initialization code based on transports used
3. Manages imports efficiently (only includes websocket, grpc packages when needed)
4. Provides a unified main.go that can run HTTP-only, gRPC-only, or both transports
5. Maintains the existing single-service (services/<svc>/cmd/<svc>) and multi-service (cmd/<server>) layouts

Fixes #209
@raphael raphael merged commit 99f325a into v3 Oct 16, 2025
5 checks passed
@raphael raphael deleted the feat/mains-grpc-support branch October 16, 2025 07:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

mains plugin generates faulty main.go file (package and import duplicated)

1 participant