ktr0731 / grpcdynamic

dynamic gRPC registration mechanism

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

grpcdynamic

Dynamic gRPC registration mechanism.

Usage

grpcdynamic provides dynamic gRPC service registration with arbitrary implementations.

package main

import (
	"context"
	"fmt"
	"log"
	"net"

	"github.com/ktr0731/grpcdynamic"

	"google.golang.org/grpc"
	"google.golang.org/grpc/reflection"
)

type req struct {
	Name string
}

type res struct {
	Message string
}

func main() {
	service := grpcdynamic.NewService("api.Example")
	service.RegisterUnaryMethod("Unary", new(req), new(res), func(ctx context.Context, in interface{}) (interface{}, error) {
		req := in.(*req)
		return &res{Message: fmt.Sprintf("hi, %s", req.Name)}, nil
	})
	srv := grpcdynamic.NewServer([]*grpcdynamic.Service{service})
	reflection.Register(srv)

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	done := make(chan struct{})
	go func() {
		if err := startServer(ctx, srv); err != nil {
			log.Fatal(err)
		}
		close(done)
	}()

	res, err := callUnaryMethod(service.FullMethodName("Unary"))
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(res.Message)

	cancel()
	<-done
}

func startServer(ctx context.Context, srv *grpc.Server) error {
	l, err := net.Listen("tcp", ":50051")
	if err != nil {
		return err
	}

	go func() {
		<-ctx.Done()
		srv.Stop()
	}()

	if err := srv.Serve(l); err != nil {
		return err
	}
	return nil
}

func callUnaryMethod(name string) (*res, error) {
	conn, err := grpc.Dial(
		":50051",
		grpc.WithInsecure(),
		grpc.WithDefaultCallOptions(grpc.CallContentSubtype(grpcdynamic.CodecName)),
	)
	if err != nil {
		return nil, err
	}
	defer conn.Close()

	var res res
	if err := conn.Invoke(context.Background(), name, &req{Name: "foo"}, &res); err != nil {
		return nil, err
	}
	return &res, nil
}

About

dynamic gRPC registration mechanism

License:MIT License


Languages

Language:Go 100.0%