add service test and shutdown based on context
This commit is contained in:
parent
e84e5ae303
commit
942985ce51
24
options.go
24
options.go
@ -28,6 +28,8 @@ type Options struct {
|
|||||||
|
|
||||||
// Before and After funcs
|
// Before and After funcs
|
||||||
BeforeStart []func() error
|
BeforeStart []func() error
|
||||||
|
BeforeStop []func() error
|
||||||
|
AfterStart []func() error
|
||||||
AfterStop []func() error
|
AfterStop []func() error
|
||||||
|
|
||||||
// Other options for implementations of the interface
|
// Other options for implementations of the interface
|
||||||
@ -43,6 +45,7 @@ func newOptions(opts ...Option) Options {
|
|||||||
Server: server.DefaultServer,
|
Server: server.DefaultServer,
|
||||||
Registry: registry.DefaultRegistry,
|
Registry: registry.DefaultRegistry,
|
||||||
Transport: transport.DefaultTransport,
|
Transport: transport.DefaultTransport,
|
||||||
|
Context: context.Background(),
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, o := range opts {
|
for _, o := range opts {
|
||||||
@ -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 {
|
func Server(s server.Server) Option {
|
||||||
return func(o *Options) {
|
return func(o *Options) {
|
||||||
o.Server = s
|
o.Server = s
|
||||||
@ -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 {
|
func AfterStop(fn func() error) Option {
|
||||||
return func(o *Options) {
|
return func(o *Options) {
|
||||||
o.AfterStop = append(o.AfterStop, fn)
|
o.AfterStop = append(o.AfterStop, fn)
|
||||||
|
27
service.go
27
service.go
@ -120,10 +120,24 @@ func (s *service) Start() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, fn := range s.opts.AfterStart {
|
||||||
|
if err := fn(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *service) Stop() error {
|
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 {
|
if err := s.opts.Server.Deregister(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -132,15 +146,12 @@ func (s *service) Stop() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var gerr error
|
|
||||||
for _, fn := range s.opts.AfterStop {
|
for _, fn := range s.opts.AfterStop {
|
||||||
if err := fn(); err != nil {
|
if err := fn(); err != nil {
|
||||||
// should we bail if it fails?
|
|
||||||
// other funcs will not be executed
|
|
||||||
// seems wrong
|
|
||||||
gerr = err
|
gerr = err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return gerr
|
return gerr
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,7 +166,13 @@ func (s *service) Run() error {
|
|||||||
|
|
||||||
ch := make(chan os.Signal, 1)
|
ch := make(chan os.Signal, 1)
|
||||||
signal.Notify(ch, syscall.SIGTERM, syscall.SIGINT, syscall.SIGKILL)
|
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
|
// exit reg loop
|
||||||
close(ex)
|
close(ex)
|
||||||
|
65
service_test.go
Normal file
65
service_test.go
Normal file
@ -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()
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user