Skip to content

Commit

Permalink
add service test and shutdown based on context
Browse files Browse the repository at this point in the history
  • Loading branch information
Asim Aslam committed Jan 7, 2017
1 parent e84e5ae commit 942985c
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 5 deletions.
24 changes: 24 additions & 0 deletions options.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ type Options struct {

// Before and After funcs
BeforeStart []func() error
BeforeStop []func() error
AfterStart []func() error
AfterStop []func() error

// Other options for implementations of the interface
Expand All @@ -43,6 +45,7 @@ func newOptions(opts ...Option) Options {
Server: server.DefaultServer,
Registry: registry.DefaultRegistry,
Transport: transport.DefaultTransport,
Context: context.Background(),
}

for _, o := range opts {
Expand Down Expand Up @@ -73,6 +76,15 @@ func Client(c client.Client) Option {
}
}

// Context specifies a context for the service
// Can be used to signal shutdown of the service
// Can be used for extra option values
func Context(ctx context.Context) Option {
return func(o *Options) {
o.Context = ctx
}
}

func Server(s server.Server) Option {
return func(o *Options) {
o.Server = s
Expand Down Expand Up @@ -204,6 +216,18 @@ func BeforeStart(fn func() error) Option {
}
}

func BeforeStop(fn func() error) Option {
return func(o *Options) {
o.BeforeStop = append(o.BeforeStop, fn)
}
}

func AfterStart(fn func() error) Option {
return func(o *Options) {
o.AfterStart = append(o.AfterStart, fn)
}
}

func AfterStop(fn func() error) Option {
return func(o *Options) {
o.AfterStop = append(o.AfterStop, fn)
Expand Down
27 changes: 22 additions & 5 deletions service.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,24 @@ func (s *service) Start() error {
return err
}

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

return nil
}

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

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

if err := s.opts.Server.Deregister(); err != nil {
return err
}
Expand All @@ -132,15 +146,12 @@ func (s *service) Stop() error {
return err
}

var gerr error
for _, fn := range s.opts.AfterStop {
if err := fn(); err != nil {
// should we bail if it fails?
// other funcs will not be executed
// seems wrong
gerr = err
}
}

return gerr
}

Expand All @@ -155,7 +166,13 @@ func (s *service) Run() error {

ch := make(chan os.Signal, 1)
signal.Notify(ch, syscall.SIGTERM, syscall.SIGINT, syscall.SIGKILL)
<-ch

select {
// wait on kill signal
case <-ch:
// wait on context cancel
case <-s.opts.Context.Done():
}

// exit reg loop
close(ex)
Expand Down
65 changes: 65 additions & 0 deletions service_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package micro

import (
"sync"
"testing"

"github.com/micro/go-micro/registry/mock"
proto "github.com/micro/go-micro/server/debug/proto"

"golang.org/x/net/context"
)

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

// cancellation context
ctx, cancel := context.WithCancel(context.Background())

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

// we can't test service.Init as it parses the command line
// service.Init()

// register handler
// do that later

go func() {
// wait for start
wg.Wait()

// test call debug
req := service.Client().NewRequest(
"test.service",
"Debug.Health",
new(proto.HealthRequest),
)

rsp := new(proto.HealthResponse)

err := service.Client().Call(context.TODO(), req, rsp)
if err != nil {
t.Fatal(err)
}

if rsp.Status != "ok" {
t.Fatalf("service response: %s", rsp.Status)
}

// shutdown the service
cancel()
}()

// run service
service.Run()
}

0 comments on commit 942985c

Please sign in to comment.