add Live/Ready/Health methods
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
This commit is contained in:
parent
ae97023092
commit
36b7b9f5fb
@ -46,6 +46,12 @@ type Broker interface {
|
|||||||
BatchSubscribe(ctx context.Context, topic string, h BatchHandler, opts ...SubscribeOption) (Subscriber, error)
|
BatchSubscribe(ctx context.Context, topic string, h BatchHandler, opts ...SubscribeOption) (Subscriber, error)
|
||||||
// String type of broker
|
// String type of broker
|
||||||
String() string
|
String() string
|
||||||
|
// Live returns broker liveness
|
||||||
|
Live() bool
|
||||||
|
// Ready returns broker readiness
|
||||||
|
Ready() bool
|
||||||
|
// Health returns broker health
|
||||||
|
Health() bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
@ -339,6 +339,18 @@ func (m *memoryBroker) Name() string {
|
|||||||
return m.opts.Name
|
return m.opts.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *memoryBroker) Live() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *memoryBroker) Ready() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *memoryBroker) Health() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func (m *memoryEvent) Topic() string {
|
func (m *memoryEvent) Topic() string {
|
||||||
return m.topic
|
return m.topic
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,18 @@ func NewBroker(opts ...Option) *NoopBroker {
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *NoopBroker) Health() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *NoopBroker) Live() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *NoopBroker) Ready() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func (b *NoopBroker) Name() string {
|
func (b *NoopBroker) Name() string {
|
||||||
return b.opts.Name
|
return b.opts.Name
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,6 @@ import (
|
|||||||
"go.unistack.org/micro/v3/logger"
|
"go.unistack.org/micro/v3/logger"
|
||||||
"go.unistack.org/micro/v3/metadata"
|
"go.unistack.org/micro/v3/metadata"
|
||||||
"go.unistack.org/micro/v3/meter"
|
"go.unistack.org/micro/v3/meter"
|
||||||
"go.unistack.org/micro/v3/network/transport"
|
|
||||||
"go.unistack.org/micro/v3/options"
|
"go.unistack.org/micro/v3/options"
|
||||||
"go.unistack.org/micro/v3/register"
|
"go.unistack.org/micro/v3/register"
|
||||||
"go.unistack.org/micro/v3/router"
|
"go.unistack.org/micro/v3/router"
|
||||||
@ -22,8 +21,6 @@ import (
|
|||||||
|
|
||||||
// Options holds client options
|
// Options holds client options
|
||||||
type Options struct {
|
type Options struct {
|
||||||
// Transport used for transfer messages
|
|
||||||
Transport transport.Transport
|
|
||||||
// Selector used to select needed address
|
// Selector used to select needed address
|
||||||
Selector selector.Selector
|
Selector selector.Selector
|
||||||
// Logger used to log messages
|
// Logger used to log messages
|
||||||
@ -194,7 +191,6 @@ func NewOptions(opts ...Option) Options {
|
|||||||
Retry: DefaultRetry,
|
Retry: DefaultRetry,
|
||||||
Retries: DefaultRetries,
|
Retries: DefaultRetries,
|
||||||
RequestTimeout: DefaultRequestTimeout,
|
RequestTimeout: DefaultRequestTimeout,
|
||||||
DialTimeout: transport.DefaultDialTimeout,
|
|
||||||
},
|
},
|
||||||
Lookup: LookupRoute,
|
Lookup: LookupRoute,
|
||||||
PoolSize: DefaultPoolSize,
|
PoolSize: DefaultPoolSize,
|
||||||
@ -205,7 +201,6 @@ func NewOptions(opts ...Option) Options {
|
|||||||
Meter: meter.DefaultMeter,
|
Meter: meter.DefaultMeter,
|
||||||
Tracer: tracer.DefaultTracer,
|
Tracer: tracer.DefaultTracer,
|
||||||
Router: router.DefaultRouter,
|
Router: router.DefaultRouter,
|
||||||
Transport: transport.DefaultTransport,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, o := range opts {
|
for _, o := range opts {
|
||||||
@ -278,13 +273,6 @@ func PoolTTL(d time.Duration) Option {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transport to use for communication e.g http, rabbitmq, etc
|
|
||||||
func Transport(t transport.Transport) Option {
|
|
||||||
return func(o *Options) {
|
|
||||||
o.Transport = t
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register sets the routers register
|
// Register sets the routers register
|
||||||
func Register(r register.Register) Option {
|
func Register(r register.Register) Option {
|
||||||
return func(o *Options) {
|
return func(o *Options) {
|
||||||
@ -334,14 +322,6 @@ func TLSConfig(t *tls.Config) Option {
|
|||||||
return func(o *Options) {
|
return func(o *Options) {
|
||||||
// set the internal tls
|
// set the internal tls
|
||||||
o.TLSConfig = t
|
o.TLSConfig = t
|
||||||
|
|
||||||
// set the default transport if one is not
|
|
||||||
// already set. Required for Init call below.
|
|
||||||
|
|
||||||
// set the transport tls
|
|
||||||
_ = o.Transport.Init(
|
|
||||||
transport.TLSConfig(t),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -507,13 +487,6 @@ func WithAuthToken(t string) CallOption {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithNetwork is a CallOption which sets the network attribute
|
|
||||||
func WithNetwork(n string) CallOption {
|
|
||||||
return func(o *CallOptions) {
|
|
||||||
o.Network = n
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithRouter sets the router to use for this call
|
// WithRouter sets the router to use for this call
|
||||||
func WithRouter(r router.Router) CallOption {
|
func WithRouter(r router.Router) CallOption {
|
||||||
return func(o *CallOptions) {
|
return func(o *CallOptions) {
|
||||||
|
@ -38,4 +38,10 @@ type Cluster interface {
|
|||||||
Broadcast(ctx context.Context, msg Message, filter ...string) error
|
Broadcast(ctx context.Context, msg Message, filter ...string) error
|
||||||
// Unicast send message to single member in cluster
|
// Unicast send message to single member in cluster
|
||||||
Unicast(ctx context.Context, node Node, msg Message) error
|
Unicast(ctx context.Context, node Node, msg Message) error
|
||||||
|
// Live returns cluster liveness
|
||||||
|
Live() bool
|
||||||
|
// Ready returns cluster readiness
|
||||||
|
Ready() bool
|
||||||
|
// Health returns cluster health
|
||||||
|
Health() bool
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@ package config
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -139,7 +138,7 @@ var (
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if err := fn(ctx, c); err != nil {
|
if err := fn(ctx, c); err != nil {
|
||||||
c.Options().Logger.Error(ctx, fmt.Sprintf("%s BeforeLoad error", c.String()), err)
|
c.Options().Logger.Error(ctx, c.String()+" BeforeLoad error", err)
|
||||||
if !c.Options().AllowFail {
|
if !c.Options().AllowFail {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -154,7 +153,7 @@ var (
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if err := fn(ctx, c); err != nil {
|
if err := fn(ctx, c); err != nil {
|
||||||
c.Options().Logger.Error(ctx, fmt.Sprintf("%s AfterLoad error", c.String()), err)
|
c.Options().Logger.Error(ctx, c.String()+" AfterLoad error", err)
|
||||||
if !c.Options().AllowFail {
|
if !c.Options().AllowFail {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -169,7 +168,7 @@ var (
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if err := fn(ctx, c); err != nil {
|
if err := fn(ctx, c); err != nil {
|
||||||
c.Options().Logger.Error(ctx, fmt.Sprintf("%s BeforeSave error", c.String()), err)
|
c.Options().Logger.Error(ctx, c.String()+" BeforeSave error", err)
|
||||||
if !c.Options().AllowFail {
|
if !c.Options().AllowFail {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -184,7 +183,7 @@ var (
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if err := fn(ctx, c); err != nil {
|
if err := fn(ctx, c); err != nil {
|
||||||
c.Options().Logger.Error(ctx, fmt.Sprintf("%s AfterSave error", c.String()), err)
|
c.Options().Logger.Error(ctx, c.String()+" AfterSave error", err)
|
||||||
if !c.Options().AllowFail {
|
if !c.Options().AllowFail {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -199,7 +198,7 @@ var (
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if err := fn(ctx, c); err != nil {
|
if err := fn(ctx, c); err != nil {
|
||||||
c.Options().Logger.Error(ctx, fmt.Sprintf("%s BeforeInit error", c.String()), err)
|
c.Options().Logger.Error(ctx, c.String()+" BeforeInit error", err)
|
||||||
if !c.Options().AllowFail {
|
if !c.Options().AllowFail {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -214,7 +213,7 @@ var (
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if err := fn(ctx, c); err != nil {
|
if err := fn(ctx, c); err != nil {
|
||||||
c.Options().Logger.Error(ctx, fmt.Sprintf("%s AfterInit error", c.String(), err), err)
|
c.Options().Logger.Error(ctx, c.String()+" AfterInit error", err)
|
||||||
if !c.Options().AllowFail {
|
if !c.Options().AllowFail {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,28 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestMultipleUsage(t *testing.T) {
|
||||||
|
ctx := context.TODO()
|
||||||
|
md := New(0)
|
||||||
|
md.Set("key1_1", "val1_1", "key1_2", "val1_2", "key1_3", "val1_3")
|
||||||
|
ctx = NewIncomingContext(ctx, Copy(md))
|
||||||
|
ctx = NewOutgoingContext(ctx, Copy(md))
|
||||||
|
imd, _ := FromIncomingContext(ctx)
|
||||||
|
omd, _ := FromOutgoingContext(ctx)
|
||||||
|
_ = func(x context.Context) context.Context {
|
||||||
|
m, _ := FromIncomingContext(x)
|
||||||
|
m.Del("key1_2")
|
||||||
|
return ctx
|
||||||
|
}(ctx)
|
||||||
|
_ = func(x context.Context) context.Context {
|
||||||
|
m, _ := FromIncomingContext(x)
|
||||||
|
m.Del("key1_3")
|
||||||
|
return ctx
|
||||||
|
}(ctx)
|
||||||
|
t.Logf("imd %#+v", imd)
|
||||||
|
t.Logf("omd %#+v", omd)
|
||||||
|
}
|
||||||
|
|
||||||
func TestMetadataSetMultiple(t *testing.T) {
|
func TestMetadataSetMultiple(t *testing.T) {
|
||||||
md := New(4)
|
md := New(4)
|
||||||
md.Set("key1", "val1", "key2", "val2", "key3")
|
md.Set("key1", "val1", "key2", "val2", "key3")
|
||||||
|
@ -66,6 +66,12 @@ type bro struct {
|
|||||||
|
|
||||||
func (p *bro) Name() string { return p.name }
|
func (p *bro) Name() string { return p.name }
|
||||||
|
|
||||||
|
func (p *bro) Live() bool { return true }
|
||||||
|
|
||||||
|
func (p *bro) Ready() bool { return true }
|
||||||
|
|
||||||
|
func (p *bro) Health() bool { return true }
|
||||||
|
|
||||||
func (p *bro) Init(opts ...broker.Option) error { return nil }
|
func (p *bro) Init(opts ...broker.Option) error { return nil }
|
||||||
|
|
||||||
// Options returns broker options
|
// Options returns broker options
|
||||||
|
@ -45,6 +45,18 @@ type (
|
|||||||
tunnelAddr struct{}
|
tunnelAddr struct{}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func (t *tunBroker) Live() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *tunBroker) Ready() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *tunBroker) Health() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func (t *tunBroker) Init(opts ...broker.Option) error {
|
func (t *tunBroker) Init(opts ...broker.Option) error {
|
||||||
for _, o := range opts {
|
for _, o := range opts {
|
||||||
o(&t.opts)
|
o(&t.opts)
|
||||||
|
@ -29,17 +29,32 @@ var (
|
|||||||
// and an abstraction over varying implementations
|
// and an abstraction over varying implementations
|
||||||
// {consul, etcd, zookeeper, ...}
|
// {consul, etcd, zookeeper, ...}
|
||||||
type Register interface {
|
type Register interface {
|
||||||
|
// Name returns register name
|
||||||
Name() string
|
Name() string
|
||||||
|
// Init initialize register
|
||||||
Init(...Option) error
|
Init(...Option) error
|
||||||
|
// Options returns options for register
|
||||||
Options() Options
|
Options() Options
|
||||||
|
// Connect initialize connect to register
|
||||||
Connect(context.Context) error
|
Connect(context.Context) error
|
||||||
|
// Disconnect initialize discconection from register
|
||||||
Disconnect(context.Context) error
|
Disconnect(context.Context) error
|
||||||
|
// Register service in registry
|
||||||
Register(context.Context, *Service, ...RegisterOption) error
|
Register(context.Context, *Service, ...RegisterOption) error
|
||||||
|
// Deregister service from registry
|
||||||
Deregister(context.Context, *Service, ...DeregisterOption) error
|
Deregister(context.Context, *Service, ...DeregisterOption) error
|
||||||
|
// LookupService in registry
|
||||||
LookupService(context.Context, string, ...LookupOption) ([]*Service, error)
|
LookupService(context.Context, string, ...LookupOption) ([]*Service, error)
|
||||||
|
// ListServices in registry
|
||||||
ListServices(context.Context, ...ListOption) ([]*Service, error)
|
ListServices(context.Context, ...ListOption) ([]*Service, error)
|
||||||
|
// Watch registry events
|
||||||
Watch(context.Context, ...WatchOption) (Watcher, error)
|
Watch(context.Context, ...WatchOption) (Watcher, error)
|
||||||
|
// String returns registry string representation
|
||||||
String() string
|
String() string
|
||||||
|
// Live returns register liveness
|
||||||
|
// Live() bool
|
||||||
|
// Ready returns register readiness
|
||||||
|
// Ready() bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Service holds service register info
|
// Service holds service register info
|
||||||
|
@ -121,6 +121,18 @@ func (n *noopServer) newCodec(contentType string) (codec.Codec, error) {
|
|||||||
return nil, codec.ErrUnknownContentType
|
return nil, codec.ErrUnknownContentType
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (n *noopServer) Live() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *noopServer) Ready() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *noopServer) Health() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func (n *noopServer) Handle(handler Handler) error {
|
func (n *noopServer) Handle(handler Handler) error {
|
||||||
n.h = handler
|
n.h = handler
|
||||||
return nil
|
return nil
|
||||||
|
@ -12,7 +12,6 @@ import (
|
|||||||
"go.unistack.org/micro/v3/logger"
|
"go.unistack.org/micro/v3/logger"
|
||||||
"go.unistack.org/micro/v3/metadata"
|
"go.unistack.org/micro/v3/metadata"
|
||||||
"go.unistack.org/micro/v3/meter"
|
"go.unistack.org/micro/v3/meter"
|
||||||
"go.unistack.org/micro/v3/network/transport"
|
|
||||||
"go.unistack.org/micro/v3/options"
|
"go.unistack.org/micro/v3/options"
|
||||||
"go.unistack.org/micro/v3/register"
|
"go.unistack.org/micro/v3/register"
|
||||||
msync "go.unistack.org/micro/v3/sync"
|
msync "go.unistack.org/micro/v3/sync"
|
||||||
@ -37,8 +36,6 @@ type Options struct {
|
|||||||
Logger logger.Logger
|
Logger logger.Logger
|
||||||
// Meter holds the meter
|
// Meter holds the meter
|
||||||
Meter meter.Meter
|
Meter meter.Meter
|
||||||
// Transport holds the transport
|
|
||||||
Transport transport.Transport
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// Router for requests
|
// Router for requests
|
||||||
@ -100,7 +97,6 @@ func NewOptions(opts ...Option) Options {
|
|||||||
Tracer: tracer.DefaultTracer,
|
Tracer: tracer.DefaultTracer,
|
||||||
Broker: broker.DefaultBroker,
|
Broker: broker.DefaultBroker,
|
||||||
Register: register.DefaultRegister,
|
Register: register.DefaultRegister,
|
||||||
Transport: transport.DefaultTransport,
|
|
||||||
Address: DefaultAddress,
|
Address: DefaultAddress,
|
||||||
Name: DefaultName,
|
Name: DefaultName,
|
||||||
Version: DefaultVersion,
|
Version: DefaultVersion,
|
||||||
@ -209,13 +205,6 @@ func Tracer(t tracer.Tracer) Option {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transport mechanism for communication e.g http, rabbitmq, etc
|
|
||||||
func Transport(t transport.Transport) Option {
|
|
||||||
return func(o *Options) {
|
|
||||||
o.Transport = t
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Metadata associated with the server
|
// Metadata associated with the server
|
||||||
func Metadata(md metadata.Metadata) Option {
|
func Metadata(md metadata.Metadata) Option {
|
||||||
return func(o *Options) {
|
return func(o *Options) {
|
||||||
@ -249,14 +238,6 @@ func TLSConfig(t *tls.Config) Option {
|
|||||||
return func(o *Options) {
|
return func(o *Options) {
|
||||||
// set the internal tls
|
// set the internal tls
|
||||||
o.TLSConfig = t
|
o.TLSConfig = t
|
||||||
|
|
||||||
// set the default transport if one is not
|
|
||||||
// already set. Required for Init call below.
|
|
||||||
|
|
||||||
// set the transport tls
|
|
||||||
_ = o.Transport.Init(
|
|
||||||
transport.TLSConfig(t),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,6 +62,12 @@ type Server interface {
|
|||||||
Stop() error
|
Stop() error
|
||||||
// Server implementation
|
// Server implementation
|
||||||
String() string
|
String() string
|
||||||
|
// Live returns server liveness
|
||||||
|
Live() bool
|
||||||
|
// Ready returns server readiness
|
||||||
|
Ready() bool
|
||||||
|
// Health returns server health
|
||||||
|
Health() bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
75
service.go
75
service.go
@ -1,5 +1,5 @@
|
|||||||
// Package micro is a pluggable framework for microservices
|
// Package micro is a pluggable framework for microservices
|
||||||
package micro // import "go.unistack.org/micro/v3"
|
package micro
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -72,8 +72,14 @@ type Service interface {
|
|||||||
Start() error
|
Start() error
|
||||||
// Stop the service
|
// Stop the service
|
||||||
Stop() error
|
Stop() error
|
||||||
// The service implementation
|
// String service representation
|
||||||
String() string
|
String() string
|
||||||
|
// Live returns service liveness
|
||||||
|
Live() bool
|
||||||
|
// Ready returns service readiness
|
||||||
|
Ready() bool
|
||||||
|
// Health returns service health
|
||||||
|
Health() bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegisterHandler is syntactic sugar for registering a handler
|
// RegisterHandler is syntactic sugar for registering a handler
|
||||||
@ -101,9 +107,7 @@ func (s *service) Name() string {
|
|||||||
return s.opts.Name
|
return s.opts.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init initialises options. Additionally it calls cmd.Init
|
// Init initialises options.
|
||||||
// which parses command line flags. cmd.Init is only called
|
|
||||||
// on first Init.
|
|
||||||
//
|
//
|
||||||
//nolint:gocyclo
|
//nolint:gocyclo
|
||||||
func (s *service) Init(opts ...Option) error {
|
func (s *service) Init(opts ...Option) error {
|
||||||
@ -252,6 +256,63 @@ func (s *service) String() string {
|
|||||||
return s.opts.Name
|
return s.opts.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *service) Live() bool {
|
||||||
|
for _, v := range s.opts.Brokers {
|
||||||
|
if !v.Live() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, v := range s.opts.Servers {
|
||||||
|
if !v.Live() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, v := range s.opts.Stores {
|
||||||
|
if !v.Live() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *service) Ready() bool {
|
||||||
|
for _, v := range s.opts.Brokers {
|
||||||
|
if !v.Ready() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, v := range s.opts.Servers {
|
||||||
|
if !v.Ready() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, v := range s.opts.Stores {
|
||||||
|
if !v.Ready() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *service) Health() bool {
|
||||||
|
for _, v := range s.opts.Brokers {
|
||||||
|
if !v.Health() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, v := range s.opts.Servers {
|
||||||
|
if !v.Health() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, v := range s.opts.Stores {
|
||||||
|
if !v.Health() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
//nolint:gocyclo
|
//nolint:gocyclo
|
||||||
func (s *service) Start() error {
|
func (s *service) Start() error {
|
||||||
var err error
|
var err error
|
||||||
@ -281,10 +342,6 @@ func (s *service) Start() error {
|
|||||||
config.Loggers[0].Info(s.opts.Context, fmt.Sprintf("starting [service] %s version %s", s.Options().Name, s.Options().Version))
|
config.Loggers[0].Info(s.opts.Context, fmt.Sprintf("starting [service] %s version %s", s.Options().Name, s.Options().Version))
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(s.opts.Servers) == 0 {
|
|
||||||
return fmt.Errorf("cant start nil server")
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, reg := range s.opts.Registers {
|
for _, reg := range s.opts.Registers {
|
||||||
if err = reg.Connect(s.opts.Context); err != nil {
|
if err = reg.Connect(s.opts.Context); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -149,6 +149,18 @@ func (m *memoryStore) Name() string {
|
|||||||
return m.opts.Name
|
return m.opts.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *memoryStore) Live() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *memoryStore) Ready() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *memoryStore) Health() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func (m *memoryStore) Exists(ctx context.Context, key string, opts ...store.ExistsOption) error {
|
func (m *memoryStore) Exists(ctx context.Context, key string, opts ...store.ExistsOption) error {
|
||||||
if m.opts.LazyConnect {
|
if m.opts.LazyConnect {
|
||||||
if err := m.connect(ctx); err != nil {
|
if err := m.connect(ctx); err != nil {
|
||||||
@ -279,3 +291,16 @@ func (m *memoryStore) connect(ctx context.Context) error {
|
|||||||
m.isConnected.CompareAndSwap(0, 1)
|
m.isConnected.CompareAndSwap(0, 1)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *memoryStore) Watch(ctx context.Context, opts ...store.WatchOption) (store.Watcher, error) {
|
||||||
|
return &watcher{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type watcher struct{}
|
||||||
|
|
||||||
|
func (w *watcher) Next() (store.Event, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *watcher) Stop() {
|
||||||
|
}
|
||||||
|
@ -23,6 +23,18 @@ type noopStore struct {
|
|||||||
isConnected atomic.Int32
|
isConnected atomic.Int32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (n *noopStore) Live() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *noopStore) Ready() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *noopStore) Health() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func NewStore(opts ...Option) *noopStore {
|
func NewStore(opts ...Option) *noopStore {
|
||||||
options := NewOptions(opts...)
|
options := NewOptions(opts...)
|
||||||
return &noopStore{opts: options}
|
return &noopStore{opts: options}
|
||||||
|
@ -45,7 +45,14 @@ type Store interface {
|
|||||||
Disconnect(ctx context.Context) error
|
Disconnect(ctx context.Context) error
|
||||||
// String returns the name of the implementation.
|
// String returns the name of the implementation.
|
||||||
String() string
|
String() string
|
||||||
|
// Watch returns events watcher
|
||||||
Watch(ctx context.Context, opts ...WatchOption) (Watcher, error)
|
Watch(ctx context.Context, opts ...WatchOption) (Watcher, error)
|
||||||
|
// Live returns store liveness
|
||||||
|
Live() bool
|
||||||
|
// Ready returns store readiness
|
||||||
|
Ready() bool
|
||||||
|
// Health returns store health
|
||||||
|
Health() bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
@ -70,3 +70,15 @@ func (w *NamespaceStore) String() string {
|
|||||||
func (w *NamespaceStore) Watch(ctx context.Context, opts ...WatchOption) (Watcher, error) {
|
func (w *NamespaceStore) Watch(ctx context.Context, opts ...WatchOption) (Watcher, error) {
|
||||||
return w.s.Watch(ctx, opts...)
|
return w.s.Watch(ctx, opts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *NamespaceStore) Live() bool {
|
||||||
|
return w.s.Live()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *NamespaceStore) Ready() bool {
|
||||||
|
return w.s.Ready()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *NamespaceStore) Health() bool {
|
||||||
|
return w.s.Health()
|
||||||
|
}
|
||||||
|
@ -1,40 +0,0 @@
|
|||||||
// Package io is for io management
|
|
||||||
package io
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
|
|
||||||
"go.unistack.org/micro/v3/network/transport"
|
|
||||||
)
|
|
||||||
|
|
||||||
type rwc struct {
|
|
||||||
socket transport.Socket
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *rwc) Read(p []byte) (n int, err error) {
|
|
||||||
m := new(transport.Message)
|
|
||||||
if err := r.socket.Recv(m); err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
copy(p, m.Body)
|
|
||||||
return len(m.Body), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *rwc) Write(p []byte) (n int, err error) {
|
|
||||||
err = r.socket.Send(&transport.Message{
|
|
||||||
Body: p,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return len(p), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *rwc) Close() error {
|
|
||||||
return r.socket.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewRWC returns a new ReadWriteCloser
|
|
||||||
func NewRWC(sock transport.Socket) io.ReadWriteCloser {
|
|
||||||
return &rwc{sock}
|
|
||||||
}
|
|
@ -1,118 +0,0 @@
|
|||||||
package pool
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"go.unistack.org/micro/v3/network/transport"
|
|
||||||
"go.unistack.org/micro/v3/util/id"
|
|
||||||
)
|
|
||||||
|
|
||||||
type pool struct {
|
|
||||||
tr transport.Transport
|
|
||||||
conns map[string][]*poolConn
|
|
||||||
size int
|
|
||||||
ttl time.Duration
|
|
||||||
sync.Mutex
|
|
||||||
}
|
|
||||||
|
|
||||||
type poolConn struct {
|
|
||||||
created time.Time
|
|
||||||
transport.Client
|
|
||||||
id string
|
|
||||||
}
|
|
||||||
|
|
||||||
func newPool(options Options) *pool {
|
|
||||||
return &pool{
|
|
||||||
size: options.Size,
|
|
||||||
tr: options.Transport,
|
|
||||||
ttl: options.TTL,
|
|
||||||
conns: make(map[string][]*poolConn),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *pool) Close() error {
|
|
||||||
p.Lock()
|
|
||||||
for k, c := range p.conns {
|
|
||||||
for _, conn := range c {
|
|
||||||
conn.Client.Close()
|
|
||||||
}
|
|
||||||
delete(p.conns, k)
|
|
||||||
}
|
|
||||||
p.Unlock()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NoOp the Close since we manage it
|
|
||||||
func (p *poolConn) Close() error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *poolConn) ID() string {
|
|
||||||
return p.id
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *poolConn) Created() time.Time {
|
|
||||||
return p.created
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *pool) Get(ctx context.Context, addr string, opts ...transport.DialOption) (Conn, error) {
|
|
||||||
p.Lock()
|
|
||||||
conns := p.conns[addr]
|
|
||||||
|
|
||||||
// while we have conns check age and then return one
|
|
||||||
// otherwise we'll create a new conn
|
|
||||||
for len(conns) > 0 {
|
|
||||||
conn := conns[len(conns)-1]
|
|
||||||
conns = conns[:len(conns)-1]
|
|
||||||
p.conns[addr] = conns
|
|
||||||
|
|
||||||
// if conn is old kill it and move on
|
|
||||||
if d := time.Since(conn.Created()); d > p.ttl {
|
|
||||||
conn.Client.Close()
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// we got a good conn, lets unlock and return it
|
|
||||||
p.Unlock()
|
|
||||||
|
|
||||||
return conn, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
p.Unlock()
|
|
||||||
|
|
||||||
// create new conn
|
|
||||||
c, err := p.tr.Dial(ctx, addr, opts...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
id, err := id.New()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &poolConn{
|
|
||||||
Client: c,
|
|
||||||
id: id,
|
|
||||||
created: time.Now(),
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *pool) Release(conn Conn, err error) error {
|
|
||||||
// don't store the conn if it has errored
|
|
||||||
if err != nil {
|
|
||||||
return conn.(*poolConn).Client.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
// otherwise put it back for reuse
|
|
||||||
p.Lock()
|
|
||||||
conns := p.conns[conn.Remote()]
|
|
||||||
if len(conns) >= p.size {
|
|
||||||
p.Unlock()
|
|
||||||
return conn.(*poolConn).Client.Close()
|
|
||||||
}
|
|
||||||
p.conns[conn.Remote()] = append(conns, conn.(*poolConn))
|
|
||||||
p.Unlock()
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -1,92 +0,0 @@
|
|||||||
//go:build ignore
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
package pool
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"go.unistack.org/micro/v3/network/transport"
|
|
||||||
"go.unistack.org/micro/v3/network/transport/memory"
|
|
||||||
)
|
|
||||||
|
|
||||||
func testPool(t *testing.T, size int, ttl time.Duration) {
|
|
||||||
// mock transport
|
|
||||||
tr := memory.NewTransport()
|
|
||||||
|
|
||||||
options := Options{
|
|
||||||
TTL: ttl,
|
|
||||||
Size: size,
|
|
||||||
Transport: tr,
|
|
||||||
}
|
|
||||||
// zero pool
|
|
||||||
p := newPool(options)
|
|
||||||
|
|
||||||
// listen
|
|
||||||
l, err := tr.Listen(":0")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer l.Close()
|
|
||||||
|
|
||||||
// accept loop
|
|
||||||
go func() {
|
|
||||||
for {
|
|
||||||
if err := l.Accept(func(s transport.Socket) {
|
|
||||||
for {
|
|
||||||
var msg transport.Message
|
|
||||||
if err := s.Recv(&msg); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err := s.Send(&msg); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
for i := 0; i < 10; i++ {
|
|
||||||
// get a conn
|
|
||||||
c, err := p.Get(l.Addr())
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
msg := &transport.Message{
|
|
||||||
Body: []byte(`hello world`),
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := c.Send(msg); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var rcv transport.Message
|
|
||||||
|
|
||||||
if err := c.Recv(&rcv); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if string(rcv.Body) != string(msg.Body) {
|
|
||||||
t.Fatalf("got %v, expected %v", rcv.Body, msg.Body)
|
|
||||||
}
|
|
||||||
|
|
||||||
// release the conn
|
|
||||||
p.Release(c, nil)
|
|
||||||
|
|
||||||
p.Lock()
|
|
||||||
if i := len(p.conns[l.Addr()]); i > size {
|
|
||||||
p.Unlock()
|
|
||||||
t.Fatalf("pool size %d is greater than expected %d", i, size)
|
|
||||||
}
|
|
||||||
p.Unlock()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestClientPool(t *testing.T) {
|
|
||||||
testPool(t, 0, time.Minute)
|
|
||||||
testPool(t, 2, time.Minute)
|
|
||||||
}
|
|
@ -1,38 +0,0 @@
|
|||||||
package pool
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"go.unistack.org/micro/v3/network/transport"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Options struct
|
|
||||||
type Options struct {
|
|
||||||
Transport transport.Transport
|
|
||||||
TTL time.Duration
|
|
||||||
Size int
|
|
||||||
}
|
|
||||||
|
|
||||||
// Option func signature
|
|
||||||
type Option func(*Options)
|
|
||||||
|
|
||||||
// Size sets the size
|
|
||||||
func Size(i int) Option {
|
|
||||||
return func(o *Options) {
|
|
||||||
o.Size = i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transport sets the transport
|
|
||||||
func Transport(t transport.Transport) Option {
|
|
||||||
return func(o *Options) {
|
|
||||||
o.Transport = t
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TTL specifies ttl
|
|
||||||
func TTL(t time.Duration) Option {
|
|
||||||
return func(o *Options) {
|
|
||||||
o.TTL = t
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,38 +0,0 @@
|
|||||||
// Package pool is a connection pool
|
|
||||||
package pool
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"go.unistack.org/micro/v3/network/transport"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Pool is an interface for connection pooling
|
|
||||||
type Pool interface {
|
|
||||||
// Close the pool
|
|
||||||
Close() error
|
|
||||||
// Get a connection
|
|
||||||
Get(ctx context.Context, addr string, opts ...transport.DialOption) (Conn, error)
|
|
||||||
// Release the connection
|
|
||||||
Release(c Conn, status error) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Conn conn pool interface
|
|
||||||
type Conn interface {
|
|
||||||
// unique id of connection
|
|
||||||
ID() string
|
|
||||||
// time it was created
|
|
||||||
Created() time.Time
|
|
||||||
// embedded connection
|
|
||||||
transport.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewPool creates new connection pool
|
|
||||||
func NewPool(opts ...Option) Pool {
|
|
||||||
options := Options{}
|
|
||||||
for _, o := range opts {
|
|
||||||
o(&options)
|
|
||||||
}
|
|
||||||
return newPool(options)
|
|
||||||
}
|
|
@ -23,7 +23,7 @@ func TestMarshalYAML(t *testing.T) {
|
|||||||
|
|
||||||
func TestUnmarshalYAML(t *testing.T) {
|
func TestUnmarshalYAML(t *testing.T) {
|
||||||
type str struct {
|
type str struct {
|
||||||
TTL Duration `yaml:"ttl"`
|
TTL *Duration `yaml:"ttl"`
|
||||||
}
|
}
|
||||||
v := &str{}
|
v := &str{}
|
||||||
var err error
|
var err error
|
||||||
@ -31,14 +31,14 @@ func TestUnmarshalYAML(t *testing.T) {
|
|||||||
err = yaml.Unmarshal([]byte(`{"ttl":"10ms"}`), v)
|
err = yaml.Unmarshal([]byte(`{"ttl":"10ms"}`), v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
} else if v.TTL != 10000000 {
|
} else if *(v.TTL) != 10000000 {
|
||||||
t.Fatalf("invalid duration %v != 10000000", v.TTL)
|
t.Fatalf("invalid duration %v != 10000000", v.TTL)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = yaml.Unmarshal([]byte(`{"ttl":"1y"}`), v)
|
err = yaml.Unmarshal([]byte(`{"ttl":"1y"}`), v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
} else if v.TTL != 31622400000000000 {
|
} else if *(v.TTL) != 31622400000000000 {
|
||||||
t.Fatalf("invalid duration %v != 31622400000000000", v.TTL)
|
t.Fatalf("invalid duration %v != 31622400000000000", v.TTL)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user