Skip to content

Commit

Permalink
readd service package (#2026)
Browse files Browse the repository at this point in the history
  • Loading branch information
asim committed Sep 26, 2020
1 parent 6e2c9e7 commit d8f17ac
Show file tree
Hide file tree
Showing 9 changed files with 1,000 additions and 0 deletions.
129 changes: 129 additions & 0 deletions service/grpc/grpc.go
@@ -0,0 +1,129 @@
package grpc

import (
"github.com/micro/go-micro/v3/client"
gclient "github.com/micro/go-micro/v3/client/grpc"
"github.com/micro/go-micro/v3/model"
"github.com/micro/go-micro/v3/server"
gserver "github.com/micro/go-micro/v3/server/grpc"
"github.com/micro/go-micro/v3/service"
)

type grpcService struct {
opts service.Options
}

func newService(opts ...service.Option) service.Service {
options := service.NewOptions(opts...)

return &grpcService{
opts: options,
}
}

func (s *grpcService) Name() string {
return s.opts.Server.Options().Name
}

// Init initialises options. Additionally it calls cmd.Init
// which parses command line flags. cmd.Init is only called
// on first Init.
func (s *grpcService) Init(opts ...service.Option) {
// process options
for _, o := range opts {
o(&s.opts)
}
}

func (s *grpcService) Options() service.Options {
return s.opts
}

func (s *grpcService) Client() client.Client {
return s.opts.Client
}

func (s *grpcService) Server() server.Server {
return s.opts.Server
}

func (s *grpcService) Model() model.Model {
return s.opts.Model
}

func (s *grpcService) String() string {
return "grpc"
}

func (s *grpcService) Start() error {
for _, fn := range s.opts.BeforeStart {
if err := fn(); err != nil {
return err
}
}

if err := s.opts.Server.Start(); err != nil {
return err
}

for _, fn := range s.opts.AfterStart {
if err := fn(); err != nil {
return err
}
}

return nil
}

func (s *grpcService) Stop() error {
var gerr error

for _, fn := range s.opts.BeforeStop {
if err := fn(); err != nil {
gerr = err
}
}

if err := s.opts.Server.Stop(); err != nil {
return err
}

for _, fn := range s.opts.AfterStop {
if err := fn(); err != nil {
gerr = err
}
}

return gerr
}

func (s *grpcService) Run() error {
if err := s.Start(); err != nil {
return err
}

// wait on context cancel
<-s.opts.Context.Done()

return s.Stop()
}

// NewService returns a grpc service compatible with go-micro.Service
func NewService(opts ...service.Option) service.Service {
// our grpc client
c := gclient.NewClient()
// our grpc server
s := gserver.NewServer()

// create options with priority for our opts
options := []service.Option{
service.Client(c),
service.Server(s),
}

// append passed in opts
options = append(options, opts...)

// generate and return a service
return newService(options...)
}
155 changes: 155 additions & 0 deletions service/grpc/grpc_test.go
@@ -0,0 +1,155 @@
package grpc

import (
"context"
"crypto/tls"
"sync"
"testing"
"time"

"github.com/micro/go-micro/v3/registry/memory"
"github.com/micro/go-micro/v3/service"
hello "github.com/micro/go-micro/v3/service/grpc/proto"
mls "github.com/micro/go-micro/v3/util/tls"
)

type testHandler struct{}

func (t *testHandler) Call(ctx context.Context, req *hello.Request, rsp *hello.Response) error {
rsp.Msg = "Hello " + req.Name
return nil
}

func TestGRPCService(t *testing.T) {
var wg sync.WaitGroup
wg.Add(1)

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

// create memory registry
r := memory.NewRegistry()

// create GRPC service
service := NewService(
service.Name("test.service"),
service.Registry(r),
service.AfterStart(func() error {
wg.Done()
return nil
}),
service.Context(ctx),
)

// register test handler
hello.RegisterTestHandler(service.Server(), &testHandler{})

// run service
errCh := make(chan error, 1)
go func() {
defer close(errCh)
errCh <- service.Run()
}()

// wait for start
wg.Wait()

// create client
test := hello.NewTestService("test.service", service.Client())

// call service
ctx2, cancel2 := context.WithTimeout(context.Background(), time.Duration(time.Second))
defer cancel2()
rsp, err := test.Call(ctx2, &hello.Request{
Name: "John",
})
if err != nil {
t.Fatal(err)
}

// check server
select {
case err := <-errCh:
t.Fatal(err)
case <-time.After(time.Second):
break
}

// check message
if rsp.Msg != "Hello John" {
t.Fatalf("unexpected response %s", rsp.Msg)
}
}

func TestGRPCTLSService(t *testing.T) {
var wg sync.WaitGroup
wg.Add(1)

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

// create memory registry
r := memory.NewRegistry()

// create cert
cert, err := mls.Certificate("test.service")
if err != nil {
t.Fatal(err)
}
config := &tls.Config{
Certificates: []tls.Certificate{cert},
InsecureSkipVerify: true,
}

// create GRPC service
service := NewService(
service.Name("test.service"),
service.Registry(r),
service.AfterStart(func() error {
wg.Done()
return nil
}),
service.Context(ctx),
// set TLS config
WithTLS(config),
)

// register test handler
hello.RegisterTestHandler(service.Server(), &testHandler{})

// run service
errCh := make(chan error, 1)
go func() {
defer close(errCh)
errCh <- service.Run()
}()

// wait for start
wg.Wait()

// create client
test := hello.NewTestService("test.service", service.Client())

// call service
ctx2, cancel2 := context.WithTimeout(context.Background(), time.Duration(time.Second))
defer cancel2()
rsp, err := test.Call(ctx2, &hello.Request{
Name: "John",
})
if err != nil {
t.Fatal(err)
}

// check server
select {
case err := <-errCh:
t.Fatal(err)
case <-time.After(time.Second):
break
}

// check message
if rsp.Msg != "Hello John" {
t.Fatalf("unexpected response %s", rsp.Msg)
}
}
21 changes: 21 additions & 0 deletions service/grpc/options.go
@@ -0,0 +1,21 @@
package grpc

import (
"crypto/tls"

gc "github.com/micro/go-micro/v3/client/grpc"
gs "github.com/micro/go-micro/v3/server/grpc"
"github.com/micro/go-micro/v3/service"
)

// WithTLS sets the TLS config for the service
func WithTLS(t *tls.Config) service.Option {
return func(o *service.Options) {
o.Client.Init(
gc.AuthTLS(t),
)
o.Server.Init(
gs.AuthTLS(t),
)
}
}

0 comments on commit d8f17ac

Please sign in to comment.