Compare commits
	
		
			28 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| e724425ce2 | |||
| bc55c2fa6f | |||
| fdd1589122 | |||
| 6f6f850af6 | |||
| b1dbd99ce2 | |||
| 6e24807edf | |||
| 654d8fa7e4 | |||
| dd1a9cd25a | |||
| d463eb20cb | |||
| 8d5e25f8cf | |||
| 27e8043fed | |||
| 4e86df1721 | |||
| 03de1ec38f | |||
| 819ad1117a | |||
| a2a383606d | |||
| 55ce58617b | |||
| 0e587d923e | |||
| fa0248c80c | |||
| 054bd02b59 | |||
| 0cf246d2d6 | |||
| af278bd7d3 | |||
| 814b90efe5 | |||
| e403ae3d8e | |||
| c9816a3957 | |||
| 5691238a6a | |||
| 963a0fa7b7 | |||
| 485257035c | |||
| ebd8ddf05b | 
@@ -1,4 +1,4 @@
 | 
				
			|||||||
# Micro [](https://opensource.org/licenses/Apache-2.0) [](https://pkg.go.dev/github.com/unistack-org/micro/v3?tab=overview) [](https://github.com/unistack-org/micro/actions?query=workflow%3Abuild+branch%3Amaster+event%3Apush) [](https://goreportcard.com/report/go.unistack.org/micro/v3) [](https://codecov.io/gh/unistack-org/micro)
 | 
					# Micro [](https://opensource.org/licenses/Apache-2.0) [](https://pkg.go.dev/go.unistack.org/micro/v4?tab=overview) [](https://github.com/unistack-org/micro/actions?query=workflow%3Abuild+branch%3Amaster+event%3Apush) [](https://goreportcard.com/report/go.unistack.org/micro/v4) [](https://codecov.io/gh/unistack-org/micro)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Micro is a standard library for microservices.
 | 
					Micro is a standard library for microservices.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,22 +1,24 @@
 | 
				
			|||||||
// Package broker is an interface used for asynchronous messaging
 | 
					// Package broker is an interface used for asynchronous messaging
 | 
				
			||||||
package broker // import "go.unistack.org/micro/v3/broker"
 | 
					package broker // import "go.unistack.org/micro/v4/broker"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro/v3/codec"
 | 
						"go.unistack.org/micro/v4/metadata"
 | 
				
			||||||
	"go.unistack.org/micro/v3/metadata"
 | 
						"go.unistack.org/micro/v4/options"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DefaultBroker default memory broker
 | 
					// DefaultBroker default memory broker
 | 
				
			||||||
var DefaultBroker = NewBroker()
 | 
					var DefaultBroker Broker = NewBroker()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
	// ErrNotConnected returns when broker used but not connected yet
 | 
						// ErrNotConnected returns when broker used but not connected yet
 | 
				
			||||||
	ErrNotConnected = errors.New("broker not connected")
 | 
						ErrNotConnected = errors.New("broker not connected")
 | 
				
			||||||
	// ErrDisconnected returns when broker disconnected
 | 
						// ErrDisconnected returns when broker disconnected
 | 
				
			||||||
	ErrDisconnected = errors.New("broker disconnected")
 | 
						ErrDisconnected = errors.New("broker disconnected")
 | 
				
			||||||
 | 
						// ErrInvalidMessage returns when message has nvalid format
 | 
				
			||||||
 | 
						ErrInvalidMessage = errors.New("broker message has invalid format")
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Broker is an interface used for asynchronous messaging.
 | 
					// Broker is an interface used for asynchronous messaging.
 | 
				
			||||||
@@ -24,7 +26,7 @@ type Broker interface {
 | 
				
			|||||||
	// Name returns broker instance name
 | 
						// Name returns broker instance name
 | 
				
			||||||
	Name() string
 | 
						Name() string
 | 
				
			||||||
	// Init initilize broker
 | 
						// Init initilize broker
 | 
				
			||||||
	Init(opts ...Option) error
 | 
						Init(opts ...options.Option) error
 | 
				
			||||||
	// Options returns broker options
 | 
						// Options returns broker options
 | 
				
			||||||
	Options() Options
 | 
						Options() Options
 | 
				
			||||||
	// Address return configured address
 | 
						// Address return configured address
 | 
				
			||||||
@@ -33,72 +35,29 @@ type Broker interface {
 | 
				
			|||||||
	Connect(ctx context.Context) error
 | 
						Connect(ctx context.Context) error
 | 
				
			||||||
	// Disconnect disconnect from broker
 | 
						// Disconnect disconnect from broker
 | 
				
			||||||
	Disconnect(ctx context.Context) error
 | 
						Disconnect(ctx context.Context) error
 | 
				
			||||||
	// Publish message to broker topic
 | 
						// Publish message, msg can be single broker.Message or []broker.Message
 | 
				
			||||||
	Publish(ctx context.Context, topic string, msg *Message, opts ...PublishOption) error
 | 
						Publish(ctx context.Context, msg interface{}, opts ...options.Option) error
 | 
				
			||||||
	// Subscribe subscribes to topic message via handler
 | 
						// Subscribe subscribes to topic message via handler
 | 
				
			||||||
	Subscribe(ctx context.Context, topic string, h Handler, opts ...SubscribeOption) (Subscriber, error)
 | 
						Subscribe(ctx context.Context, topic string, handler interface{}, opts ...options.Option) (Subscriber, error)
 | 
				
			||||||
	// BatchPublish messages to broker with multiple topics
 | 
					 | 
				
			||||||
	BatchPublish(ctx context.Context, msgs []*Message, opts ...PublishOption) error
 | 
					 | 
				
			||||||
	// BatchSubscribe subscribes to topic messages via handler
 | 
					 | 
				
			||||||
	BatchSubscribe(ctx context.Context, topic string, h BatchHandler, opts ...SubscribeOption) (Subscriber, error)
 | 
					 | 
				
			||||||
	// String type of broker
 | 
						// String type of broker
 | 
				
			||||||
	String() string
 | 
						String() string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Handler is used to process messages via a subscription of a topic.
 | 
					// Message is given to a subscription handler for processing
 | 
				
			||||||
type Handler func(Event) error
 | 
					type Message interface {
 | 
				
			||||||
 | 
						// Context for the message
 | 
				
			||||||
// Events contains multiple events
 | 
						Context() context.Context
 | 
				
			||||||
type Events []Event
 | 
						// Topic
 | 
				
			||||||
 | 
					 | 
				
			||||||
// Ack try to ack all events and return
 | 
					 | 
				
			||||||
func (evs Events) Ack() error {
 | 
					 | 
				
			||||||
	var err error
 | 
					 | 
				
			||||||
	for _, ev := range evs {
 | 
					 | 
				
			||||||
		if err = ev.Ack(); err != nil {
 | 
					 | 
				
			||||||
			return err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// SetError sets error on event
 | 
					 | 
				
			||||||
func (evs Events) SetError(err error) {
 | 
					 | 
				
			||||||
	for _, ev := range evs {
 | 
					 | 
				
			||||||
		ev.SetError(err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// BatchHandler is used to process messages in batches via a subscription of a topic.
 | 
					 | 
				
			||||||
type BatchHandler func(Events) error
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Event is given to a subscription handler for processing
 | 
					 | 
				
			||||||
type Event interface {
 | 
					 | 
				
			||||||
	// Topic returns event topic
 | 
					 | 
				
			||||||
	Topic() string
 | 
						Topic() string
 | 
				
			||||||
	// Message returns broker message
 | 
						// Header returns message headers
 | 
				
			||||||
	Message() *Message
 | 
						Header() metadata.Metadata
 | 
				
			||||||
 | 
						// Body returns broker message may be []byte slice or some go struct
 | 
				
			||||||
 | 
						Body() interface{}
 | 
				
			||||||
	// Ack acknowledge message
 | 
						// Ack acknowledge message
 | 
				
			||||||
	Ack() error
 | 
						Ack() error
 | 
				
			||||||
	// Error returns message error (like decoding errors or some other)
 | 
						// Error returns message error (like decoding errors or some other)
 | 
				
			||||||
 | 
						// In this case Body contains raw []byte from broker
 | 
				
			||||||
	Error() error
 | 
						Error() error
 | 
				
			||||||
	// SetError set event processing error
 | 
					 | 
				
			||||||
	SetError(err error)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Message is used to transfer data
 | 
					 | 
				
			||||||
type Message struct {
 | 
					 | 
				
			||||||
	// Header contains message metadata
 | 
					 | 
				
			||||||
	Header metadata.Metadata
 | 
					 | 
				
			||||||
	// Body contains message body
 | 
					 | 
				
			||||||
	Body codec.RawMessage
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// NewMessage create broker message with topic filled
 | 
					 | 
				
			||||||
func NewMessage(topic string) *Message {
 | 
					 | 
				
			||||||
	m := &Message{Header: metadata.New(2)}
 | 
					 | 
				
			||||||
	m.Header.Set(metadata.HeaderTopic, topic)
 | 
					 | 
				
			||||||
	return m
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Subscriber is a convenience return type for the Subscribe method
 | 
					// Subscriber is a convenience return type for the Subscribe method
 | 
				
			||||||
@@ -110,3 +69,9 @@ type Subscriber interface {
 | 
				
			|||||||
	// Unsubscribe from topic
 | 
						// Unsubscribe from topic
 | 
				
			||||||
	Unsubscribe(ctx context.Context) error
 | 
						Unsubscribe(ctx context.Context) error
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// MessageHandler func signature for single message processing
 | 
				
			||||||
 | 
					type MessageHandler func(Message) error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// MessagesHandler func signature for batch message processing
 | 
				
			||||||
 | 
					type MessagesHandler func([]Message) error
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,33 +22,3 @@ func NewContext(ctx context.Context, s Broker) context.Context {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	return context.WithValue(ctx, brokerKey{}, s)
 | 
						return context.WithValue(ctx, brokerKey{}, s)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
// SetSubscribeOption returns a function to setup a context with given value
 | 
					 | 
				
			||||||
func SetSubscribeOption(k, v interface{}) SubscribeOption {
 | 
					 | 
				
			||||||
	return func(o *SubscribeOptions) {
 | 
					 | 
				
			||||||
		if o.Context == nil {
 | 
					 | 
				
			||||||
			o.Context = context.Background()
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		o.Context = context.WithValue(o.Context, k, v)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// SetOption returns a function to setup a context with given value
 | 
					 | 
				
			||||||
func SetOption(k, v interface{}) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		if o.Context == nil {
 | 
					 | 
				
			||||||
			o.Context = context.Background()
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		o.Context = context.WithValue(o.Context, k, v)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// SetPublishOption returns a function to setup a context with given value
 | 
					 | 
				
			||||||
func SetPublishOption(k, v interface{}) PublishOption {
 | 
					 | 
				
			||||||
	return func(o *PublishOptions) {
 | 
					 | 
				
			||||||
		if o.Context == nil {
 | 
					 | 
				
			||||||
			o.Context = context.Background()
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		o.Context = context.WithValue(o.Context, k, v)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -37,36 +37,3 @@ func TestNewNilContext(t *testing.T) {
 | 
				
			|||||||
		t.Fatal("NewContext not works")
 | 
							t.Fatal("NewContext not works")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestSetSubscribeOption(t *testing.T) {
 | 
					 | 
				
			||||||
	type key struct{}
 | 
					 | 
				
			||||||
	o := SetSubscribeOption(key{}, "test")
 | 
					 | 
				
			||||||
	opts := &SubscribeOptions{}
 | 
					 | 
				
			||||||
	o(opts)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if v, ok := opts.Context.Value(key{}).(string); !ok || v == "" {
 | 
					 | 
				
			||||||
		t.Fatal("SetSubscribeOption not works")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestSetPublishOption(t *testing.T) {
 | 
					 | 
				
			||||||
	type key struct{}
 | 
					 | 
				
			||||||
	o := SetPublishOption(key{}, "test")
 | 
					 | 
				
			||||||
	opts := &PublishOptions{}
 | 
					 | 
				
			||||||
	o(opts)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if v, ok := opts.Context.Value(key{}).(string); !ok || v == "" {
 | 
					 | 
				
			||||||
		t.Fatal("SetPublishOption not works")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestSetOption(t *testing.T) {
 | 
					 | 
				
			||||||
	type key struct{}
 | 
					 | 
				
			||||||
	o := SetOption(key{}, "test")
 | 
					 | 
				
			||||||
	opts := &Options{}
 | 
					 | 
				
			||||||
	o(opts)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if v, ok := opts.Context.Value(key{}).(string); !ok || v == "" {
 | 
					 | 
				
			||||||
		t.Fatal("SetOption not works")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										288
									
								
								broker/memory.go
									
									
									
									
									
								
							
							
						
						
									
										288
									
								
								broker/memory.go
									
									
									
									
									
								
							@@ -2,17 +2,22 @@ package broker
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro/v3/logger"
 | 
						"go.unistack.org/micro/v4/codec"
 | 
				
			||||||
	"go.unistack.org/micro/v3/metadata"
 | 
						"go.unistack.org/micro/v4/logger"
 | 
				
			||||||
	maddr "go.unistack.org/micro/v3/util/addr"
 | 
						"go.unistack.org/micro/v4/metadata"
 | 
				
			||||||
	"go.unistack.org/micro/v3/util/id"
 | 
						"go.unistack.org/micro/v4/options"
 | 
				
			||||||
	mnet "go.unistack.org/micro/v3/util/net"
 | 
						"go.unistack.org/micro/v4/semconv"
 | 
				
			||||||
	"go.unistack.org/micro/v3/util/rand"
 | 
						maddr "go.unistack.org/micro/v4/util/addr"
 | 
				
			||||||
 | 
						"go.unistack.org/micro/v4/util/id"
 | 
				
			||||||
 | 
						mnet "go.unistack.org/micro/v4/util/net"
 | 
				
			||||||
 | 
						"go.unistack.org/micro/v4/util/rand"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type memoryBroker struct {
 | 
					type MemoryBroker struct {
 | 
				
			||||||
	subscribers map[string][]*memorySubscriber
 | 
						subscribers map[string][]*memorySubscriber
 | 
				
			||||||
	addr        string
 | 
						addr        string
 | 
				
			||||||
	opts        Options
 | 
						opts        Options
 | 
				
			||||||
@@ -20,32 +25,15 @@ type memoryBroker struct {
 | 
				
			|||||||
	connected bool
 | 
						connected bool
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type memoryEvent struct {
 | 
					func (m *MemoryBroker) Options() Options {
 | 
				
			||||||
	err     error
 | 
					 | 
				
			||||||
	message interface{}
 | 
					 | 
				
			||||||
	topic   string
 | 
					 | 
				
			||||||
	opts    Options
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type memorySubscriber struct {
 | 
					 | 
				
			||||||
	ctx          context.Context
 | 
					 | 
				
			||||||
	exit         chan bool
 | 
					 | 
				
			||||||
	handler      Handler
 | 
					 | 
				
			||||||
	batchhandler BatchHandler
 | 
					 | 
				
			||||||
	id           string
 | 
					 | 
				
			||||||
	topic        string
 | 
					 | 
				
			||||||
	opts         SubscribeOptions
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *memoryBroker) Options() Options {
 | 
					 | 
				
			||||||
	return m.opts
 | 
						return m.opts
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *memoryBroker) Address() string {
 | 
					func (m *MemoryBroker) Address() string {
 | 
				
			||||||
	return m.addr
 | 
						return m.addr
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *memoryBroker) Connect(ctx context.Context) error {
 | 
					func (m *MemoryBroker) Connect(ctx context.Context) error {
 | 
				
			||||||
	m.Lock()
 | 
						m.Lock()
 | 
				
			||||||
	defer m.Unlock()
 | 
						defer m.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -69,35 +57,33 @@ func (m *memoryBroker) Connect(ctx context.Context) error {
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *memoryBroker) Disconnect(ctx context.Context) error {
 | 
					func (m *MemoryBroker) Disconnect(ctx context.Context) error {
 | 
				
			||||||
	m.Lock()
 | 
						m.Lock()
 | 
				
			||||||
	defer m.Unlock()
 | 
						defer m.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if !m.connected {
 | 
						select {
 | 
				
			||||||
		return nil
 | 
						case <-ctx.Done():
 | 
				
			||||||
 | 
							return ctx.Err()
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							if m.connected {
 | 
				
			||||||
 | 
								m.connected = false
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	m.connected = false
 | 
					 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *memoryBroker) Init(opts ...Option) error {
 | 
					func (m *MemoryBroker) Init(opts ...options.Option) error {
 | 
				
			||||||
 | 
						var err error
 | 
				
			||||||
	for _, o := range opts {
 | 
						for _, o := range opts {
 | 
				
			||||||
		o(&m.opts)
 | 
							if err = o(&m.opts); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *memoryBroker) Publish(ctx context.Context, topic string, msg *Message, opts ...PublishOption) error {
 | 
					func (m *MemoryBroker) Publish(ctx context.Context, message interface{}, opts ...options.Option) error {
 | 
				
			||||||
	msg.Header.Set(metadata.HeaderTopic, topic)
 | 
					 | 
				
			||||||
	return m.publish(ctx, []*Message{msg}, opts...)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *memoryBroker) BatchPublish(ctx context.Context, msgs []*Message, opts ...PublishOption) error {
 | 
					 | 
				
			||||||
	return m.publish(ctx, msgs, opts...)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *memoryBroker) publish(ctx context.Context, msgs []*Message, opts ...PublishOption) error {
 | 
					 | 
				
			||||||
	m.RLock()
 | 
						m.RLock()
 | 
				
			||||||
	if !m.connected {
 | 
						if !m.connected {
 | 
				
			||||||
		m.RUnlock()
 | 
							m.RUnlock()
 | 
				
			||||||
@@ -112,17 +98,29 @@ func (m *memoryBroker) publish(ctx context.Context, msgs []*Message, opts ...Pub
 | 
				
			|||||||
		return ctx.Err()
 | 
							return ctx.Err()
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		options := NewPublishOptions(opts...)
 | 
							options := NewPublishOptions(opts...)
 | 
				
			||||||
 | 
							var msgs []Message
 | 
				
			||||||
		msgTopicMap := make(map[string]Events)
 | 
							switch v := message.(type) {
 | 
				
			||||||
		for _, v := range msgs {
 | 
							case []Message:
 | 
				
			||||||
			p := &memoryEvent{opts: m.opts}
 | 
								msgs = v
 | 
				
			||||||
 | 
							case Message:
 | 
				
			||||||
			if m.opts.Codec == nil || options.BodyOnly {
 | 
								msgs = append(msgs, v)
 | 
				
			||||||
				p.topic, _ = v.Header.Get(metadata.HeaderTopic)
 | 
							default:
 | 
				
			||||||
				p.message = v.Body
 | 
								return ErrInvalidMessage
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							msgTopicMap := make(map[string][]*memoryMessage)
 | 
				
			||||||
 | 
							for _, msg := range msgs {
 | 
				
			||||||
 | 
								p := &memoryMessage{opts: options}
 | 
				
			||||||
 | 
								p.topic, _ = msg.Header().Get(metadata.HeaderTopic)
 | 
				
			||||||
 | 
								if v, ok := msg.Body().(*codec.Frame); ok {
 | 
				
			||||||
 | 
									p.body = msg.Body()
 | 
				
			||||||
 | 
								} else if len(m.opts.Codecs) == 0 {
 | 
				
			||||||
 | 
									p.body = msg.Body()
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				p.topic, _ = v.Header.Get(metadata.HeaderTopic)
 | 
									cf, ok := m.opts.Codecs[options.ContentType]
 | 
				
			||||||
				p.message, err = m.opts.Codec.Marshal(v)
 | 
									if !ok {
 | 
				
			||||||
 | 
										return fmt.Errorf("%s: %s", codec.ErrUnknownContentType, options.ContentType)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									p.body, err = cf.Marshal(v)
 | 
				
			||||||
				if err != nil {
 | 
									if err != nil {
 | 
				
			||||||
					return err
 | 
										return err
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
@@ -130,110 +128,96 @@ func (m *memoryBroker) publish(ctx context.Context, msgs []*Message, opts ...Pub
 | 
				
			|||||||
			msgTopicMap[p.topic] = append(msgTopicMap[p.topic], p)
 | 
								msgTopicMap[p.topic] = append(msgTopicMap[p.topic], p)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		beh := m.opts.BatchErrorHandler
 | 
					 | 
				
			||||||
		eh := m.opts.ErrorHandler
 | 
							eh := m.opts.ErrorHandler
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for t, ms := range msgTopicMap {
 | 
							for t, ms := range msgTopicMap {
 | 
				
			||||||
 | 
								ts := time.Now()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								m.opts.Meter.Counter(semconv.PublishMessageInflight, "endpoint", t).Add(len(ms))
 | 
				
			||||||
 | 
								m.opts.Meter.Counter(semconv.SubscribeMessageInflight, "endpoint", t).Add(len(ms))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			m.RLock()
 | 
								m.RLock()
 | 
				
			||||||
			subs, ok := m.subscribers[t]
 | 
								subs, ok := m.subscribers[t]
 | 
				
			||||||
			m.RUnlock()
 | 
								m.RUnlock()
 | 
				
			||||||
			if !ok {
 | 
								if !ok {
 | 
				
			||||||
 | 
									m.opts.Meter.Counter(semconv.PublishMessageTotal, "endpoint", t, "status", "failure").Add(len(ms))
 | 
				
			||||||
 | 
									m.opts.Meter.Counter(semconv.PublishMessageInflight, "endpoint", t).Add(-len(ms))
 | 
				
			||||||
 | 
									m.opts.Meter.Counter(semconv.SubscribeMessageInflight, "endpoint", t).Add(-len(ms))
 | 
				
			||||||
				continue
 | 
									continue
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								m.opts.Meter.Counter(semconv.PublishMessageTotal, "endpoint", t, "status", "success").Add(len(ms))
 | 
				
			||||||
			for _, sub := range subs {
 | 
								for _, sub := range subs {
 | 
				
			||||||
				if sub.opts.BatchErrorHandler != nil {
 | 
					 | 
				
			||||||
					beh = sub.opts.BatchErrorHandler
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				if sub.opts.ErrorHandler != nil {
 | 
									if sub.opts.ErrorHandler != nil {
 | 
				
			||||||
					eh = sub.opts.ErrorHandler
 | 
										eh = sub.opts.ErrorHandler
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				switch {
 | 
									switch mh := sub.handler.(type) {
 | 
				
			||||||
				// batch processing
 | 
									case MessagesHandler:
 | 
				
			||||||
				case sub.batchhandler != nil:
 | 
										mhs := make([]Message, 0, len(ms))
 | 
				
			||||||
					if err = sub.batchhandler(ms); err != nil {
 | 
										for _, m := range ms {
 | 
				
			||||||
						ms.SetError(err)
 | 
											mhs = append(mhs, m)
 | 
				
			||||||
						if beh != nil {
 | 
										}
 | 
				
			||||||
							_ = beh(ms)
 | 
										if err = mh(mhs); err != nil {
 | 
				
			||||||
 | 
											m.opts.Meter.Counter(semconv.SubscribeMessageTotal, "endpoint", t, "status", "failure").Add(len(ms))
 | 
				
			||||||
 | 
											if eh != nil {
 | 
				
			||||||
 | 
												switch meh := eh.(type) {
 | 
				
			||||||
 | 
												case MessagesHandler:
 | 
				
			||||||
 | 
													_ = meh(mhs)
 | 
				
			||||||
 | 
												case MessageHandler:
 | 
				
			||||||
 | 
													for _, me := range mhs {
 | 
				
			||||||
 | 
														_ = meh(me)
 | 
				
			||||||
 | 
													}
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
						} else if m.opts.Logger.V(logger.ErrorLevel) {
 | 
											} else if m.opts.Logger.V(logger.ErrorLevel) {
 | 
				
			||||||
							m.opts.Logger.Error(m.opts.Context, err.Error())
 | 
												m.opts.Logger.Error(m.opts.Context, err.Error())
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
					} else if sub.opts.AutoAck {
 | 
					 | 
				
			||||||
						if err = ms.Ack(); err != nil {
 | 
					 | 
				
			||||||
							m.opts.Logger.Errorf(m.opts.Context, "ack failed: %v", err)
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					// single processing
 | 
									case MessageHandler:
 | 
				
			||||||
				case sub.handler != nil:
 | 
					 | 
				
			||||||
					for _, p := range ms {
 | 
										for _, p := range ms {
 | 
				
			||||||
						if err = sub.handler(p); err != nil {
 | 
											if err = mh(p); err != nil {
 | 
				
			||||||
							p.SetError(err)
 | 
												m.opts.Meter.Counter(semconv.SubscribeMessageTotal, "endpoint", t, "status", "failure").Inc()
 | 
				
			||||||
							if eh != nil {
 | 
												if eh != nil {
 | 
				
			||||||
								_ = eh(p)
 | 
													switch meh := eh.(type) {
 | 
				
			||||||
 | 
													case MessageHandler:
 | 
				
			||||||
 | 
														_ = meh(p)
 | 
				
			||||||
 | 
													case MessagesHandler:
 | 
				
			||||||
 | 
														_ = meh([]Message{p})
 | 
				
			||||||
 | 
													}
 | 
				
			||||||
							} else if m.opts.Logger.V(logger.ErrorLevel) {
 | 
												} else if m.opts.Logger.V(logger.ErrorLevel) {
 | 
				
			||||||
								m.opts.Logger.Error(m.opts.Context, err.Error())
 | 
													m.opts.Logger.Error(m.opts.Context, err.Error())
 | 
				
			||||||
							}
 | 
												}
 | 
				
			||||||
						} else if sub.opts.AutoAck {
 | 
											} else {
 | 
				
			||||||
							if err = p.Ack(); err != nil {
 | 
												if sub.opts.AutoAck {
 | 
				
			||||||
								m.opts.Logger.Errorf(m.opts.Context, "ack failed: %v", err)
 | 
													if err = p.Ack(); err != nil {
 | 
				
			||||||
 | 
														m.opts.Logger.Errorf(m.opts.Context, "ack failed: %v", err)
 | 
				
			||||||
 | 
														m.opts.Meter.Counter(semconv.SubscribeMessageTotal, "endpoint", t, "status", "failure").Inc()
 | 
				
			||||||
 | 
													} else {
 | 
				
			||||||
 | 
														m.opts.Meter.Counter(semconv.SubscribeMessageTotal, "endpoint", t, "status", "success").Inc()
 | 
				
			||||||
 | 
													}
 | 
				
			||||||
 | 
												} else {
 | 
				
			||||||
 | 
													m.opts.Meter.Counter(semconv.SubscribeMessageTotal, "endpoint", t, "status", "success").Inc()
 | 
				
			||||||
							}
 | 
												}
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
 | 
											m.opts.Meter.Counter(semconv.PublishMessageInflight, "endpoint", t).Add(-1)
 | 
				
			||||||
 | 
											m.opts.Meter.Counter(semconv.SubscribeMessageInflight, "endpoint", t).Add(-1)
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								te := time.Since(ts)
 | 
				
			||||||
 | 
								m.opts.Meter.Summary(semconv.PublishMessageLatencyMicroseconds, "endpoint", t).Update(te.Seconds())
 | 
				
			||||||
 | 
								m.opts.Meter.Histogram(semconv.PublishMessageDurationSeconds, "endpoint", t).Update(te.Seconds())
 | 
				
			||||||
 | 
								m.opts.Meter.Summary(semconv.SubscribeMessageLatencyMicroseconds, "endpoint", t).Update(te.Seconds())
 | 
				
			||||||
 | 
								m.opts.Meter.Histogram(semconv.SubscribeMessageDurationSeconds, "endpoint", t).Update(te.Seconds())
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *memoryBroker) BatchSubscribe(ctx context.Context, topic string, handler BatchHandler, opts ...SubscribeOption) (Subscriber, error) {
 | 
					func (m *MemoryBroker) Subscribe(ctx context.Context, topic string, handler interface{}, opts ...options.Option) (Subscriber, error) {
 | 
				
			||||||
	m.RLock()
 | 
					 | 
				
			||||||
	if !m.connected {
 | 
					 | 
				
			||||||
		m.RUnlock()
 | 
					 | 
				
			||||||
		return nil, ErrNotConnected
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	m.RUnlock()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sid, err := id.New()
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	options := NewSubscribeOptions(opts...)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sub := &memorySubscriber{
 | 
					 | 
				
			||||||
		exit:         make(chan bool, 1),
 | 
					 | 
				
			||||||
		id:           sid,
 | 
					 | 
				
			||||||
		topic:        topic,
 | 
					 | 
				
			||||||
		batchhandler: handler,
 | 
					 | 
				
			||||||
		opts:         options,
 | 
					 | 
				
			||||||
		ctx:          ctx,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	m.Lock()
 | 
					 | 
				
			||||||
	m.subscribers[topic] = append(m.subscribers[topic], sub)
 | 
					 | 
				
			||||||
	m.Unlock()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	go func() {
 | 
					 | 
				
			||||||
		<-sub.exit
 | 
					 | 
				
			||||||
		m.Lock()
 | 
					 | 
				
			||||||
		newSubscribers := make([]*memorySubscriber, 0, len(m.subscribers)-1)
 | 
					 | 
				
			||||||
		for _, sb := range m.subscribers[topic] {
 | 
					 | 
				
			||||||
			if sb.id == sub.id {
 | 
					 | 
				
			||||||
				continue
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			newSubscribers = append(newSubscribers, sb)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		m.subscribers[topic] = newSubscribers
 | 
					 | 
				
			||||||
		m.Unlock()
 | 
					 | 
				
			||||||
	}()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return sub, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *memoryBroker) Subscribe(ctx context.Context, topic string, handler Handler, opts ...SubscribeOption) (Subscriber, error) {
 | 
					 | 
				
			||||||
	m.RLock()
 | 
						m.RLock()
 | 
				
			||||||
	if !m.connected {
 | 
						if !m.connected {
 | 
				
			||||||
		m.RUnlock()
 | 
							m.RUnlock()
 | 
				
			||||||
@@ -278,46 +262,54 @@ func (m *memoryBroker) Subscribe(ctx context.Context, topic string, handler Hand
 | 
				
			|||||||
	return sub, nil
 | 
						return sub, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *memoryBroker) String() string {
 | 
					func (m *MemoryBroker) String() string {
 | 
				
			||||||
	return "memory"
 | 
						return "memory"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *memoryBroker) Name() string {
 | 
					func (m *MemoryBroker) Name() string {
 | 
				
			||||||
	return m.opts.Name
 | 
						return m.opts.Name
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *memoryEvent) Topic() string {
 | 
					type memoryMessage struct {
 | 
				
			||||||
 | 
						err    error
 | 
				
			||||||
 | 
						body   interface{}
 | 
				
			||||||
 | 
						topic  string
 | 
				
			||||||
 | 
						header metadata.Metadata
 | 
				
			||||||
 | 
						opts   PublishOptions
 | 
				
			||||||
 | 
						ctx    context.Context
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *memoryMessage) Topic() string {
 | 
				
			||||||
	return m.topic
 | 
						return m.topic
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *memoryEvent) Message() *Message {
 | 
					func (m *memoryMessage) Header() metadata.Metadata {
 | 
				
			||||||
	switch v := m.message.(type) {
 | 
						return m.header
 | 
				
			||||||
	case *Message:
 | 
					}
 | 
				
			||||||
		return v
 | 
					 | 
				
			||||||
	case []byte:
 | 
					 | 
				
			||||||
		msg := &Message{}
 | 
					 | 
				
			||||||
		if err := m.opts.Codec.Unmarshal(v, msg); err != nil {
 | 
					 | 
				
			||||||
			if m.opts.Logger.V(logger.ErrorLevel) {
 | 
					 | 
				
			||||||
				m.opts.Logger.Error(m.opts.Context, "[memory]: failed to unmarshal: %v", err)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			return nil
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return msg
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *memoryMessage) Body() interface{} {
 | 
				
			||||||
 | 
						return m.body
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *memoryMessage) Ack() error {
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *memoryEvent) Ack() error {
 | 
					func (m *memoryMessage) Error() error {
 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *memoryEvent) Error() error {
 | 
					 | 
				
			||||||
	return m.err
 | 
						return m.err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *memoryEvent) SetError(err error) {
 | 
					func (m *memoryMessage) Context() context.Context {
 | 
				
			||||||
	m.err = err
 | 
						return m.ctx
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type memorySubscriber struct {
 | 
				
			||||||
 | 
						ctx     context.Context
 | 
				
			||||||
 | 
						exit    chan bool
 | 
				
			||||||
 | 
						handler interface{}
 | 
				
			||||||
 | 
						id      string
 | 
				
			||||||
 | 
						topic   string
 | 
				
			||||||
 | 
						opts    SubscribeOptions
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *memorySubscriber) Options() SubscribeOptions {
 | 
					func (m *memorySubscriber) Options() SubscribeOptions {
 | 
				
			||||||
@@ -334,8 +326,8 @@ func (m *memorySubscriber) Unsubscribe(ctx context.Context) error {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewBroker return new memory broker
 | 
					// NewBroker return new memory broker
 | 
				
			||||||
func NewBroker(opts ...Option) Broker {
 | 
					func NewBroker(opts ...options.Option) *MemoryBroker {
 | 
				
			||||||
	return &memoryBroker{
 | 
						return &MemoryBroker{
 | 
				
			||||||
		opts:        NewOptions(opts...),
 | 
							opts:        NewOptions(opts...),
 | 
				
			||||||
		subscribers: make(map[string][]*memorySubscriber),
 | 
							subscribers: make(map[string][]*memorySubscriber),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,7 +5,7 @@ import (
 | 
				
			|||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro/v3/metadata"
 | 
						"go.unistack.org/micro/v4/metadata"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestMemoryBatchBroker(t *testing.T) {
 | 
					func TestMemoryBatchBroker(t *testing.T) {
 | 
				
			||||||
@@ -19,29 +19,35 @@ func TestMemoryBatchBroker(t *testing.T) {
 | 
				
			|||||||
	topic := "test"
 | 
						topic := "test"
 | 
				
			||||||
	count := 10
 | 
						count := 10
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn := func(evts Events) error {
 | 
						fn := func(evts []Message) error {
 | 
				
			||||||
		return evts.Ack()
 | 
							var err error
 | 
				
			||||||
 | 
							for _, evt := range evts {
 | 
				
			||||||
 | 
								if err = evt.Ack(); err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sub, err := b.BatchSubscribe(ctx, topic, fn)
 | 
						sub, err := b.Subscribe(ctx, topic, fn)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Fatalf("Unexpected error subscribing %v", err)
 | 
							t.Fatalf("Unexpected error subscribing %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	msgs := make([]*Message, 0, count)
 | 
						msgs := make([]Message, 0, count)
 | 
				
			||||||
	for i := 0; i < count; i++ {
 | 
						for i := 0; i < count; i++ {
 | 
				
			||||||
		message := &Message{
 | 
							message := &memoryMessage{
 | 
				
			||||||
			Header: map[string]string{
 | 
								header: map[string]string{
 | 
				
			||||||
				metadata.HeaderTopic: topic,
 | 
									metadata.HeaderTopic: topic,
 | 
				
			||||||
				"foo":                "bar",
 | 
									"foo":                "bar",
 | 
				
			||||||
				"id":                 fmt.Sprintf("%d", i),
 | 
									"id":                 fmt.Sprintf("%d", i),
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			Body: []byte(`"hello world"`),
 | 
								body: []byte(`"hello world"`),
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		msgs = append(msgs, message)
 | 
							msgs = append(msgs, message)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := b.BatchPublish(ctx, msgs); err != nil {
 | 
						if err := b.Publish(ctx, msgs); err != nil {
 | 
				
			||||||
		t.Fatalf("Unexpected error publishing %v", err)
 | 
							t.Fatalf("Unexpected error publishing %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -65,8 +71,8 @@ func TestMemoryBroker(t *testing.T) {
 | 
				
			|||||||
	topic := "test"
 | 
						topic := "test"
 | 
				
			||||||
	count := 10
 | 
						count := 10
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn := func(p Event) error {
 | 
						fn := func(p Message) error {
 | 
				
			||||||
		return nil
 | 
							return p.Ack()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sub, err := b.Subscribe(ctx, topic, fn)
 | 
						sub, err := b.Subscribe(ctx, topic, fn)
 | 
				
			||||||
@@ -74,24 +80,20 @@ func TestMemoryBroker(t *testing.T) {
 | 
				
			|||||||
		t.Fatalf("Unexpected error subscribing %v", err)
 | 
							t.Fatalf("Unexpected error subscribing %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	msgs := make([]*Message, 0, count)
 | 
						msgs := make([]Message, 0, count)
 | 
				
			||||||
	for i := 0; i < count; i++ {
 | 
						for i := 0; i < count; i++ {
 | 
				
			||||||
		message := &Message{
 | 
							message := &memoryMessage{
 | 
				
			||||||
			Header: map[string]string{
 | 
								header: map[string]string{
 | 
				
			||||||
				metadata.HeaderTopic: topic,
 | 
									metadata.HeaderTopic: topic,
 | 
				
			||||||
				"foo":                "bar",
 | 
									"foo":                "bar",
 | 
				
			||||||
				"id":                 fmt.Sprintf("%d", i),
 | 
									"id":                 fmt.Sprintf("%d", i),
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			Body: []byte(`"hello world"`),
 | 
								body: []byte(`"hello world"`),
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		msgs = append(msgs, message)
 | 
							msgs = append(msgs, message)
 | 
				
			||||||
 | 
					 | 
				
			||||||
		if err := b.Publish(ctx, topic, message); err != nil {
 | 
					 | 
				
			||||||
			t.Fatalf("Unexpected error publishing %d err: %v", i, err)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := b.BatchPublish(ctx, msgs); err != nil {
 | 
						if err := b.Publish(ctx, msgs); err != nil {
 | 
				
			||||||
		t.Fatalf("Unexpected error publishing %v", err)
 | 
							t.Fatalf("Unexpected error publishing %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,11 +5,13 @@ import (
 | 
				
			|||||||
	"crypto/tls"
 | 
						"crypto/tls"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro/v3/codec"
 | 
						"go.unistack.org/micro/v4/codec"
 | 
				
			||||||
	"go.unistack.org/micro/v3/logger"
 | 
						"go.unistack.org/micro/v4/logger"
 | 
				
			||||||
	"go.unistack.org/micro/v3/meter"
 | 
						"go.unistack.org/micro/v4/metadata"
 | 
				
			||||||
	"go.unistack.org/micro/v3/register"
 | 
						"go.unistack.org/micro/v4/meter"
 | 
				
			||||||
	"go.unistack.org/micro/v3/tracer"
 | 
						"go.unistack.org/micro/v4/options"
 | 
				
			||||||
 | 
						"go.unistack.org/micro/v4/register"
 | 
				
			||||||
 | 
						"go.unistack.org/micro/v4/tracer"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Options struct
 | 
					// Options struct
 | 
				
			||||||
@@ -18,8 +20,8 @@ type Options struct {
 | 
				
			|||||||
	Tracer tracer.Tracer
 | 
						Tracer tracer.Tracer
 | 
				
			||||||
	// Register can be used for clustering
 | 
						// Register can be used for clustering
 | 
				
			||||||
	Register register.Register
 | 
						Register register.Register
 | 
				
			||||||
	// Codec holds the codec for marshal/unmarshal
 | 
						// Codecs holds the codec for marshal/unmarshal
 | 
				
			||||||
	Codec codec.Codec
 | 
						Codecs map[string]codec.Codec
 | 
				
			||||||
	// Logger used for logging
 | 
						// Logger used for logging
 | 
				
			||||||
	Logger logger.Logger
 | 
						Logger logger.Logger
 | 
				
			||||||
	// Meter used for metrics
 | 
						// Meter used for metrics
 | 
				
			||||||
@@ -28,24 +30,22 @@ type Options struct {
 | 
				
			|||||||
	Context context.Context
 | 
						Context context.Context
 | 
				
			||||||
	// TLSConfig holds tls.TLSConfig options
 | 
						// TLSConfig holds tls.TLSConfig options
 | 
				
			||||||
	TLSConfig *tls.Config
 | 
						TLSConfig *tls.Config
 | 
				
			||||||
	// ErrorHandler used when broker can't unmarshal incoming message
 | 
						// ErrorHandler used when broker have error while processing message
 | 
				
			||||||
	ErrorHandler Handler
 | 
						ErrorHandler interface{}
 | 
				
			||||||
	// BatchErrorHandler used when broker can't unmashal incoming messages
 | 
					 | 
				
			||||||
	BatchErrorHandler BatchHandler
 | 
					 | 
				
			||||||
	// Name holds the broker name
 | 
						// Name holds the broker name
 | 
				
			||||||
	Name string
 | 
						Name string
 | 
				
			||||||
	// Addrs holds the broker address
 | 
						// Address holds the broker address
 | 
				
			||||||
	Addrs []string
 | 
						Address []string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewOptions create new Options
 | 
					// NewOptions create new Options
 | 
				
			||||||
func NewOptions(opts ...Option) Options {
 | 
					func NewOptions(opts ...options.Option) Options {
 | 
				
			||||||
	options := Options{
 | 
						options := Options{
 | 
				
			||||||
		Register: register.DefaultRegister,
 | 
							Register: register.DefaultRegister,
 | 
				
			||||||
		Logger:   logger.DefaultLogger,
 | 
							Logger:   logger.DefaultLogger,
 | 
				
			||||||
		Context:  context.Background(),
 | 
							Context:  context.Background(),
 | 
				
			||||||
		Meter:    meter.DefaultMeter,
 | 
							Meter:    meter.DefaultMeter,
 | 
				
			||||||
		Codec:    codec.DefaultCodec,
 | 
							Codecs:   make(map[string]codec.Codec),
 | 
				
			||||||
		Tracer:   tracer.DefaultTracer,
 | 
							Tracer:   tracer.DefaultTracer,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for _, o := range opts {
 | 
						for _, o := range opts {
 | 
				
			||||||
@@ -54,23 +54,22 @@ func NewOptions(opts ...Option) Options {
 | 
				
			|||||||
	return options
 | 
						return options
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Context sets the context option
 | 
					 | 
				
			||||||
func Context(ctx context.Context) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Context = ctx
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// PublishOptions struct
 | 
					// PublishOptions struct
 | 
				
			||||||
type PublishOptions struct {
 | 
					type PublishOptions struct {
 | 
				
			||||||
	// Context holds external options
 | 
						// Context holds external options
 | 
				
			||||||
	Context context.Context
 | 
						Context context.Context
 | 
				
			||||||
	// BodyOnly flag says the message contains raw body bytes
 | 
						// BodyOnly flag says the message contains raw body bytes
 | 
				
			||||||
	BodyOnly bool
 | 
						BodyOnly bool
 | 
				
			||||||
 | 
						// Message metadata usually passed as message headers
 | 
				
			||||||
 | 
						Metadata metadata.Metadata
 | 
				
			||||||
 | 
						// Content-Type of message for marshal
 | 
				
			||||||
 | 
						ContentType string
 | 
				
			||||||
 | 
						// Topic destination
 | 
				
			||||||
 | 
						Topic string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewPublishOptions creates PublishOptions struct
 | 
					// NewPublishOptions creates PublishOptions struct
 | 
				
			||||||
func NewPublishOptions(opts ...PublishOption) PublishOptions {
 | 
					func NewPublishOptions(opts ...options.Option) PublishOptions {
 | 
				
			||||||
	options := PublishOptions{
 | 
						options := PublishOptions{
 | 
				
			||||||
		Context: context.Background(),
 | 
							Context: context.Background(),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -80,16 +79,21 @@ func NewPublishOptions(opts ...PublishOption) PublishOptions {
 | 
				
			|||||||
	return options
 | 
						return options
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// PublishTopic pass topic for messages
 | 
				
			||||||
 | 
					func PublishTopic(t string) options.Option {
 | 
				
			||||||
 | 
						return func(src interface{}) error {
 | 
				
			||||||
 | 
							return options.Set(src, t, ".Topic")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// SubscribeOptions struct
 | 
					// SubscribeOptions struct
 | 
				
			||||||
type SubscribeOptions struct {
 | 
					type SubscribeOptions struct {
 | 
				
			||||||
	// Context holds external options
 | 
						// Context holds external options
 | 
				
			||||||
	Context context.Context
 | 
						Context context.Context
 | 
				
			||||||
	// ErrorHandler used when broker can't unmarshal incoming message
 | 
						// ErrorHandler used when broker have error while processing message
 | 
				
			||||||
	ErrorHandler Handler
 | 
						ErrorHandler interface{}
 | 
				
			||||||
	// BatchErrorHandler used when broker can't unmashal incoming messages
 | 
						// QueueGroup holds consumer group
 | 
				
			||||||
	BatchErrorHandler BatchHandler
 | 
						QueueGroup string
 | 
				
			||||||
	// Group holds consumer group
 | 
					 | 
				
			||||||
	Group string
 | 
					 | 
				
			||||||
	// AutoAck flag specifies auto ack of incoming message when no error happens
 | 
						// AutoAck flag specifies auto ack of incoming message when no error happens
 | 
				
			||||||
	AutoAck bool
 | 
						AutoAck bool
 | 
				
			||||||
	// BodyOnly flag specifies that message contains only body bytes without header
 | 
						// BodyOnly flag specifies that message contains only body bytes without header
 | 
				
			||||||
@@ -100,179 +104,16 @@ type SubscribeOptions struct {
 | 
				
			|||||||
	BatchWait time.Duration
 | 
						BatchWait time.Duration
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Option func
 | 
					 | 
				
			||||||
type Option func(*Options)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// PublishOption func
 | 
					 | 
				
			||||||
type PublishOption func(*PublishOptions)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// PublishBodyOnly publish only body of the message
 | 
					 | 
				
			||||||
func PublishBodyOnly(b bool) PublishOption {
 | 
					 | 
				
			||||||
	return func(o *PublishOptions) {
 | 
					 | 
				
			||||||
		o.BodyOnly = b
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// PublishContext sets the context
 | 
					 | 
				
			||||||
func PublishContext(ctx context.Context) PublishOption {
 | 
					 | 
				
			||||||
	return func(o *PublishOptions) {
 | 
					 | 
				
			||||||
		o.Context = ctx
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Addrs sets the host addresses to be used by the broker
 | 
					 | 
				
			||||||
func Addrs(addrs ...string) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Addrs = addrs
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Codec sets the codec used for encoding/decoding used where
 | 
					 | 
				
			||||||
// a broker does not support headers
 | 
					 | 
				
			||||||
func Codec(c codec.Codec) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Codec = c
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ErrorHandler will catch all broker errors that cant be handled
 | 
					// ErrorHandler will catch all broker errors that cant be handled
 | 
				
			||||||
// in normal way, for example Codec errors
 | 
					// in normal way, for example Codec errors
 | 
				
			||||||
func ErrorHandler(h Handler) Option {
 | 
					func ErrorHandler(h interface{}) options.Option {
 | 
				
			||||||
	return func(o *Options) {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		o.ErrorHandler = h
 | 
							return options.Set(src, h, ".ErrorHandler")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// BatchErrorHandler will catch all broker errors that cant be handled
 | 
					 | 
				
			||||||
// in normal way, for example Codec errors
 | 
					 | 
				
			||||||
func BatchErrorHandler(h BatchHandler) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.BatchErrorHandler = h
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// SubscribeErrorHandler will catch all broker errors that cant be handled
 | 
					 | 
				
			||||||
// in normal way, for example Codec errors
 | 
					 | 
				
			||||||
func SubscribeErrorHandler(h Handler) SubscribeOption {
 | 
					 | 
				
			||||||
	return func(o *SubscribeOptions) {
 | 
					 | 
				
			||||||
		o.ErrorHandler = h
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// SubscribeBatchErrorHandler will catch all broker errors that cant be handled
 | 
					 | 
				
			||||||
// in normal way, for example Codec errors
 | 
					 | 
				
			||||||
func SubscribeBatchErrorHandler(h BatchHandler) SubscribeOption {
 | 
					 | 
				
			||||||
	return func(o *SubscribeOptions) {
 | 
					 | 
				
			||||||
		o.BatchErrorHandler = h
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Queue sets the subscribers queue
 | 
					 | 
				
			||||||
// Deprecated
 | 
					 | 
				
			||||||
func Queue(name string) SubscribeOption {
 | 
					 | 
				
			||||||
	return func(o *SubscribeOptions) {
 | 
					 | 
				
			||||||
		o.Group = name
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// SubscribeGroup sets the name of the queue to share messages on
 | 
					 | 
				
			||||||
func SubscribeGroup(name string) SubscribeOption {
 | 
					 | 
				
			||||||
	return func(o *SubscribeOptions) {
 | 
					 | 
				
			||||||
		o.Group = name
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Register sets register option
 | 
					 | 
				
			||||||
func Register(r register.Register) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Register = r
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// TLSConfig sets the TLS Config
 | 
					 | 
				
			||||||
func TLSConfig(t *tls.Config) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.TLSConfig = t
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Logger sets the logger
 | 
					 | 
				
			||||||
func Logger(l logger.Logger) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Logger = l
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Tracer to be used for tracing
 | 
					 | 
				
			||||||
func Tracer(t tracer.Tracer) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Tracer = t
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Meter sets the meter
 | 
					 | 
				
			||||||
func Meter(m meter.Meter) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Meter = m
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Name sets the name
 | 
					 | 
				
			||||||
func Name(n string) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Name = n
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// SubscribeContext set context
 | 
					 | 
				
			||||||
func SubscribeContext(ctx context.Context) SubscribeOption {
 | 
					 | 
				
			||||||
	return func(o *SubscribeOptions) {
 | 
					 | 
				
			||||||
		o.Context = ctx
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// DisableAutoAck disables auto ack
 | 
					 | 
				
			||||||
// Deprecated
 | 
					 | 
				
			||||||
func DisableAutoAck() SubscribeOption {
 | 
					 | 
				
			||||||
	return func(o *SubscribeOptions) {
 | 
					 | 
				
			||||||
		o.AutoAck = false
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// SubscribeAutoAck contol auto acking of messages
 | 
					 | 
				
			||||||
// after they have been handled.
 | 
					 | 
				
			||||||
func SubscribeAutoAck(b bool) SubscribeOption {
 | 
					 | 
				
			||||||
	return func(o *SubscribeOptions) {
 | 
					 | 
				
			||||||
		o.AutoAck = b
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// SubscribeBodyOnly consumes only body of the message
 | 
					 | 
				
			||||||
func SubscribeBodyOnly(b bool) SubscribeOption {
 | 
					 | 
				
			||||||
	return func(o *SubscribeOptions) {
 | 
					 | 
				
			||||||
		o.BodyOnly = b
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// SubscribeBatchSize specifies max batch size
 | 
					 | 
				
			||||||
func SubscribeBatchSize(n int) SubscribeOption {
 | 
					 | 
				
			||||||
	return func(o *SubscribeOptions) {
 | 
					 | 
				
			||||||
		o.BatchSize = n
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// SubscribeBatchWait specifies max batch wait time
 | 
					 | 
				
			||||||
func SubscribeBatchWait(td time.Duration) SubscribeOption {
 | 
					 | 
				
			||||||
	return func(o *SubscribeOptions) {
 | 
					 | 
				
			||||||
		o.BatchWait = td
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// SubscribeOption func
 | 
					 | 
				
			||||||
type SubscribeOption func(*SubscribeOptions)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// NewSubscribeOptions creates new SubscribeOptions
 | 
					// NewSubscribeOptions creates new SubscribeOptions
 | 
				
			||||||
func NewSubscribeOptions(opts ...SubscribeOption) SubscribeOptions {
 | 
					func NewSubscribeOptions(opts ...options.Option) SubscribeOptions {
 | 
				
			||||||
	options := SubscribeOptions{
 | 
						options := SubscribeOptions{
 | 
				
			||||||
		AutoAck: true,
 | 
							AutoAck: true,
 | 
				
			||||||
		Context: context.Background(),
 | 
							Context: context.Background(),
 | 
				
			||||||
@@ -282,3 +123,39 @@ func NewSubscribeOptions(opts ...SubscribeOption) SubscribeOptions {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	return options
 | 
						return options
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SubscribeAutoAck contol auto acking of messages
 | 
				
			||||||
 | 
					// after they have been handled.
 | 
				
			||||||
 | 
					func SubscribeAutoAck(b bool) options.Option {
 | 
				
			||||||
 | 
						return func(src interface{}) error {
 | 
				
			||||||
 | 
							return options.Set(src, b, ".AutoAck")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// BodyOnly transfer only body without
 | 
				
			||||||
 | 
					func BodyOnly(b bool) options.Option {
 | 
				
			||||||
 | 
						return func(src interface{}) error {
 | 
				
			||||||
 | 
							return options.Set(src, b, ".BodyOnly")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SubscribeBatchSize specifies max batch size
 | 
				
			||||||
 | 
					func SubscribeBatchSize(n int) options.Option {
 | 
				
			||||||
 | 
						return func(src interface{}) error {
 | 
				
			||||||
 | 
							return options.Set(src, n, ".BatchSize")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SubscribeBatchWait specifies max batch wait time
 | 
				
			||||||
 | 
					func SubscribeBatchWait(td time.Duration) options.Option {
 | 
				
			||||||
 | 
						return func(src interface{}) error {
 | 
				
			||||||
 | 
							return options.Set(src, td, ".BatchWait")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SubscribeQueueGroup sets the shared queue name distributed messages across subscribers
 | 
				
			||||||
 | 
					func SubscribeQueueGroup(n string) options.Option {
 | 
				
			||||||
 | 
						return func(src interface{}) error {
 | 
				
			||||||
 | 
							return options.Set(src, n, ".QueueGroup")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										98
									
								
								broker/subscriber.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								broker/subscriber.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,98 @@
 | 
				
			|||||||
 | 
					package broker
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"reflect"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
						"unicode"
 | 
				
			||||||
 | 
						"unicode/utf8"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						subSig      = "func(context.Context, interface{}) error"
 | 
				
			||||||
 | 
						batchSubSig = "func([]context.Context, []interface{}) error"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Precompute the reflect type for error. Can't use error directly
 | 
				
			||||||
 | 
					// because Typeof takes an empty interface value. This is annoying.
 | 
				
			||||||
 | 
					var typeOfError = reflect.TypeOf((*error)(nil)).Elem()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Is this an exported - upper case - name?
 | 
				
			||||||
 | 
					func isExported(name string) bool {
 | 
				
			||||||
 | 
						rune, _ := utf8.DecodeRuneInString(name)
 | 
				
			||||||
 | 
						return unicode.IsUpper(rune)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Is this type exported or a builtin?
 | 
				
			||||||
 | 
					func isExportedOrBuiltinType(t reflect.Type) bool {
 | 
				
			||||||
 | 
						for t.Kind() == reflect.Ptr {
 | 
				
			||||||
 | 
							t = t.Elem()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// PkgPath will be non-empty even for an exported type,
 | 
				
			||||||
 | 
						// so we need to check the type name as well.
 | 
				
			||||||
 | 
						return isExported(t.Name()) || t.PkgPath() == ""
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ValidateSubscriber func signature
 | 
				
			||||||
 | 
					func ValidateSubscriber(sub interface{}) error {
 | 
				
			||||||
 | 
						typ := reflect.TypeOf(sub)
 | 
				
			||||||
 | 
						var argType reflect.Type
 | 
				
			||||||
 | 
						switch typ.Kind() {
 | 
				
			||||||
 | 
						case reflect.Func:
 | 
				
			||||||
 | 
							name := "Func"
 | 
				
			||||||
 | 
							switch typ.NumIn() {
 | 
				
			||||||
 | 
							case 1: // func(Message) error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case 2: // func(context.Context, Message) error or func(context.Context, []Message) error
 | 
				
			||||||
 | 
								argType = typ.In(2)
 | 
				
			||||||
 | 
								// if sub.Options().Batch {
 | 
				
			||||||
 | 
								if argType.Kind() != reflect.Slice {
 | 
				
			||||||
 | 
									return fmt.Errorf("subscriber %v dont have required signature %s", name, batchSubSig)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if strings.Compare(fmt.Sprintf("%v", argType), "[]interface{}") == 0 {
 | 
				
			||||||
 | 
									return fmt.Errorf("subscriber %v dont have required signaure %s", name, batchSubSig)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							//	}
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								return fmt.Errorf("subscriber %v takes wrong number of args: %v required signature %s or %s", name, typ.NumIn(), subSig, batchSubSig)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if !isExportedOrBuiltinType(argType) {
 | 
				
			||||||
 | 
								return fmt.Errorf("subscriber %v argument type not exported: %v", name, argType)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if typ.NumOut() != 1 {
 | 
				
			||||||
 | 
								return fmt.Errorf("subscriber %v has wrong number of return values: %v require signature %s or %s",
 | 
				
			||||||
 | 
									name, typ.NumOut(), subSig, batchSubSig)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if returnType := typ.Out(0); returnType != typeOfError {
 | 
				
			||||||
 | 
								return fmt.Errorf("subscriber %v returns %v not error", name, returnType.String())
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							hdlr := reflect.ValueOf(sub)
 | 
				
			||||||
 | 
							name := reflect.Indirect(hdlr).Type().Name()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for m := 0; m < typ.NumMethod(); m++ {
 | 
				
			||||||
 | 
								method := typ.Method(m)
 | 
				
			||||||
 | 
								switch method.Type.NumIn() {
 | 
				
			||||||
 | 
								case 3:
 | 
				
			||||||
 | 
									argType = method.Type.In(2)
 | 
				
			||||||
 | 
								default:
 | 
				
			||||||
 | 
									return fmt.Errorf("subscriber %v.%v takes wrong number of args: %v required signature %s or %s",
 | 
				
			||||||
 | 
										name, method.Name, method.Type.NumIn(), subSig, batchSubSig)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if !isExportedOrBuiltinType(argType) {
 | 
				
			||||||
 | 
									return fmt.Errorf("%v argument type not exported: %v", name, argType)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if method.Type.NumOut() != 1 {
 | 
				
			||||||
 | 
									return fmt.Errorf(
 | 
				
			||||||
 | 
										"subscriber %v.%v has wrong number of return values: %v require signature %s or %s",
 | 
				
			||||||
 | 
										name, method.Name, method.Type.NumOut(), subSig, batchSubSig)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if returnType := method.Type.Out(0); returnType != typeOfError {
 | 
				
			||||||
 | 
									return fmt.Errorf("subscriber %v.%v returns %v not error", name, method.Name, returnType.String())
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -5,7 +5,7 @@ import (
 | 
				
			|||||||
	"math"
 | 
						"math"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro/v3/util/backoff"
 | 
						"go.unistack.org/micro/v4/util/backoff"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// BackoffFunc is the backoff call func
 | 
					// BackoffFunc is the backoff call func
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,12 +1,12 @@
 | 
				
			|||||||
// Package client is an interface for an RPC client
 | 
					// Package client is an interface for an RPC client
 | 
				
			||||||
package client // import "go.unistack.org/micro/v3/client"
 | 
					package client // import "go.unistack.org/micro/v4/client"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro/v3/codec"
 | 
						"go.unistack.org/micro/v4/codec"
 | 
				
			||||||
	"go.unistack.org/micro/v3/metadata"
 | 
						"go.unistack.org/micro/v4/options"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
@@ -22,6 +22,8 @@ var (
 | 
				
			|||||||
	DefaultRetries = 0
 | 
						DefaultRetries = 0
 | 
				
			||||||
	// DefaultRequestTimeout is the default request timeout
 | 
						// DefaultRequestTimeout is the default request timeout
 | 
				
			||||||
	DefaultRequestTimeout = time.Second * 5
 | 
						DefaultRequestTimeout = time.Second * 5
 | 
				
			||||||
 | 
						// DefaultDialTimeout the default dial timeout
 | 
				
			||||||
 | 
						DefaultDialTimeout = time.Second * 5
 | 
				
			||||||
	// DefaultPoolSize sets the connection pool size
 | 
						// DefaultPoolSize sets the connection pool size
 | 
				
			||||||
	DefaultPoolSize = 100
 | 
						DefaultPoolSize = 100
 | 
				
			||||||
	// DefaultPoolTTL sets the connection pool ttl
 | 
						// DefaultPoolTTL sets the connection pool ttl
 | 
				
			||||||
@@ -33,25 +35,14 @@ var (
 | 
				
			|||||||
// It also supports bidirectional streaming of requests.
 | 
					// It also supports bidirectional streaming of requests.
 | 
				
			||||||
type Client interface {
 | 
					type Client interface {
 | 
				
			||||||
	Name() string
 | 
						Name() string
 | 
				
			||||||
	Init(opts ...Option) error
 | 
						Init(opts ...options.Option) error
 | 
				
			||||||
	Options() Options
 | 
						Options() Options
 | 
				
			||||||
	NewMessage(topic string, msg interface{}, opts ...MessageOption) Message
 | 
						NewRequest(service string, endpoint string, req interface{}, opts ...options.Option) Request
 | 
				
			||||||
	NewRequest(service string, endpoint string, req interface{}, opts ...RequestOption) Request
 | 
						Call(ctx context.Context, req Request, rsp interface{}, opts ...options.Option) error
 | 
				
			||||||
	Call(ctx context.Context, req Request, rsp interface{}, opts ...CallOption) error
 | 
						Stream(ctx context.Context, req Request, opts ...options.Option) (Stream, error)
 | 
				
			||||||
	Stream(ctx context.Context, req Request, opts ...CallOption) (Stream, error)
 | 
					 | 
				
			||||||
	Publish(ctx context.Context, msg Message, opts ...PublishOption) error
 | 
					 | 
				
			||||||
	BatchPublish(ctx context.Context, msg []Message, opts ...PublishOption) error
 | 
					 | 
				
			||||||
	String() string
 | 
						String() string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Message is the interface for publishing asynchronously
 | 
					 | 
				
			||||||
type Message interface {
 | 
					 | 
				
			||||||
	Topic() string
 | 
					 | 
				
			||||||
	Payload() interface{}
 | 
					 | 
				
			||||||
	ContentType() string
 | 
					 | 
				
			||||||
	Metadata() metadata.Metadata
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Request is the interface for a synchronous request used by Call or Stream
 | 
					// Request is the interface for a synchronous request used by Call or Stream
 | 
				
			||||||
type Request interface {
 | 
					type Request interface {
 | 
				
			||||||
	// The service to call
 | 
						// The service to call
 | 
				
			||||||
@@ -68,16 +59,22 @@ type Request interface {
 | 
				
			|||||||
	Codec() codec.Codec
 | 
						Codec() codec.Codec
 | 
				
			||||||
	// indicates whether the request will be a streaming one rather than unary
 | 
						// indicates whether the request will be a streaming one rather than unary
 | 
				
			||||||
	Stream() bool
 | 
						Stream() bool
 | 
				
			||||||
 | 
						// Header data
 | 
				
			||||||
 | 
						// Header() metadata.Metadata
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Response is the response received from a service
 | 
					// Response is the response received from a service
 | 
				
			||||||
type Response interface {
 | 
					type Response interface {
 | 
				
			||||||
	// Read the response
 | 
						// Read the response
 | 
				
			||||||
	Codec() codec.Codec
 | 
						Codec() codec.Codec
 | 
				
			||||||
 | 
						// The content type
 | 
				
			||||||
 | 
						// ContentType() string
 | 
				
			||||||
	// Header data
 | 
						// Header data
 | 
				
			||||||
	Header() metadata.Metadata
 | 
						// Header() metadata.Metadata
 | 
				
			||||||
	// Read the undecoded response
 | 
						// Read the undecoded response
 | 
				
			||||||
	Read() ([]byte, error)
 | 
						Read() ([]byte, error)
 | 
				
			||||||
 | 
						// The unencoded request body
 | 
				
			||||||
 | 
						// Body() interface{}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Stream is the interface for a bidirectional synchronous stream
 | 
					// Stream is the interface for a bidirectional synchronous stream
 | 
				
			||||||
@@ -103,18 +100,3 @@ type Stream interface {
 | 
				
			|||||||
	// CloseSend closes the send direction of the stream
 | 
						// CloseSend closes the send direction of the stream
 | 
				
			||||||
	CloseSend() error
 | 
						CloseSend() error
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
// Option used by the Client
 | 
					 | 
				
			||||||
type Option func(*Options)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// CallOption used by Call or Stream
 | 
					 | 
				
			||||||
type CallOption func(*CallOptions)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// PublishOption used by Publish
 | 
					 | 
				
			||||||
type PublishOption func(*PublishOptions)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// MessageOption used by NewMessage
 | 
					 | 
				
			||||||
type MessageOption func(*MessageOptions)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// RequestOption used by NewRequest
 | 
					 | 
				
			||||||
type RequestOption func(*RequestOptions)
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,22 +2,24 @@ package client
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"go.unistack.org/micro/v4/options"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type clientCallOptions struct {
 | 
					type clientCallOptions struct {
 | 
				
			||||||
	Client
 | 
						Client
 | 
				
			||||||
	opts []CallOption
 | 
						opts []options.Option
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *clientCallOptions) Call(ctx context.Context, req Request, rsp interface{}, opts ...CallOption) error {
 | 
					func (s *clientCallOptions) Call(ctx context.Context, req Request, rsp interface{}, opts ...options.Option) error {
 | 
				
			||||||
	return s.Client.Call(ctx, req, rsp, append(s.opts, opts...)...)
 | 
						return s.Client.Call(ctx, req, rsp, append(s.opts, opts...)...)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *clientCallOptions) Stream(ctx context.Context, req Request, opts ...CallOption) (Stream, error) {
 | 
					func (s *clientCallOptions) Stream(ctx context.Context, req Request, opts ...options.Option) (Stream, error) {
 | 
				
			||||||
	return s.Client.Stream(ctx, req, append(s.opts, opts...)...)
 | 
						return s.Client.Stream(ctx, req, append(s.opts, opts...)...)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewClientCallOptions add CallOption to every call
 | 
					// NewClientCallOptions add CallOption to every call
 | 
				
			||||||
func NewClientCallOptions(c Client, opts ...CallOption) Client {
 | 
					func NewClientCallOptions(c Client, opts ...options.Option) Client {
 | 
				
			||||||
	return &clientCallOptions{c, opts}
 | 
						return &clientCallOptions{c, opts}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,6 +4,8 @@ import (
 | 
				
			|||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"go.unistack.org/micro/v4/options"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestNewClientCallOptions(t *testing.T) {
 | 
					func TestNewClientCallOptions(t *testing.T) {
 | 
				
			||||||
@@ -13,11 +15,11 @@ func TestNewClientCallOptions(t *testing.T) {
 | 
				
			|||||||
		return fn
 | 
							return fn
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	c := NewClientCallOptions(NewClient(),
 | 
						c := NewClientCallOptions(NewClient(),
 | 
				
			||||||
		WithAddress("127.0.0.1"),
 | 
							options.Address("127.0.0.1"),
 | 
				
			||||||
		WithCallWrapper(w),
 | 
							WithCallWrapper(w),
 | 
				
			||||||
		WithRequestTimeout(1*time.Millisecond),
 | 
							RequestTimeout(1*time.Millisecond),
 | 
				
			||||||
		WithRetries(0),
 | 
							Retries(0),
 | 
				
			||||||
		WithBackoff(BackoffInterval(10*time.Millisecond, 100*time.Millisecond)),
 | 
							Backoff(BackoffInterval(10*time.Millisecond, 100*time.Millisecond)),
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
	_ = c.Call(context.TODO(), c.NewRequest("service", "endpoint", nil), nil)
 | 
						_ = c.Call(context.TODO(), c.NewRequest("service", "endpoint", nil), nil)
 | 
				
			||||||
	if !flag {
 | 
						if !flag {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,33 +22,3 @@ func NewContext(ctx context.Context, c Client) context.Context {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	return context.WithValue(ctx, clientKey{}, c)
 | 
						return context.WithValue(ctx, clientKey{}, c)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
// SetPublishOption returns a function to setup a context with given value
 | 
					 | 
				
			||||||
func SetPublishOption(k, v interface{}) PublishOption {
 | 
					 | 
				
			||||||
	return func(o *PublishOptions) {
 | 
					 | 
				
			||||||
		if o.Context == nil {
 | 
					 | 
				
			||||||
			o.Context = context.Background()
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		o.Context = context.WithValue(o.Context, k, v)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// SetCallOption returns a function to setup a context with given value
 | 
					 | 
				
			||||||
func SetCallOption(k, v interface{}) CallOption {
 | 
					 | 
				
			||||||
	return func(o *CallOptions) {
 | 
					 | 
				
			||||||
		if o.Context == nil {
 | 
					 | 
				
			||||||
			o.Context = context.Background()
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		o.Context = context.WithValue(o.Context, k, v)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// SetOption returns a function to setup a context with given value
 | 
					 | 
				
			||||||
func SetOption(k, v interface{}) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		if o.Context == nil {
 | 
					 | 
				
			||||||
			o.Context = context.Background()
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		o.Context = context.WithValue(o.Context, k, v)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -38,36 +38,3 @@ func TestNewNilContext(t *testing.T) {
 | 
				
			|||||||
		t.Fatal("NewContext not works")
 | 
							t.Fatal("NewContext not works")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestSetPublishOption(t *testing.T) {
 | 
					 | 
				
			||||||
	type key struct{}
 | 
					 | 
				
			||||||
	o := SetPublishOption(key{}, "test")
 | 
					 | 
				
			||||||
	opts := &PublishOptions{}
 | 
					 | 
				
			||||||
	o(opts)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if v, ok := opts.Context.Value(key{}).(string); !ok || v == "" {
 | 
					 | 
				
			||||||
		t.Fatal("SetPublishOption not works")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestSetCallOption(t *testing.T) {
 | 
					 | 
				
			||||||
	type key struct{}
 | 
					 | 
				
			||||||
	o := SetCallOption(key{}, "test")
 | 
					 | 
				
			||||||
	opts := &CallOptions{}
 | 
					 | 
				
			||||||
	o(opts)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if v, ok := opts.Context.Value(key{}).(string); !ok || v == "" {
 | 
					 | 
				
			||||||
		t.Fatal("SetCallOption not works")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestSetOption(t *testing.T) {
 | 
					 | 
				
			||||||
	type key struct{}
 | 
					 | 
				
			||||||
	o := SetOption(key{}, "test")
 | 
					 | 
				
			||||||
	opts := &Options{}
 | 
					 | 
				
			||||||
	o(opts)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if v, ok := opts.Context.Value(key{}).(string); !ok || v == "" {
 | 
					 | 
				
			||||||
		t.Fatal("SetOption not works")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,8 +4,8 @@ import (
 | 
				
			|||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"sort"
 | 
						"sort"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro/v3/errors"
 | 
						"go.unistack.org/micro/v4/errors"
 | 
				
			||||||
	"go.unistack.org/micro/v3/router"
 | 
						"go.unistack.org/micro/v4/router"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// LookupFunc is used to lookup routes for a service
 | 
					// LookupFunc is used to lookup routes for a service
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										137
									
								
								client/noop.go
									
									
									
									
									
								
							
							
						
						
									
										137
									
								
								client/noop.go
									
									
									
									
									
								
							@@ -5,11 +5,12 @@ import (
 | 
				
			|||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro/v3/broker"
 | 
						"go.unistack.org/micro/v4/codec"
 | 
				
			||||||
	"go.unistack.org/micro/v3/codec"
 | 
						"go.unistack.org/micro/v4/errors"
 | 
				
			||||||
	"go.unistack.org/micro/v3/errors"
 | 
						"go.unistack.org/micro/v4/metadata"
 | 
				
			||||||
	"go.unistack.org/micro/v3/metadata"
 | 
						"go.unistack.org/micro/v4/options"
 | 
				
			||||||
	"go.unistack.org/micro/v3/selector"
 | 
						"go.unistack.org/micro/v4/selector"
 | 
				
			||||||
 | 
						"go.unistack.org/micro/v4/semconv"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DefaultCodecs will be used to encode/decode data
 | 
					// DefaultCodecs will be used to encode/decode data
 | 
				
			||||||
@@ -21,12 +22,6 @@ type noopClient struct {
 | 
				
			|||||||
	opts Options
 | 
						opts Options
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type noopMessage struct {
 | 
					 | 
				
			||||||
	topic   string
 | 
					 | 
				
			||||||
	payload interface{}
 | 
					 | 
				
			||||||
	opts    MessageOptions
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type noopRequest struct {
 | 
					type noopRequest struct {
 | 
				
			||||||
	body        interface{}
 | 
						body        interface{}
 | 
				
			||||||
	codec       codec.Codec
 | 
						codec       codec.Codec
 | 
				
			||||||
@@ -38,16 +33,12 @@ type noopRequest struct {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewClient returns new noop client
 | 
					// NewClient returns new noop client
 | 
				
			||||||
func NewClient(opts ...Option) Client {
 | 
					func NewClient(opts ...options.Option) Client {
 | 
				
			||||||
	nc := &noopClient{opts: NewOptions(opts...)}
 | 
						nc := &noopClient{opts: NewOptions(opts...)}
 | 
				
			||||||
	// wrap in reverse
 | 
						// wrap in reverse
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	c := Client(nc)
 | 
						c := Client(nc)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for i := len(nc.opts.Wrappers); i > 0; i-- {
 | 
					 | 
				
			||||||
		c = nc.opts.Wrappers[i-1](c)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return c
 | 
						return c
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -142,22 +133,6 @@ func (n *noopStream) CloseSend() error {
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (n *noopMessage) Topic() string {
 | 
					 | 
				
			||||||
	return n.topic
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (n *noopMessage) Payload() interface{} {
 | 
					 | 
				
			||||||
	return n.payload
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (n *noopMessage) ContentType() string {
 | 
					 | 
				
			||||||
	return n.opts.ContentType
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (n *noopMessage) Metadata() metadata.Metadata {
 | 
					 | 
				
			||||||
	return n.opts.Metadata
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (n *noopClient) newCodec(contentType string) (codec.Codec, error) {
 | 
					func (n *noopClient) newCodec(contentType string) (codec.Codec, error) {
 | 
				
			||||||
	if cf, ok := n.opts.Codecs[contentType]; ok {
 | 
						if cf, ok := n.opts.Codecs[contentType]; ok {
 | 
				
			||||||
		return cf, nil
 | 
							return cf, nil
 | 
				
			||||||
@@ -168,7 +143,7 @@ func (n *noopClient) newCodec(contentType string) (codec.Codec, error) {
 | 
				
			|||||||
	return nil, codec.ErrUnknownContentType
 | 
						return nil, codec.ErrUnknownContentType
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (n *noopClient) Init(opts ...Option) error {
 | 
					func (n *noopClient) Init(opts ...options.Option) error {
 | 
				
			||||||
	for _, o := range opts {
 | 
						for _, o := range opts {
 | 
				
			||||||
		o(&n.opts)
 | 
							o(&n.opts)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -183,7 +158,7 @@ func (n *noopClient) String() string {
 | 
				
			|||||||
	return "noop"
 | 
						return "noop"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (n *noopClient) Call(ctx context.Context, req Request, rsp interface{}, opts ...CallOption) error {
 | 
					func (n *noopClient) Call(ctx context.Context, req Request, rsp interface{}, opts ...options.Option) error {
 | 
				
			||||||
	// make a copy of call opts
 | 
						// make a copy of call opts
 | 
				
			||||||
	callOpts := n.opts.CallOptions
 | 
						callOpts := n.opts.CallOptions
 | 
				
			||||||
	for _, opt := range opts {
 | 
						for _, opt := range opts {
 | 
				
			||||||
@@ -200,7 +175,7 @@ func (n *noopClient) Call(ctx context.Context, req Request, rsp interface{}, opt
 | 
				
			|||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		// got a deadline so no need to setup context
 | 
							// got a deadline so no need to setup context
 | 
				
			||||||
		// but we need to set the timeout we pass along
 | 
							// but we need to set the timeout we pass along
 | 
				
			||||||
		opt := WithRequestTimeout(time.Until(d))
 | 
							opt := RequestTimeout(time.Until(d))
 | 
				
			||||||
		opt(&callOpts)
 | 
							opt(&callOpts)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -285,6 +260,9 @@ func (n *noopClient) Call(ctx context.Context, req Request, rsp interface{}, opt
 | 
				
			|||||||
	ch := make(chan error, callOpts.Retries)
 | 
						ch := make(chan error, callOpts.Retries)
 | 
				
			||||||
	var gerr error
 | 
						var gerr error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ts := time.Now()
 | 
				
			||||||
 | 
						endpoint := fmt.Sprintf("%s.%s", req.Service(), req.Endpoint())
 | 
				
			||||||
 | 
						n.opts.Meter.Counter(semconv.ClientRequestInflight, "endpoint", endpoint).Inc()
 | 
				
			||||||
	for i := 0; i <= callOpts.Retries; i++ {
 | 
						for i := 0; i <= callOpts.Retries; i++ {
 | 
				
			||||||
		go func() {
 | 
							go func() {
 | 
				
			||||||
			ch <- call(i)
 | 
								ch <- call(i)
 | 
				
			||||||
@@ -312,6 +290,16 @@ func (n *noopClient) Call(ctx context.Context, req Request, rsp interface{}, opt
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if gerr != nil {
 | 
				
			||||||
 | 
							n.opts.Meter.Counter(semconv.ClientRequestTotal, "endpoint", endpoint, "status", "failure").Inc()
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							n.opts.Meter.Counter(semconv.ClientRequestTotal, "endpoint", endpoint, "status", "success").Inc()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						n.opts.Meter.Counter(semconv.ClientRequestInflight, "endpoint", endpoint).Dec()
 | 
				
			||||||
 | 
						te := time.Since(ts)
 | 
				
			||||||
 | 
						n.opts.Meter.Summary(semconv.ClientRequestLatencyMicroseconds, "endpoint", endpoint).Update(te.Seconds())
 | 
				
			||||||
 | 
						n.opts.Meter.Histogram(semconv.ClientRequestDurationSeconds, "endpoint", endpoint).Update(te.Seconds())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return gerr
 | 
						return gerr
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -319,16 +307,11 @@ func (n *noopClient) call(ctx context.Context, addr string, req Request, rsp int
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (n *noopClient) NewRequest(service, endpoint string, req interface{}, opts ...RequestOption) Request {
 | 
					func (n *noopClient) NewRequest(service, endpoint string, req interface{}, opts ...options.Option) Request {
 | 
				
			||||||
	return &noopRequest{service: service, endpoint: endpoint}
 | 
						return &noopRequest{service: service, endpoint: endpoint}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (n *noopClient) NewMessage(topic string, msg interface{}, opts ...MessageOption) Message {
 | 
					func (n *noopClient) Stream(ctx context.Context, req Request, opts ...options.Option) (Stream, error) {
 | 
				
			||||||
	options := NewMessageOptions(append([]MessageOption{MessageContentType(n.opts.ContentType)}, opts...)...)
 | 
					 | 
				
			||||||
	return &noopMessage{topic: topic, payload: msg, opts: options}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (n *noopClient) Stream(ctx context.Context, req Request, opts ...CallOption) (Stream, error) {
 | 
					 | 
				
			||||||
	var err error
 | 
						var err error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// make a copy of call opts
 | 
						// make a copy of call opts
 | 
				
			||||||
@@ -347,7 +330,7 @@ func (n *noopClient) Stream(ctx context.Context, req Request, opts ...CallOption
 | 
				
			|||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		// got a deadline so no need to setup context
 | 
							// got a deadline so no need to setup context
 | 
				
			||||||
		// but we need to set the timeout we pass along
 | 
							// but we need to set the timeout we pass along
 | 
				
			||||||
		o := WithStreamTimeout(time.Until(d))
 | 
							o := StreamTimeout(time.Until(d))
 | 
				
			||||||
		o(&callOpts)
 | 
							o(&callOpts)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -414,7 +397,15 @@ func (n *noopClient) Stream(ctx context.Context, req Request, opts ...CallOption
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		node := next()
 | 
							node := next()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// ts := time.Now()
 | 
				
			||||||
 | 
							endpoint := fmt.Sprintf("%s.%s", req.Service(), req.Endpoint())
 | 
				
			||||||
 | 
							n.opts.Meter.Counter(semconv.ClientRequestInflight, "endpoint", endpoint).Inc()
 | 
				
			||||||
		stream, cerr := n.stream(ctx, node, req, callOpts)
 | 
							stream, cerr := n.stream(ctx, node, req, callOpts)
 | 
				
			||||||
 | 
							if cerr != nil {
 | 
				
			||||||
 | 
								n.opts.Meter.Counter(semconv.ClientRequestTotal, "endpoint", endpoint, "status", "failure").Inc()
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								n.opts.Meter.Counter(semconv.ClientRequestTotal, "endpoint", endpoint, "status", "success").Inc()
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// record the result of the call to inform future routing decisions
 | 
							// record the result of the call to inform future routing decisions
 | 
				
			||||||
		if verr := n.opts.Selector.Record(node, cerr); verr != nil {
 | 
							if verr := n.opts.Selector.Record(node, cerr); verr != nil {
 | 
				
			||||||
@@ -468,64 +459,6 @@ func (n *noopClient) Stream(ctx context.Context, req Request, opts ...CallOption
 | 
				
			|||||||
	return nil, grr
 | 
						return nil, grr
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (n *noopClient) stream(ctx context.Context, addr string, req Request, opts CallOptions) (Stream, error) {
 | 
					func (n *noopClient) stream(ctx context.Context, addr string, req Request, opts CallOptions) (*noopStream, error) {
 | 
				
			||||||
	return &noopStream{}, nil
 | 
						return &noopStream{}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
func (n *noopClient) BatchPublish(ctx context.Context, ps []Message, opts ...PublishOption) error {
 | 
					 | 
				
			||||||
	return n.publish(ctx, ps, opts...)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (n *noopClient) Publish(ctx context.Context, p Message, opts ...PublishOption) error {
 | 
					 | 
				
			||||||
	return n.publish(ctx, []Message{p}, opts...)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (n *noopClient) publish(ctx context.Context, ps []Message, opts ...PublishOption) error {
 | 
					 | 
				
			||||||
	options := NewPublishOptions(opts...)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	msgs := make([]*broker.Message, 0, len(ps))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for _, p := range ps {
 | 
					 | 
				
			||||||
		md, ok := metadata.FromOutgoingContext(ctx)
 | 
					 | 
				
			||||||
		if !ok {
 | 
					 | 
				
			||||||
			md = metadata.New(0)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		md[metadata.HeaderContentType] = p.ContentType()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		topic := p.Topic()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// get the exchange
 | 
					 | 
				
			||||||
		if len(options.Exchange) > 0 {
 | 
					 | 
				
			||||||
			topic = options.Exchange
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		md[metadata.HeaderTopic] = topic
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		var body []byte
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// passed in raw data
 | 
					 | 
				
			||||||
		if d, ok := p.Payload().(*codec.Frame); ok {
 | 
					 | 
				
			||||||
			body = d.Data
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			// use codec for payload
 | 
					 | 
				
			||||||
			cf, err := n.newCodec(p.ContentType())
 | 
					 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				return errors.InternalServerError("go.micro.client", err.Error())
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			// set the body
 | 
					 | 
				
			||||||
			b, err := cf.Marshal(p.Payload())
 | 
					 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				return errors.InternalServerError("go.micro.client", err.Error())
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			body = b
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		msgs = append(msgs, &broker.Message{Header: md, Body: body})
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return n.opts.Broker.BatchPublish(ctx, msgs,
 | 
					 | 
				
			||||||
		broker.PublishContext(options.Context),
 | 
					 | 
				
			||||||
		broker.PublishBodyOnly(options.BodyOnly),
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,31 +6,25 @@ import (
 | 
				
			|||||||
	"net"
 | 
						"net"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro/v3/broker"
 | 
						"go.unistack.org/micro/v4/codec"
 | 
				
			||||||
	"go.unistack.org/micro/v3/codec"
 | 
						"go.unistack.org/micro/v4/logger"
 | 
				
			||||||
	"go.unistack.org/micro/v3/logger"
 | 
						"go.unistack.org/micro/v4/metadata"
 | 
				
			||||||
	"go.unistack.org/micro/v3/metadata"
 | 
						"go.unistack.org/micro/v4/meter"
 | 
				
			||||||
	"go.unistack.org/micro/v3/meter"
 | 
						"go.unistack.org/micro/v4/options"
 | 
				
			||||||
	"go.unistack.org/micro/v3/network/transport"
 | 
						"go.unistack.org/micro/v4/router"
 | 
				
			||||||
	"go.unistack.org/micro/v3/register"
 | 
						"go.unistack.org/micro/v4/selector"
 | 
				
			||||||
	"go.unistack.org/micro/v3/router"
 | 
						"go.unistack.org/micro/v4/selector/random"
 | 
				
			||||||
	"go.unistack.org/micro/v3/selector"
 | 
						"go.unistack.org/micro/v4/tracer"
 | 
				
			||||||
	"go.unistack.org/micro/v3/selector/random"
 | 
					 | 
				
			||||||
	"go.unistack.org/micro/v3/tracer"
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 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
 | 
				
			||||||
	Logger logger.Logger
 | 
						Logger logger.Logger
 | 
				
			||||||
	// Tracer used for tracing
 | 
						// Tracer used for tracing
 | 
				
			||||||
	Tracer tracer.Tracer
 | 
						Tracer tracer.Tracer
 | 
				
			||||||
	// Broker used to publish messages
 | 
					 | 
				
			||||||
	Broker broker.Broker
 | 
					 | 
				
			||||||
	// Meter used for metrics
 | 
						// Meter used for metrics
 | 
				
			||||||
	Meter meter.Meter
 | 
						Meter meter.Meter
 | 
				
			||||||
	// Context is used for external options
 | 
						// Context is used for external options
 | 
				
			||||||
@@ -49,8 +43,6 @@ type Options struct {
 | 
				
			|||||||
	ContentType string
 | 
						ContentType string
 | 
				
			||||||
	// Name is the client name
 | 
						// Name is the client name
 | 
				
			||||||
	Name string
 | 
						Name string
 | 
				
			||||||
	// Wrappers contains wrappers
 | 
					 | 
				
			||||||
	Wrappers []Wrapper
 | 
					 | 
				
			||||||
	// CallOptions contains default CallOptions
 | 
						// CallOptions contains default CallOptions
 | 
				
			||||||
	CallOptions CallOptions
 | 
						CallOptions CallOptions
 | 
				
			||||||
	// PoolSize connection pool size
 | 
						// PoolSize connection pool size
 | 
				
			||||||
@@ -59,10 +51,12 @@ type Options struct {
 | 
				
			|||||||
	PoolTTL time.Duration
 | 
						PoolTTL time.Duration
 | 
				
			||||||
	// ContextDialer used to connect
 | 
						// ContextDialer used to connect
 | 
				
			||||||
	ContextDialer func(context.Context, string) (net.Conn, error)
 | 
						ContextDialer func(context.Context, string) (net.Conn, error)
 | 
				
			||||||
 | 
						// Hooks may contains Client func wrapper
 | 
				
			||||||
 | 
						Hooks options.Hooks
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewCallOptions creates new call options struct
 | 
					// NewCallOptions creates new call options struct
 | 
				
			||||||
func NewCallOptions(opts ...CallOption) CallOptions {
 | 
					func NewCallOptions(opts ...options.Option) CallOptions {
 | 
				
			||||||
	options := CallOptions{}
 | 
						options := CallOptions{}
 | 
				
			||||||
	for _, o := range opts {
 | 
						for _, o := range opts {
 | 
				
			||||||
		o(&options)
 | 
							o(&options)
 | 
				
			||||||
@@ -111,58 +105,14 @@ type CallOptions struct {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ContextDialer pass ContextDialer to client
 | 
					// ContextDialer pass ContextDialer to client
 | 
				
			||||||
func ContextDialer(fn func(context.Context, string) (net.Conn, error)) Option {
 | 
					func ContextDialer(fn func(context.Context, string) (net.Conn, error)) options.Option {
 | 
				
			||||||
	return func(o *Options) {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		o.ContextDialer = fn
 | 
							return options.Set(src, fn, ".ContextDialer")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Context pass context to client
 | 
					 | 
				
			||||||
func Context(ctx context.Context) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Context = ctx
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// NewPublishOptions create new PublishOptions struct from option
 | 
					 | 
				
			||||||
func NewPublishOptions(opts ...PublishOption) PublishOptions {
 | 
					 | 
				
			||||||
	options := PublishOptions{}
 | 
					 | 
				
			||||||
	for _, o := range opts {
 | 
					 | 
				
			||||||
		o(&options)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return options
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// PublishOptions holds publish options
 | 
					 | 
				
			||||||
type PublishOptions struct {
 | 
					 | 
				
			||||||
	// Context used for external options
 | 
					 | 
				
			||||||
	Context context.Context
 | 
					 | 
				
			||||||
	// Exchange topic exchange name
 | 
					 | 
				
			||||||
	Exchange string
 | 
					 | 
				
			||||||
	// BodyOnly will publish only message body
 | 
					 | 
				
			||||||
	BodyOnly bool
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// NewMessageOptions creates message options struct
 | 
					 | 
				
			||||||
func NewMessageOptions(opts ...MessageOption) MessageOptions {
 | 
					 | 
				
			||||||
	options := MessageOptions{Metadata: metadata.New(1)}
 | 
					 | 
				
			||||||
	for _, o := range opts {
 | 
					 | 
				
			||||||
		o(&options)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return options
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// MessageOptions holds client message options
 | 
					 | 
				
			||||||
type MessageOptions struct {
 | 
					 | 
				
			||||||
	// Metadata additional metadata
 | 
					 | 
				
			||||||
	Metadata metadata.Metadata
 | 
					 | 
				
			||||||
	// ContentType specify content-type of message
 | 
					 | 
				
			||||||
	// deprecated
 | 
					 | 
				
			||||||
	ContentType string
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// NewRequestOptions creates new RequestOptions struct
 | 
					// NewRequestOptions creates new RequestOptions struct
 | 
				
			||||||
func NewRequestOptions(opts ...RequestOption) RequestOptions {
 | 
					func NewRequestOptions(opts ...options.Option) RequestOptions {
 | 
				
			||||||
	options := RequestOptions{}
 | 
						options := RequestOptions{}
 | 
				
			||||||
	for _, o := range opts {
 | 
						for _, o := range opts {
 | 
				
			||||||
		o(&options)
 | 
							o(&options)
 | 
				
			||||||
@@ -181,7 +131,7 @@ type RequestOptions struct {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewOptions creates new options struct
 | 
					// NewOptions creates new options struct
 | 
				
			||||||
func NewOptions(opts ...Option) Options {
 | 
					func NewOptions(opts ...options.Option) Options {
 | 
				
			||||||
	options := Options{
 | 
						options := Options{
 | 
				
			||||||
		Context:     context.Background(),
 | 
							Context:     context.Background(),
 | 
				
			||||||
		ContentType: DefaultContentType,
 | 
							ContentType: DefaultContentType,
 | 
				
			||||||
@@ -192,18 +142,16 @@ func NewOptions(opts ...Option) Options {
 | 
				
			|||||||
			Retry:          DefaultRetry,
 | 
								Retry:          DefaultRetry,
 | 
				
			||||||
			Retries:        DefaultRetries,
 | 
								Retries:        DefaultRetries,
 | 
				
			||||||
			RequestTimeout: DefaultRequestTimeout,
 | 
								RequestTimeout: DefaultRequestTimeout,
 | 
				
			||||||
			DialTimeout:    transport.DefaultDialTimeout,
 | 
								DialTimeout:    DefaultDialTimeout,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		Lookup:    LookupRoute,
 | 
							Lookup:   LookupRoute,
 | 
				
			||||||
		PoolSize:  DefaultPoolSize,
 | 
							PoolSize: DefaultPoolSize,
 | 
				
			||||||
		PoolTTL:   DefaultPoolTTL,
 | 
							PoolTTL:  DefaultPoolTTL,
 | 
				
			||||||
		Selector:  random.NewSelector(),
 | 
							Selector: random.NewSelector(),
 | 
				
			||||||
		Logger:    logger.DefaultLogger,
 | 
							Logger:   logger.DefaultLogger,
 | 
				
			||||||
		Broker:    broker.DefaultBroker,
 | 
							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 {
 | 
				
			||||||
@@ -213,381 +161,131 @@ func NewOptions(opts ...Option) Options {
 | 
				
			|||||||
	return options
 | 
						return options
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Broker to be used for pub/sub
 | 
					 | 
				
			||||||
func Broker(b broker.Broker) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Broker = b
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Tracer to be used for tracing
 | 
					 | 
				
			||||||
func Tracer(t tracer.Tracer) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Tracer = t
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Logger to be used for log mesages
 | 
					 | 
				
			||||||
func Logger(l logger.Logger) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Logger = l
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Meter to be used for metrics
 | 
					 | 
				
			||||||
func Meter(m meter.Meter) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Meter = m
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Codec to be used to encode/decode requests for a given content type
 | 
					 | 
				
			||||||
func Codec(contentType string, c codec.Codec) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Codecs[contentType] = c
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ContentType used by default if not specified
 | 
					 | 
				
			||||||
func ContentType(ct string) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.ContentType = ct
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Proxy sets the proxy address
 | 
					// Proxy sets the proxy address
 | 
				
			||||||
func Proxy(addr string) Option {
 | 
					func Proxy(addr string) options.Option {
 | 
				
			||||||
	return func(o *Options) {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		o.Proxy = addr
 | 
							return options.Set(src, addr, ".Proxy")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// PoolSize sets the connection pool size
 | 
					// PoolSize sets the connection pool size
 | 
				
			||||||
func PoolSize(d int) Option {
 | 
					func PoolSize(d int) options.Option {
 | 
				
			||||||
	return func(o *Options) {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		o.PoolSize = d
 | 
							return options.Set(src, d, ".PoolSize")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// PoolTTL sets the connection pool ttl
 | 
					// PoolTTL sets the connection pool ttl
 | 
				
			||||||
func PoolTTL(d time.Duration) Option {
 | 
					func PoolTTL(td time.Duration) options.Option {
 | 
				
			||||||
	return func(o *Options) {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		o.PoolTTL = d
 | 
							return options.Set(src, td, ".PoolTTL")
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// 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
 | 
					 | 
				
			||||||
func Register(r register.Register) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		if o.Router != nil {
 | 
					 | 
				
			||||||
			_ = o.Router.Init(router.Register(r))
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Router is used to lookup routes for a service
 | 
					 | 
				
			||||||
func Router(r router.Router) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Router = r
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Selector is used to select a route
 | 
					// Selector is used to select a route
 | 
				
			||||||
func Selector(s selector.Selector) Option {
 | 
					func Selector(s selector.Selector) options.Option {
 | 
				
			||||||
	return func(o *Options) {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		o.Selector = s
 | 
							return options.Set(src, s, ".Selector")
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Wrap adds a wrapper to the list of options passed into the client
 | 
					 | 
				
			||||||
func Wrap(w Wrapper) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Wrappers = append(o.Wrappers, w)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// WrapCall adds a wrapper to the list of CallFunc wrappers
 | 
					 | 
				
			||||||
func WrapCall(cw ...CallWrapper) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.CallOptions.CallWrappers = append(o.CallOptions.CallWrappers, cw...)
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Backoff is used to set the backoff function used when retrying Calls
 | 
					// Backoff is used to set the backoff function used when retrying Calls
 | 
				
			||||||
func Backoff(fn BackoffFunc) Option {
 | 
					func Backoff(fn BackoffFunc) options.Option {
 | 
				
			||||||
	return func(o *Options) {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		o.CallOptions.Backoff = fn
 | 
							return options.Set(src, fn, ".Backoff")
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Name sets the client name
 | 
					 | 
				
			||||||
func Name(n string) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Name = n
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Lookup sets the lookup function to use for resolving service names
 | 
					// Lookup sets the lookup function to use for resolving service names
 | 
				
			||||||
func Lookup(l LookupFunc) Option {
 | 
					func Lookup(fn LookupFunc) options.Option {
 | 
				
			||||||
	return func(o *Options) {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		o.Lookup = l
 | 
							return options.Set(src, fn, ".Lookup")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TLSConfig specifies a *tls.Config
 | 
					// WithCallWrapper sets the retry function to be used when re-trying.
 | 
				
			||||||
func TLSConfig(t *tls.Config) Option {
 | 
					func WithCallWrapper(fn CallWrapper) options.Option {
 | 
				
			||||||
	return func(o *Options) {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		// set the internal tls
 | 
							return options.Set(src, fn, ".CallWrappers")
 | 
				
			||||||
		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),
 | 
					 | 
				
			||||||
		)
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Retries sets the retry count when making the request.
 | 
					// Retries sets the retry count when making the request.
 | 
				
			||||||
func Retries(i int) Option {
 | 
					func Retries(n int) options.Option {
 | 
				
			||||||
	return func(o *Options) {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		o.CallOptions.Retries = i
 | 
							return options.Set(src, n, ".Retries")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Retry sets the retry function to be used when re-trying.
 | 
					// Retry sets the retry function to be used when re-trying.
 | 
				
			||||||
func Retry(fn RetryFunc) Option {
 | 
					func Retry(fn RetryFunc) options.Option {
 | 
				
			||||||
	return func(o *Options) {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		o.CallOptions.Retry = fn
 | 
							return options.Set(src, fn, ".Retry")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// RequestTimeout is the request timeout.
 | 
					// RequestTimeout is the request timeout.
 | 
				
			||||||
func RequestTimeout(d time.Duration) Option {
 | 
					func RequestTimeout(td time.Duration) options.Option {
 | 
				
			||||||
	return func(o *Options) {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		o.CallOptions.RequestTimeout = d
 | 
							return options.Set(src, td, ".RequestTimeout")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// StreamTimeout sets the stream timeout
 | 
					// StreamTimeout sets the stream timeout
 | 
				
			||||||
func StreamTimeout(d time.Duration) Option {
 | 
					func StreamTimeout(td time.Duration) options.Option {
 | 
				
			||||||
	return func(o *Options) {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		o.CallOptions.StreamTimeout = d
 | 
							return options.Set(src, td, ".StreamTimeout")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DialTimeout sets the dial timeout
 | 
					// DialTimeout sets the dial timeout
 | 
				
			||||||
func DialTimeout(d time.Duration) Option {
 | 
					func DialTimeout(td time.Duration) options.Option {
 | 
				
			||||||
	return func(o *Options) {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		o.CallOptions.DialTimeout = d
 | 
							return options.Set(src, td, ".DialTimeout")
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// WithExchange sets the exchange to route a message through
 | 
					 | 
				
			||||||
// Deprecated
 | 
					 | 
				
			||||||
func WithExchange(e string) PublishOption {
 | 
					 | 
				
			||||||
	return func(o *PublishOptions) {
 | 
					 | 
				
			||||||
		o.Exchange = e
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// PublishExchange sets the exchange to route a message through
 | 
					 | 
				
			||||||
func PublishExchange(e string) PublishOption {
 | 
					 | 
				
			||||||
	return func(o *PublishOptions) {
 | 
					 | 
				
			||||||
		o.Exchange = e
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// WithBodyOnly publish only message body
 | 
					 | 
				
			||||||
// DERECATED
 | 
					 | 
				
			||||||
func WithBodyOnly(b bool) PublishOption {
 | 
					 | 
				
			||||||
	return func(o *PublishOptions) {
 | 
					 | 
				
			||||||
		o.BodyOnly = b
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// PublishBodyOnly publish only message body
 | 
					 | 
				
			||||||
func PublishBodyOnly(b bool) PublishOption {
 | 
					 | 
				
			||||||
	return func(o *PublishOptions) {
 | 
					 | 
				
			||||||
		o.BodyOnly = b
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// PublishContext sets the context in publish options
 | 
					 | 
				
			||||||
func PublishContext(ctx context.Context) PublishOption {
 | 
					 | 
				
			||||||
	return func(o *PublishOptions) {
 | 
					 | 
				
			||||||
		o.Context = ctx
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// WithContextDialer pass ContextDialer to client call
 | 
					 | 
				
			||||||
func WithContextDialer(fn func(context.Context, string) (net.Conn, error)) CallOption {
 | 
					 | 
				
			||||||
	return func(o *CallOptions) {
 | 
					 | 
				
			||||||
		o.ContextDialer = fn
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// WithContentType specifies call content type
 | 
					 | 
				
			||||||
func WithContentType(ct string) CallOption {
 | 
					 | 
				
			||||||
	return func(o *CallOptions) {
 | 
					 | 
				
			||||||
		o.ContentType = ct
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// WithAddress sets the remote addresses to use rather than using service discovery
 | 
					 | 
				
			||||||
func WithAddress(a ...string) CallOption {
 | 
					 | 
				
			||||||
	return func(o *CallOptions) {
 | 
					 | 
				
			||||||
		o.Address = a
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// WithCallWrapper is a CallOption which adds to the existing CallFunc wrappers
 | 
					 | 
				
			||||||
func WithCallWrapper(cw ...CallWrapper) CallOption {
 | 
					 | 
				
			||||||
	return func(o *CallOptions) {
 | 
					 | 
				
			||||||
		o.CallWrappers = append(o.CallWrappers, cw...)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// WithBackoff is a CallOption which overrides that which
 | 
					 | 
				
			||||||
// set in Options.CallOptions
 | 
					 | 
				
			||||||
func WithBackoff(fn BackoffFunc) CallOption {
 | 
					 | 
				
			||||||
	return func(o *CallOptions) {
 | 
					 | 
				
			||||||
		o.Backoff = fn
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// WithRetry is a CallOption which overrides that which
 | 
					 | 
				
			||||||
// set in Options.CallOptions
 | 
					 | 
				
			||||||
func WithRetry(fn RetryFunc) CallOption {
 | 
					 | 
				
			||||||
	return func(o *CallOptions) {
 | 
					 | 
				
			||||||
		o.Retry = fn
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// WithRetries is a CallOption which overrides that which
 | 
					 | 
				
			||||||
// set in Options.CallOptions
 | 
					 | 
				
			||||||
func WithRetries(i int) CallOption {
 | 
					 | 
				
			||||||
	return func(o *CallOptions) {
 | 
					 | 
				
			||||||
		o.Retries = i
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// WithResponseMetadata is a CallOption which adds metadata.Metadata to Options.CallOptions
 | 
					// WithResponseMetadata is a CallOption which adds metadata.Metadata to Options.CallOptions
 | 
				
			||||||
func WithResponseMetadata(md *metadata.Metadata) CallOption {
 | 
					func ResponseMetadata(md *metadata.Metadata) options.Option {
 | 
				
			||||||
	return func(o *CallOptions) {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		o.ResponseMetadata = md
 | 
							return options.Set(src, md, ".ResponseMetadata")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// WithRequestMetadata is a CallOption which adds metadata.Metadata to Options.CallOptions
 | 
					// WithRequestMetadata is a CallOption which adds metadata.Metadata to Options.CallOptions
 | 
				
			||||||
func WithRequestMetadata(md metadata.Metadata) CallOption {
 | 
					func RequestMetadata(md metadata.Metadata) options.Option {
 | 
				
			||||||
	return func(o *CallOptions) {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		o.RequestMetadata = md
 | 
							return options.Set(src, metadata.Copy(md), ".RequestMetadata")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// WithRequestTimeout is a CallOption which overrides that which
 | 
					// AuthToken is a CallOption which overrides the
 | 
				
			||||||
// set in Options.CallOptions
 | 
					 | 
				
			||||||
func WithRequestTimeout(d time.Duration) CallOption {
 | 
					 | 
				
			||||||
	return func(o *CallOptions) {
 | 
					 | 
				
			||||||
		o.RequestTimeout = d
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// WithStreamTimeout sets the stream timeout
 | 
					 | 
				
			||||||
func WithStreamTimeout(d time.Duration) CallOption {
 | 
					 | 
				
			||||||
	return func(o *CallOptions) {
 | 
					 | 
				
			||||||
		o.StreamTimeout = d
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// WithDialTimeout is a CallOption which overrides that which
 | 
					 | 
				
			||||||
// set in Options.CallOptions
 | 
					 | 
				
			||||||
func WithDialTimeout(d time.Duration) CallOption {
 | 
					 | 
				
			||||||
	return func(o *CallOptions) {
 | 
					 | 
				
			||||||
		o.DialTimeout = d
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// WithAuthToken is a CallOption which overrides the
 | 
					 | 
				
			||||||
// authorization header with the services own auth token
 | 
					// authorization header with the services own auth token
 | 
				
			||||||
func WithAuthToken(t string) CallOption {
 | 
					func AuthToken(t string) options.Option {
 | 
				
			||||||
	return func(o *CallOptions) {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		o.AuthToken = t
 | 
							return options.Set(src, t, ".AuthToken")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// WithNetwork is a CallOption which sets the network attribute
 | 
					// Network is a CallOption which sets the network attribute
 | 
				
			||||||
func WithNetwork(n string) CallOption {
 | 
					func Network(n string) options.Option {
 | 
				
			||||||
	return func(o *CallOptions) {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		o.Network = n
 | 
							return options.Set(src, n, ".Network")
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// WithRouter sets the router to use for this call
 | 
					 | 
				
			||||||
func WithRouter(r router.Router) CallOption {
 | 
					 | 
				
			||||||
	return func(o *CallOptions) {
 | 
					 | 
				
			||||||
		o.Router = r
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// WithSelector sets the selector to use for this call
 | 
					 | 
				
			||||||
func WithSelector(s selector.Selector) CallOption {
 | 
					 | 
				
			||||||
	return func(o *CallOptions) {
 | 
					 | 
				
			||||||
		o.Selector = s
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
// WithSelectOptions sets the options to pass to the selector for this call
 | 
					// WithSelectOptions sets the options to pass to the selector for this call
 | 
				
			||||||
func WithSelectOptions(sops ...selector.SelectOption) CallOption {
 | 
					func WithSelectOptions(sops ...selector.SelectOption) options.Option {
 | 
				
			||||||
	return func(o *CallOptions) {
 | 
						return func(o *CallOptions) {
 | 
				
			||||||
		o.SelectOptions = sops
 | 
							o.SelectOptions = sops
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
// WithMessageContentType sets the message content type
 | 
					 | 
				
			||||||
// Deprecated
 | 
					 | 
				
			||||||
func WithMessageContentType(ct string) MessageOption {
 | 
					 | 
				
			||||||
	return func(o *MessageOptions) {
 | 
					 | 
				
			||||||
		o.Metadata.Set(metadata.HeaderContentType, ct)
 | 
					 | 
				
			||||||
		o.ContentType = ct
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// MessageContentType sets the message content type
 | 
					 | 
				
			||||||
func MessageContentType(ct string) MessageOption {
 | 
					 | 
				
			||||||
	return func(o *MessageOptions) {
 | 
					 | 
				
			||||||
		o.Metadata.Set(metadata.HeaderContentType, ct)
 | 
					 | 
				
			||||||
		o.ContentType = ct
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// MessageMetadata sets the message metadata
 | 
					 | 
				
			||||||
func MessageMetadata(k, v string) MessageOption {
 | 
					 | 
				
			||||||
	return func(o *MessageOptions) {
 | 
					 | 
				
			||||||
		o.Metadata.Set(k, v)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
// StreamingRequest specifies that request is streaming
 | 
					// StreamingRequest specifies that request is streaming
 | 
				
			||||||
func StreamingRequest(b bool) RequestOption {
 | 
					func StreamingRequest(b bool) options.Option {
 | 
				
			||||||
	return func(o *RequestOptions) {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		o.Stream = b
 | 
							return options.Set(src, b, ".Stream")
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// RequestContentType specifies request content type
 | 
					 | 
				
			||||||
func RequestContentType(ct string) RequestOption {
 | 
					 | 
				
			||||||
	return func(o *RequestOptions) {
 | 
					 | 
				
			||||||
		o.ContentType = ct
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,7 +3,7 @@ package client
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro/v3/errors"
 | 
						"go.unistack.org/micro/v4/errors"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// RetryFunc that returning either false or a non-nil error will result in the call not being retried
 | 
					// RetryFunc that returning either false or a non-nil error will result in the call not being retried
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,7 +5,7 @@ import (
 | 
				
			|||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro/v3/errors"
 | 
						"go.unistack.org/micro/v4/errors"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestRetryAlways(t *testing.T) {
 | 
					func TestRetryAlways(t *testing.T) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
package client
 | 
					package client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"go.unistack.org/micro/v3/codec"
 | 
						"go.unistack.org/micro/v4/codec"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type testRequest struct {
 | 
					type testRequest struct {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,11 +1,11 @@
 | 
				
			|||||||
// Package codec is an interface for encoding messages
 | 
					// Package codec is an interface for encoding messages
 | 
				
			||||||
package codec // import "go.unistack.org/micro/v3/codec"
 | 
					package codec // import "go.unistack.org/micro/v4/codec"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro/v3/metadata"
 | 
						"go.unistack.org/micro/v4/metadata"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Message types
 | 
					// Message types
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
// Copyright 2021 Unistack LLC
 | 
					// Copyright 2021-2023 Unistack LLC
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// Licensed under the Apache License, Version 2.0 (the "License");
 | 
					// Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
// you may not use this file except in compliance with the License.
 | 
					// you may not use this file except in compliance with the License.
 | 
				
			||||||
@@ -17,7 +17,7 @@ syntax = "proto3";
 | 
				
			|||||||
package micro.codec;
 | 
					package micro.codec;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
option cc_enable_arenas = true;
 | 
					option cc_enable_arenas = true;
 | 
				
			||||||
option go_package = "go.unistack.org/micro/v3/codec;codec";
 | 
					option go_package = "go.unistack.org/micro/v4/codec;codec";
 | 
				
			||||||
option java_multiple_files = true;
 | 
					option java_multiple_files = true;
 | 
				
			||||||
option java_outer_classname = "MicroCodec";
 | 
					option java_outer_classname = "MicroCodec";
 | 
				
			||||||
option java_package = "micro.codec";
 | 
					option java_package = "micro.codec";
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,9 +3,9 @@ package codec
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro/v3/logger"
 | 
						"go.unistack.org/micro/v4/logger"
 | 
				
			||||||
	"go.unistack.org/micro/v3/meter"
 | 
						"go.unistack.org/micro/v4/meter"
 | 
				
			||||||
	"go.unistack.org/micro/v3/tracer"
 | 
						"go.unistack.org/micro/v4/tracer"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Option func
 | 
					// Option func
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,11 +1,13 @@
 | 
				
			|||||||
// Package config is an interface for dynamic configuration.
 | 
					// Package config is an interface for dynamic configuration.
 | 
				
			||||||
package config // import "go.unistack.org/micro/v3/config"
 | 
					package config // import "go.unistack.org/micro/v4/config"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
	"reflect"
 | 
						"reflect"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"go.unistack.org/micro/v4/options"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Validator interface {
 | 
					type Validator interface {
 | 
				
			||||||
@@ -37,15 +39,15 @@ type Config interface {
 | 
				
			|||||||
	// Name returns name of config
 | 
						// Name returns name of config
 | 
				
			||||||
	Name() string
 | 
						Name() string
 | 
				
			||||||
	// Init the config
 | 
						// Init the config
 | 
				
			||||||
	Init(opts ...Option) error
 | 
						Init(opts ...options.Option) error
 | 
				
			||||||
	// Options in the config
 | 
						// Options in the config
 | 
				
			||||||
	Options() Options
 | 
						Options() Options
 | 
				
			||||||
	// Load config from sources
 | 
						// Load config from sources
 | 
				
			||||||
	Load(context.Context, ...LoadOption) error
 | 
						Load(context.Context, ...options.Option) error
 | 
				
			||||||
	// Save config to sources
 | 
						// Save config to sources
 | 
				
			||||||
	Save(context.Context, ...SaveOption) error
 | 
						Save(context.Context, ...options.Option) error
 | 
				
			||||||
	// Watch a config for changes
 | 
						// Watch a config for changes
 | 
				
			||||||
	Watch(context.Context, ...WatchOption) (Watcher, error)
 | 
						Watch(context.Context, ...options.Option) (Watcher, error)
 | 
				
			||||||
	// String returns config type name
 | 
						// String returns config type name
 | 
				
			||||||
	String() string
 | 
						String() string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -59,7 +61,7 @@ type Watcher interface {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Load loads config from config sources
 | 
					// Load loads config from config sources
 | 
				
			||||||
func Load(ctx context.Context, cs []Config, opts ...LoadOption) error {
 | 
					func Load(ctx context.Context, cs []Config, opts ...options.Option) error {
 | 
				
			||||||
	var err error
 | 
						var err error
 | 
				
			||||||
	for _, c := range cs {
 | 
						for _, c := range cs {
 | 
				
			||||||
		if err = c.Init(); err != nil {
 | 
							if err = c.Init(); err != nil {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,43 +22,3 @@ func NewContext(ctx context.Context, c Config) context.Context {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	return context.WithValue(ctx, configKey{}, c)
 | 
						return context.WithValue(ctx, configKey{}, c)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
// SetOption returns a function to setup a context with given value
 | 
					 | 
				
			||||||
func SetOption(k, v interface{}) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		if o.Context == nil {
 | 
					 | 
				
			||||||
			o.Context = context.Background()
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		o.Context = context.WithValue(o.Context, k, v)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// SetSaveOption returns a function to setup a context with given value
 | 
					 | 
				
			||||||
func SetSaveOption(k, v interface{}) SaveOption {
 | 
					 | 
				
			||||||
	return func(o *SaveOptions) {
 | 
					 | 
				
			||||||
		if o.Context == nil {
 | 
					 | 
				
			||||||
			o.Context = context.Background()
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		o.Context = context.WithValue(o.Context, k, v)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// SetLoadOption returns a function to setup a context with given value
 | 
					 | 
				
			||||||
func SetLoadOption(k, v interface{}) LoadOption {
 | 
					 | 
				
			||||||
	return func(o *LoadOptions) {
 | 
					 | 
				
			||||||
		if o.Context == nil {
 | 
					 | 
				
			||||||
			o.Context = context.Background()
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		o.Context = context.WithValue(o.Context, k, v)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// SetWatchOption returns a function to setup a context with given value
 | 
					 | 
				
			||||||
func SetWatchOption(k, v interface{}) WatchOption {
 | 
					 | 
				
			||||||
	return func(o *WatchOptions) {
 | 
					 | 
				
			||||||
		if o.Context == nil {
 | 
					 | 
				
			||||||
			o.Context = context.Background()
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		o.Context = context.WithValue(o.Context, k, v)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -40,47 +40,3 @@ func TestNewContext(t *testing.T) {
 | 
				
			|||||||
		t.Fatal("NewContext not works")
 | 
							t.Fatal("NewContext not works")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestSetOption(t *testing.T) {
 | 
					 | 
				
			||||||
	type key struct{}
 | 
					 | 
				
			||||||
	o := SetOption(key{}, "test")
 | 
					 | 
				
			||||||
	opts := &Options{}
 | 
					 | 
				
			||||||
	o(opts)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if v, ok := opts.Context.Value(key{}).(string); !ok || v == "" {
 | 
					 | 
				
			||||||
		t.Fatal("SetOption not works")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestSetSaveOption(t *testing.T) {
 | 
					 | 
				
			||||||
	type key struct{}
 | 
					 | 
				
			||||||
	o := SetSaveOption(key{}, "test")
 | 
					 | 
				
			||||||
	opts := &SaveOptions{}
 | 
					 | 
				
			||||||
	o(opts)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if v, ok := opts.Context.Value(key{}).(string); !ok || v == "" {
 | 
					 | 
				
			||||||
		t.Fatal("SetSaveOption not works")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestSetLoadOption(t *testing.T) {
 | 
					 | 
				
			||||||
	type key struct{}
 | 
					 | 
				
			||||||
	o := SetLoadOption(key{}, "test")
 | 
					 | 
				
			||||||
	opts := &LoadOptions{}
 | 
					 | 
				
			||||||
	o(opts)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if v, ok := opts.Context.Value(key{}).(string); !ok || v == "" {
 | 
					 | 
				
			||||||
		t.Fatal("SetLoadOption not works")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestSetWatchOption(t *testing.T) {
 | 
					 | 
				
			||||||
	type key struct{}
 | 
					 | 
				
			||||||
	o := SetWatchOption(key{}, "test")
 | 
					 | 
				
			||||||
	opts := &WatchOptions{}
 | 
					 | 
				
			||||||
	o(opts)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if v, ok := opts.Context.Value(key{}).(string); !ok || v == "" {
 | 
					 | 
				
			||||||
		t.Fatal("SetWatchOption not works")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,9 +7,12 @@ import (
 | 
				
			|||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/google/uuid"
 | 
				
			||||||
	"github.com/imdario/mergo"
 | 
						"github.com/imdario/mergo"
 | 
				
			||||||
	rutil "go.unistack.org/micro/v3/util/reflect"
 | 
						"go.unistack.org/micro/v4/options"
 | 
				
			||||||
	mtime "go.unistack.org/micro/v3/util/time"
 | 
						mid "go.unistack.org/micro/v4/util/id"
 | 
				
			||||||
 | 
						rutil "go.unistack.org/micro/v4/util/reflect"
 | 
				
			||||||
 | 
						mtime "go.unistack.org/micro/v4/util/time"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type defaultConfig struct {
 | 
					type defaultConfig struct {
 | 
				
			||||||
@@ -20,7 +23,7 @@ func (c *defaultConfig) Options() Options {
 | 
				
			|||||||
	return c.opts
 | 
						return c.opts
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *defaultConfig) Init(opts ...Option) error {
 | 
					func (c *defaultConfig) Init(opts ...options.Option) error {
 | 
				
			||||||
	for _, o := range opts {
 | 
						for _, o := range opts {
 | 
				
			||||||
		o(&c.opts)
 | 
							o(&c.opts)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -36,7 +39,7 @@ func (c *defaultConfig) Init(opts ...Option) error {
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *defaultConfig) Load(ctx context.Context, opts ...LoadOption) error {
 | 
					func (c *defaultConfig) Load(ctx context.Context, opts ...options.Option) error {
 | 
				
			||||||
	if err := DefaultBeforeLoad(ctx, c); err != nil && !c.opts.AllowFail {
 | 
						if err := DefaultBeforeLoad(ctx, c); err != nil && !c.opts.AllowFail {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -124,6 +127,20 @@ func fillValue(value reflect.Value, val string) error {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		value.Set(reflect.ValueOf(v))
 | 
							value.Set(reflect.ValueOf(v))
 | 
				
			||||||
	case reflect.String:
 | 
						case reflect.String:
 | 
				
			||||||
 | 
							switch val {
 | 
				
			||||||
 | 
							case "micro:generate uuid":
 | 
				
			||||||
 | 
								uid, err := uuid.NewRandom()
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								val = uid.String()
 | 
				
			||||||
 | 
							case "micro:generate id":
 | 
				
			||||||
 | 
								uid, err := mid.New()
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								val = uid
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		value.Set(reflect.ValueOf(val))
 | 
							value.Set(reflect.ValueOf(val))
 | 
				
			||||||
	case reflect.Float32:
 | 
						case reflect.Float32:
 | 
				
			||||||
		v, err := strconv.ParseFloat(val, 32)
 | 
							v, err := strconv.ParseFloat(val, 32)
 | 
				
			||||||
@@ -169,7 +186,7 @@ func fillValue(value reflect.Value, val string) error {
 | 
				
			|||||||
				return err
 | 
									return err
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			value.Set(reflect.ValueOf(v))
 | 
								value.Set(reflect.ValueOf(v))
 | 
				
			||||||
		case value.Type().String() == "time.Duration" && value.Type().PkgPath() == "go.unistack.org/micro/v3/util/time":
 | 
							case value.Type().String() == "time.Duration" && value.Type().PkgPath() == "go.unistack.org/micro/v4/util/time":
 | 
				
			||||||
			v, err := mtime.ParseDuration(val)
 | 
								v, err := mtime.ParseDuration(val)
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				return err
 | 
									return err
 | 
				
			||||||
@@ -275,7 +292,7 @@ func fillValues(valueOf reflect.Value, tname string) error {
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *defaultConfig) Save(ctx context.Context, opts ...SaveOption) error {
 | 
					func (c *defaultConfig) Save(ctx context.Context, opts ...options.Option) error {
 | 
				
			||||||
	if err := DefaultBeforeSave(ctx, c); err != nil {
 | 
						if err := DefaultBeforeSave(ctx, c); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -295,12 +312,12 @@ func (c *defaultConfig) Name() string {
 | 
				
			|||||||
	return c.opts.Name
 | 
						return c.opts.Name
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *defaultConfig) Watch(ctx context.Context, opts ...WatchOption) (Watcher, error) {
 | 
					func (c *defaultConfig) Watch(ctx context.Context, opts ...options.Option) (Watcher, error) {
 | 
				
			||||||
	return nil, ErrWatcherNotImplemented
 | 
						return nil, ErrWatcherNotImplemented
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewConfig returns new default config source
 | 
					// NewConfig returns new default config source
 | 
				
			||||||
func NewConfig(opts ...Option) Config {
 | 
					func NewConfig(opts ...options.Option) Config {
 | 
				
			||||||
	options := NewOptions(opts...)
 | 
						options := NewOptions(opts...)
 | 
				
			||||||
	if len(options.StructTag) == 0 {
 | 
						if len(options.StructTag) == 0 {
 | 
				
			||||||
		options.StructTag = "default"
 | 
							options.StructTag = "default"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,17 +6,21 @@ import (
 | 
				
			|||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro/v3/config"
 | 
						"go.unistack.org/micro/v4/config"
 | 
				
			||||||
	mtime "go.unistack.org/micro/v3/util/time"
 | 
						mid "go.unistack.org/micro/v4/util/id"
 | 
				
			||||||
 | 
						mtime "go.unistack.org/micro/v4/util/time"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type cfg struct {
 | 
					type cfg struct {
 | 
				
			||||||
	StringValue    string `default:"string_value"`
 | 
						StringValue    string `default:"string_value"`
 | 
				
			||||||
	IgnoreValue    string `json:"-"`
 | 
						IgnoreValue    string `json:"-"`
 | 
				
			||||||
	StructValue    *cfgStructValue
 | 
						StructValue    *cfgStructValue
 | 
				
			||||||
	IntValue       int            `default:"99"`
 | 
						IntValue       int             `default:"99"`
 | 
				
			||||||
	DurationValue  time.Duration  `default:"10s"`
 | 
						DurationValue  time.Duration   `default:"10s"`
 | 
				
			||||||
	MDurationValue mtime.Duration `default:"10s"`
 | 
						MDurationValue mtime.Duration  `default:"10s"`
 | 
				
			||||||
 | 
						MapValue       map[string]bool `default:"key1=true,key2=false"`
 | 
				
			||||||
 | 
						UUIDValue      string          `default:"micro:generate uuid"`
 | 
				
			||||||
 | 
						IDValue        string          `default:"micro:generate id"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type cfgStructValue struct {
 | 
					type cfgStructValue struct {
 | 
				
			||||||
@@ -67,6 +71,21 @@ func TestDefault(t *testing.T) {
 | 
				
			|||||||
	if conf.StringValue != "after_load" {
 | 
						if conf.StringValue != "after_load" {
 | 
				
			||||||
		t.Fatal("AfterLoad option not working")
 | 
							t.Fatal("AfterLoad option not working")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if len(conf.MapValue) != 2 {
 | 
				
			||||||
 | 
							t.Fatalf("map value invalid: %#+v\n", conf.MapValue)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if conf.UUIDValue == "" {
 | 
				
			||||||
 | 
							t.Fatalf("uuid value empty")
 | 
				
			||||||
 | 
						} else if len(conf.UUIDValue) != 36 {
 | 
				
			||||||
 | 
							t.Fatalf("uuid value invalid: %s", conf.UUIDValue)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if conf.IDValue == "" {
 | 
				
			||||||
 | 
							t.Fatalf("id value empty")
 | 
				
			||||||
 | 
						} else if len(conf.IDValue) != mid.DefaultSize {
 | 
				
			||||||
 | 
							t.Fatalf("id value invalid: %s", conf.IDValue)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	_ = conf
 | 
						_ = conf
 | 
				
			||||||
	// t.Logf("%#+v\n", conf)
 | 
						// t.Logf("%#+v\n", conf)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,10 +4,11 @@ import (
 | 
				
			|||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro/v3/codec"
 | 
						"go.unistack.org/micro/v4/codec"
 | 
				
			||||||
	"go.unistack.org/micro/v3/logger"
 | 
						"go.unistack.org/micro/v4/logger"
 | 
				
			||||||
	"go.unistack.org/micro/v3/meter"
 | 
						"go.unistack.org/micro/v4/meter"
 | 
				
			||||||
	"go.unistack.org/micro/v3/tracer"
 | 
						"go.unistack.org/micro/v4/options"
 | 
				
			||||||
 | 
						"go.unistack.org/micro/v4/tracer"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Options hold the config options
 | 
					// Options hold the config options
 | 
				
			||||||
@@ -44,11 +45,8 @@ type Options struct {
 | 
				
			|||||||
	AllowFail bool
 | 
						AllowFail bool
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Option function signature
 | 
					 | 
				
			||||||
type Option func(o *Options)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// NewOptions new options struct with filed values
 | 
					// NewOptions new options struct with filed values
 | 
				
			||||||
func NewOptions(opts ...Option) Options {
 | 
					func NewOptions(opts ...options.Option) Options {
 | 
				
			||||||
	options := Options{
 | 
						options := Options{
 | 
				
			||||||
		Logger:  logger.DefaultLogger,
 | 
							Logger:  logger.DefaultLogger,
 | 
				
			||||||
		Meter:   meter.DefaultMeter,
 | 
							Meter:   meter.DefaultMeter,
 | 
				
			||||||
@@ -62,9 +60,6 @@ func NewOptions(opts ...Option) Options {
 | 
				
			|||||||
	return options
 | 
						return options
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// LoadOption function signature
 | 
					 | 
				
			||||||
type LoadOption func(o *LoadOptions)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// LoadOptions struct
 | 
					// LoadOptions struct
 | 
				
			||||||
type LoadOptions struct {
 | 
					type LoadOptions struct {
 | 
				
			||||||
	Struct   interface{}
 | 
						Struct   interface{}
 | 
				
			||||||
@@ -74,7 +69,7 @@ type LoadOptions struct {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewLoadOptions create LoadOptions struct with provided opts
 | 
					// NewLoadOptions create LoadOptions struct with provided opts
 | 
				
			||||||
func NewLoadOptions(opts ...LoadOption) LoadOptions {
 | 
					func NewLoadOptions(opts ...options.Option) LoadOptions {
 | 
				
			||||||
	options := LoadOptions{}
 | 
						options := LoadOptions{}
 | 
				
			||||||
	for _, o := range opts {
 | 
						for _, o := range opts {
 | 
				
			||||||
		o(&options)
 | 
							o(&options)
 | 
				
			||||||
@@ -83,44 +78,27 @@ func NewLoadOptions(opts ...LoadOption) LoadOptions {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// LoadOverride override values when load
 | 
					// LoadOverride override values when load
 | 
				
			||||||
func LoadOverride(b bool) LoadOption {
 | 
					func LoadOverride(b bool) options.Option {
 | 
				
			||||||
	return func(o *LoadOptions) {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		o.Override = b
 | 
							return options.Set(src, b, ".Override")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// LoadAppend override values when load
 | 
					// LoadAppend override values when load
 | 
				
			||||||
func LoadAppend(b bool) LoadOption {
 | 
					func LoadAppend(b bool) options.Option {
 | 
				
			||||||
	return func(o *LoadOptions) {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		o.Append = b
 | 
							return options.Set(src, b, ".Append")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// LoadStruct override struct for loading
 | 
					 | 
				
			||||||
func LoadStruct(src interface{}) LoadOption {
 | 
					 | 
				
			||||||
	return func(o *LoadOptions) {
 | 
					 | 
				
			||||||
		o.Struct = src
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// SaveOption function signature
 | 
					 | 
				
			||||||
type SaveOption func(o *SaveOptions)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// SaveOptions struct
 | 
					// SaveOptions struct
 | 
				
			||||||
type SaveOptions struct {
 | 
					type SaveOptions struct {
 | 
				
			||||||
	Struct  interface{}
 | 
						Struct  interface{}
 | 
				
			||||||
	Context context.Context
 | 
						Context context.Context
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// SaveStruct override struct for save to config
 | 
					 | 
				
			||||||
func SaveStruct(src interface{}) SaveOption {
 | 
					 | 
				
			||||||
	return func(o *SaveOptions) {
 | 
					 | 
				
			||||||
		o.Struct = src
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// NewSaveOptions fill SaveOptions struct
 | 
					// NewSaveOptions fill SaveOptions struct
 | 
				
			||||||
func NewSaveOptions(opts ...SaveOption) SaveOptions {
 | 
					func NewSaveOptions(opts ...options.Option) SaveOptions {
 | 
				
			||||||
	options := SaveOptions{}
 | 
						options := SaveOptions{}
 | 
				
			||||||
	for _, o := range opts {
 | 
						for _, o := range opts {
 | 
				
			||||||
		o(&options)
 | 
							o(&options)
 | 
				
			||||||
@@ -129,100 +107,65 @@ func NewSaveOptions(opts ...SaveOption) SaveOptions {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// AllowFail allows config source to fail
 | 
					// AllowFail allows config source to fail
 | 
				
			||||||
func AllowFail(b bool) Option {
 | 
					func AllowFail(b bool) options.Option {
 | 
				
			||||||
	return func(o *Options) {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		o.AllowFail = b
 | 
							return options.Set(src, b, ".AllowFail")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// BeforeInit run funcs before config Init
 | 
					// BeforeInit run funcs before config Init
 | 
				
			||||||
func BeforeInit(fn ...func(context.Context, Config) error) Option {
 | 
					func BeforeInit(fn ...func(context.Context, Config) error) options.Option {
 | 
				
			||||||
	return func(o *Options) {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		o.BeforeInit = fn
 | 
							return options.Set(src, fn, ".BeforeInit")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// AfterInit run funcs after config Init
 | 
					// AfterInit run funcs after config Init
 | 
				
			||||||
func AfterInit(fn ...func(context.Context, Config) error) Option {
 | 
					func AfterInit(fn ...func(context.Context, Config) error) options.Option {
 | 
				
			||||||
	return func(o *Options) {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		o.AfterInit = fn
 | 
							return options.Set(src, fn, ".AfterInit")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// BeforeLoad run funcs before config load
 | 
					// BeforeLoad run funcs before config load
 | 
				
			||||||
func BeforeLoad(fn ...func(context.Context, Config) error) Option {
 | 
					func BeforeLoad(fn ...func(context.Context, Config) error) options.Option {
 | 
				
			||||||
	return func(o *Options) {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		o.BeforeLoad = fn
 | 
							return options.Set(src, fn, ".BeforeLoad")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// AfterLoad run funcs after config load
 | 
					// AfterLoad run funcs after config load
 | 
				
			||||||
func AfterLoad(fn ...func(context.Context, Config) error) Option {
 | 
					func AfterLoad(fn ...func(context.Context, Config) error) options.Option {
 | 
				
			||||||
	return func(o *Options) {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		o.AfterLoad = fn
 | 
							return options.Set(src, fn, ".AfterLoad")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// BeforeSave run funcs before save
 | 
					// BeforeSave run funcs before save
 | 
				
			||||||
func BeforeSave(fn ...func(context.Context, Config) error) Option {
 | 
					func BeforeSave(fn ...func(context.Context, Config) error) options.Option {
 | 
				
			||||||
	return func(o *Options) {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		o.BeforeSave = fn
 | 
							return options.Set(src, fn, ".BeforeSave")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// AfterSave run fncs after save
 | 
					// AfterSave run fncs after save
 | 
				
			||||||
func AfterSave(fn ...func(context.Context, Config) error) Option {
 | 
					func AfterSave(fn ...func(context.Context, Config) error) options.Option {
 | 
				
			||||||
	return func(o *Options) {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		o.AfterSave = fn
 | 
							return options.Set(src, fn, ".AfterSave")
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Context pass context
 | 
					 | 
				
			||||||
func Context(ctx context.Context) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Context = ctx
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Codec sets the source codec
 | 
					 | 
				
			||||||
func Codec(c codec.Codec) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Codec = c
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Logger sets the logger
 | 
					 | 
				
			||||||
func Logger(l logger.Logger) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Logger = l
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Tracer to be used for tracing
 | 
					 | 
				
			||||||
func Tracer(t tracer.Tracer) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Tracer = t
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Struct used as config
 | 
					// Struct used as config
 | 
				
			||||||
func Struct(v interface{}) Option {
 | 
					func Struct(v interface{}) options.Option {
 | 
				
			||||||
	return func(o *Options) {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		o.Struct = v
 | 
							return options.Set(src, v, ".Struct")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// StructTag sets the struct tag that used for filling
 | 
					// StructTag sets the struct tag that used for filling
 | 
				
			||||||
func StructTag(name string) Option {
 | 
					func StructTag(name string) options.Option {
 | 
				
			||||||
	return func(o *Options) {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		o.StructTag = name
 | 
							return options.Set(src, name, ".StructTag")
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Name sets the name
 | 
					 | 
				
			||||||
func Name(n string) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Name = n
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -240,11 +183,8 @@ type WatchOptions struct {
 | 
				
			|||||||
	Coalesce bool
 | 
						Coalesce bool
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// WatchOption func signature
 | 
					 | 
				
			||||||
type WatchOption func(*WatchOptions)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// NewWatchOptions create WatchOptions struct with provided opts
 | 
					// NewWatchOptions create WatchOptions struct with provided opts
 | 
				
			||||||
func NewWatchOptions(opts ...WatchOption) WatchOptions {
 | 
					func NewWatchOptions(opts ...options.Option) WatchOptions {
 | 
				
			||||||
	options := WatchOptions{
 | 
						options := WatchOptions{
 | 
				
			||||||
		Context:     context.Background(),
 | 
							Context:     context.Background(),
 | 
				
			||||||
		MinInterval: DefaultWatcherMinInterval,
 | 
							MinInterval: DefaultWatcherMinInterval,
 | 
				
			||||||
@@ -256,31 +196,20 @@ func NewWatchOptions(opts ...WatchOption) WatchOptions {
 | 
				
			|||||||
	return options
 | 
						return options
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// WatchContext pass context
 | 
					// Coalesce controls watch event combining
 | 
				
			||||||
func WatchContext(ctx context.Context) WatchOption {
 | 
					func WatchCoalesce(b bool) options.Option {
 | 
				
			||||||
	return func(o *WatchOptions) {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		o.Context = ctx
 | 
							return options.Set(src, b, ".Coalesce")
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// WatchCoalesce controls watch event combining
 | 
					 | 
				
			||||||
func WatchCoalesce(b bool) WatchOption {
 | 
					 | 
				
			||||||
	return func(o *WatchOptions) {
 | 
					 | 
				
			||||||
		o.Coalesce = b
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// WatchInterval specifies min and max time.Duration for pulling changes
 | 
					// WatchInterval specifies min and max time.Duration for pulling changes
 | 
				
			||||||
func WatchInterval(min, max time.Duration) WatchOption {
 | 
					func WatchInterval(min, max time.Duration) options.Option {
 | 
				
			||||||
	return func(o *WatchOptions) {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		o.MinInterval = min
 | 
							var err error
 | 
				
			||||||
		o.MaxInterval = max
 | 
							if err = options.Set(src, min, ".MinInterval"); err == nil {
 | 
				
			||||||
	}
 | 
								err = options.Set(src, max, ".MaxInterval")
 | 
				
			||||||
}
 | 
							}
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
// WatchStruct overrides struct for fill
 | 
					 | 
				
			||||||
func WatchStruct(src interface{}) WatchOption {
 | 
					 | 
				
			||||||
	return func(o *WatchOptions) {
 | 
					 | 
				
			||||||
		o.Struct = src
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
// Package errors provides a way to return detailed information
 | 
					// Package errors provides a way to return detailed information
 | 
				
			||||||
// for an RPC request error. The error is normally JSON encoded.
 | 
					// for an RPC request error. The error is normally JSON encoded.
 | 
				
			||||||
package errors // import "go.unistack.org/micro/v3/errors"
 | 
					package errors // import "go.unistack.org/micro/v4/errors"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"bytes"
 | 
						"bytes"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
// Copyright 2021 Unistack LLC
 | 
					// Copyright 2021-2023 Unistack LLC
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// Licensed under the Apache License, Version 2.0 (the "License");
 | 
					// Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
// you may not use this file except in compliance with the License.
 | 
					// you may not use this file except in compliance with the License.
 | 
				
			||||||
@@ -17,7 +17,7 @@ syntax = "proto3";
 | 
				
			|||||||
package micro.errors;
 | 
					package micro.errors;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
option cc_enable_arenas = true;
 | 
					option cc_enable_arenas = true;
 | 
				
			||||||
option go_package = "go.unistack.org/micro/v3/errors;errors";
 | 
					option go_package = "go.unistack.org/micro/v4/errors;errors";
 | 
				
			||||||
option java_multiple_files = true;
 | 
					option java_multiple_files = true;
 | 
				
			||||||
option java_outer_classname = "MicroErrors";
 | 
					option java_outer_classname = "MicroErrors";
 | 
				
			||||||
option java_package = "micro.errors";
 | 
					option java_package = "micro.errors";
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										27
									
								
								event.go
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								event.go
									
									
									
									
									
								
							@@ -1,27 +0,0 @@
 | 
				
			|||||||
package micro
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"context"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"go.unistack.org/micro/v3/client"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Event is used to publish messages to a topic
 | 
					 | 
				
			||||||
type Event interface {
 | 
					 | 
				
			||||||
	// Publish publishes a message to the event topic
 | 
					 | 
				
			||||||
	Publish(ctx context.Context, msg interface{}, opts ...client.PublishOption) error
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type event struct {
 | 
					 | 
				
			||||||
	c     client.Client
 | 
					 | 
				
			||||||
	topic string
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// NewEvent creates a new event publisher
 | 
					 | 
				
			||||||
func NewEvent(topic string, c client.Client) Event {
 | 
					 | 
				
			||||||
	return &event{c, topic}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (e *event) Publish(ctx context.Context, msg interface{}, opts ...client.PublishOption) error {
 | 
					 | 
				
			||||||
	return e.c.Publish(ctx, e.c.NewMessage(e.topic, msg), opts...)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -22,13 +22,3 @@ func NewContext(ctx context.Context, f Flow) context.Context {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	return context.WithValue(ctx, flowKey{}, f)
 | 
						return context.WithValue(ctx, flowKey{}, f)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
// SetOption returns a function to setup a context with given value
 | 
					 | 
				
			||||||
func SetOption(k, v interface{}) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		if o.Context == nil {
 | 
					 | 
				
			||||||
			o.Context = context.Background()
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		o.Context = context.WithValue(o.Context, k, v)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -40,14 +40,3 @@ func TestNewContext(t *testing.T) {
 | 
				
			|||||||
		t.Fatal("NewContext not works")
 | 
							t.Fatal("NewContext not works")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestSetOption(t *testing.T) {
 | 
					 | 
				
			||||||
	type key struct{}
 | 
					 | 
				
			||||||
	o := SetOption(key{}, "test")
 | 
					 | 
				
			||||||
	opts := &Options{}
 | 
					 | 
				
			||||||
	o(opts)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if v, ok := opts.Context.Value(key{}).(string); !ok || v == "" {
 | 
					 | 
				
			||||||
		t.Fatal("SetOption not works")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,12 +6,14 @@ import (
 | 
				
			|||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/silas/dag"
 | 
						"github.com/silas/dag"
 | 
				
			||||||
	"go.unistack.org/micro/v3/client"
 | 
						"go.unistack.org/micro/v4/client"
 | 
				
			||||||
	"go.unistack.org/micro/v3/codec"
 | 
						"go.unistack.org/micro/v4/codec"
 | 
				
			||||||
	"go.unistack.org/micro/v3/logger"
 | 
						"go.unistack.org/micro/v4/logger"
 | 
				
			||||||
	"go.unistack.org/micro/v3/metadata"
 | 
						"go.unistack.org/micro/v4/metadata"
 | 
				
			||||||
	"go.unistack.org/micro/v3/store"
 | 
						"go.unistack.org/micro/v4/options"
 | 
				
			||||||
	"go.unistack.org/micro/v3/util/id"
 | 
						moptions "go.unistack.org/micro/v4/options"
 | 
				
			||||||
 | 
						"go.unistack.org/micro/v4/store"
 | 
				
			||||||
 | 
						"go.unistack.org/micro/v4/util/id"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type microFlow struct {
 | 
					type microFlow struct {
 | 
				
			||||||
@@ -163,7 +165,7 @@ func (w *microWorkflow) Resume(ctx context.Context, id string) error {
 | 
				
			|||||||
	return workflowStore.Write(ctx, "status", &codec.Frame{Data: []byte(StatusRunning.String())})
 | 
						return workflowStore.Write(ctx, "status", &codec.Frame{Data: []byte(StatusRunning.String())})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (w *microWorkflow) Execute(ctx context.Context, req *Message, opts ...ExecuteOption) (string, error) {
 | 
					func (w *microWorkflow) Execute(ctx context.Context, req *Message, opts ...options.Option) (string, error) {
 | 
				
			||||||
	w.Lock()
 | 
						w.Lock()
 | 
				
			||||||
	if !w.init {
 | 
						if !w.init {
 | 
				
			||||||
		if err := w.g.Validate(); err != nil {
 | 
							if err := w.g.Validate(); err != nil {
 | 
				
			||||||
@@ -200,13 +202,13 @@ func (w *microWorkflow) Execute(ctx context.Context, req *Message, opts ...Execu
 | 
				
			|||||||
	nctx, cancel := context.WithCancel(ctx)
 | 
						nctx, cancel := context.WithCancel(ctx)
 | 
				
			||||||
	defer cancel()
 | 
						defer cancel()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	nopts := make([]ExecuteOption, 0, len(opts)+5)
 | 
						nopts := make([]moptions.Option, 0, len(opts)+5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	nopts = append(nopts,
 | 
						nopts = append(nopts,
 | 
				
			||||||
		ExecuteClient(w.opts.Client),
 | 
							moptions.Client(w.opts.Client),
 | 
				
			||||||
		ExecuteTracer(w.opts.Tracer),
 | 
							moptions.Tracer(w.opts.Tracer),
 | 
				
			||||||
		ExecuteLogger(w.opts.Logger),
 | 
							moptions.Logger(w.opts.Logger),
 | 
				
			||||||
		ExecuteMeter(w.opts.Meter),
 | 
							moptions.Meter(w.opts.Meter),
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
	nopts = append(nopts, opts...)
 | 
						nopts = append(nopts, opts...)
 | 
				
			||||||
	done := make(chan struct{})
 | 
						done := make(chan struct{})
 | 
				
			||||||
@@ -349,7 +351,7 @@ func (w *microWorkflow) Execute(ctx context.Context, req *Message, opts ...Execu
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewFlow create new flow
 | 
					// NewFlow create new flow
 | 
				
			||||||
func NewFlow(opts ...Option) Flow {
 | 
					func NewFlow(opts ...options.Option) Flow {
 | 
				
			||||||
	options := NewOptions(opts...)
 | 
						options := NewOptions(opts...)
 | 
				
			||||||
	return µFlow{opts: options}
 | 
						return µFlow{opts: options}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -358,7 +360,7 @@ func (f *microFlow) Options() Options {
 | 
				
			|||||||
	return f.opts
 | 
						return f.opts
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (f *microFlow) Init(opts ...Option) error {
 | 
					func (f *microFlow) Init(opts ...options.Option) error {
 | 
				
			||||||
	for _, o := range opts {
 | 
						for _, o := range opts {
 | 
				
			||||||
		o(&f.opts)
 | 
							o(&f.opts)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -487,17 +489,17 @@ func (s *microCallStep) SetStatus(status Status) {
 | 
				
			|||||||
	s.status = status
 | 
						s.status = status
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *microCallStep) Execute(ctx context.Context, req *Message, opts ...ExecuteOption) (*Message, error) {
 | 
					func (s *microCallStep) Execute(ctx context.Context, req *Message, opts ...options.Option) (*Message, error) {
 | 
				
			||||||
	options := NewExecuteOptions(opts...)
 | 
						options := NewExecuteOptions(opts...)
 | 
				
			||||||
	if options.Client == nil {
 | 
						if options.Client == nil {
 | 
				
			||||||
		return nil, ErrMissingClient
 | 
							return nil, ErrMissingClient
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	rsp := &codec.Frame{}
 | 
						rsp := &codec.Frame{}
 | 
				
			||||||
	copts := []client.CallOption{client.WithRetries(0)}
 | 
						copts := []moptions.Option{client.Retries(0)}
 | 
				
			||||||
	if options.Timeout > 0 {
 | 
						if options.Timeout > 0 {
 | 
				
			||||||
		copts = append(copts,
 | 
							copts = append(copts,
 | 
				
			||||||
			client.WithRequestTimeout(options.Timeout),
 | 
								client.RequestTimeout(options.Timeout),
 | 
				
			||||||
			client.WithDialTimeout(options.Timeout))
 | 
								client.DialTimeout(options.Timeout))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	nctx := metadata.NewOutgoingContext(ctx, req.Header)
 | 
						nctx := metadata.NewOutgoingContext(ctx, req.Header)
 | 
				
			||||||
	err := options.Client.Call(nctx, options.Client.NewRequest(s.service, s.method, &codec.Frame{Data: req.Body}), rsp, copts...)
 | 
						err := options.Client.Call(nctx, options.Client.NewRequest(s.service, s.method, &codec.Frame{Data: req.Body}), rsp, copts...)
 | 
				
			||||||
@@ -570,18 +572,18 @@ func (s *microPublishStep) SetStatus(status Status) {
 | 
				
			|||||||
	s.status = status
 | 
						s.status = status
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *microPublishStep) Execute(ctx context.Context, req *Message, opts ...ExecuteOption) (*Message, error) {
 | 
					func (s *microPublishStep) Execute(ctx context.Context, req *Message, opts ...options.Option) (*Message, error) {
 | 
				
			||||||
	return nil, nil
 | 
						return nil, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewCallStep create new step with client.Call
 | 
					// NewCallStep create new step with client.Call
 | 
				
			||||||
func NewCallStep(service string, name string, method string, opts ...StepOption) Step {
 | 
					func NewCallStep(service string, name string, method string, opts ...options.Option) Step {
 | 
				
			||||||
	options := NewStepOptions(opts...)
 | 
						options := NewStepOptions(opts...)
 | 
				
			||||||
	return µCallStep{service: service, method: name + "." + method, opts: options}
 | 
						return µCallStep{service: service, method: name + "." + method, opts: options}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewPublishStep create new step with client.Publish
 | 
					// NewPublishStep create new step with client.Publish
 | 
				
			||||||
func NewPublishStep(topic string, opts ...StepOption) Step {
 | 
					func NewPublishStep(topic string, opts ...options.Option) Step {
 | 
				
			||||||
	options := NewStepOptions(opts...)
 | 
						options := NewStepOptions(opts...)
 | 
				
			||||||
	return µPublishStep{topic: topic, opts: options}
 | 
						return µPublishStep{topic: topic, opts: options}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										11
									
								
								flow/flow.go
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								flow/flow.go
									
									
									
									
									
								
							@@ -1,5 +1,5 @@
 | 
				
			|||||||
// Package flow is an interface used for saga pattern microservice workflow
 | 
					// Package flow is an interface used for saga pattern microservice workflow
 | 
				
			||||||
package flow // import "go.unistack.org/micro/v3/flow"
 | 
					package flow // import "go.unistack.org/micro/v4/flow"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
@@ -7,7 +7,8 @@ import (
 | 
				
			|||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
	"sync/atomic"
 | 
						"sync/atomic"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro/v3/metadata"
 | 
						"go.unistack.org/micro/v4/metadata"
 | 
				
			||||||
 | 
						"go.unistack.org/micro/v4/options"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
@@ -51,7 +52,7 @@ type Step interface {
 | 
				
			|||||||
	// Endpoint returns rpc endpoint service_name.service_method or broker topic
 | 
						// Endpoint returns rpc endpoint service_name.service_method or broker topic
 | 
				
			||||||
	Endpoint() string
 | 
						Endpoint() string
 | 
				
			||||||
	// Execute step run
 | 
						// Execute step run
 | 
				
			||||||
	Execute(ctx context.Context, req *Message, opts ...ExecuteOption) (*Message, error)
 | 
						Execute(ctx context.Context, req *Message, opts ...options.Option) (*Message, error)
 | 
				
			||||||
	// Requires returns dependent steps
 | 
						// Requires returns dependent steps
 | 
				
			||||||
	Requires() []string
 | 
						Requires() []string
 | 
				
			||||||
	// Options returns step options
 | 
						// Options returns step options
 | 
				
			||||||
@@ -118,7 +119,7 @@ type Workflow interface {
 | 
				
			|||||||
	// ID returns id of the workflow
 | 
						// ID returns id of the workflow
 | 
				
			||||||
	ID() string
 | 
						ID() string
 | 
				
			||||||
	// Execute workflow with args, return execution id and error
 | 
						// Execute workflow with args, return execution id and error
 | 
				
			||||||
	Execute(ctx context.Context, req *Message, opts ...ExecuteOption) (string, error)
 | 
						Execute(ctx context.Context, req *Message, opts ...options.Option) (string, error)
 | 
				
			||||||
	// RemoveSteps remove steps from workflow
 | 
						// RemoveSteps remove steps from workflow
 | 
				
			||||||
	RemoveSteps(steps ...Step) error
 | 
						RemoveSteps(steps ...Step) error
 | 
				
			||||||
	// AppendSteps append steps to workflow
 | 
						// AppendSteps append steps to workflow
 | 
				
			||||||
@@ -140,7 +141,7 @@ type Flow interface {
 | 
				
			|||||||
	// Options returns options
 | 
						// Options returns options
 | 
				
			||||||
	Options() Options
 | 
						Options() Options
 | 
				
			||||||
	// Init initialize
 | 
						// Init initialize
 | 
				
			||||||
	Init(...Option) error
 | 
						Init(...options.Option) error
 | 
				
			||||||
	// WorkflowCreate creates new workflow with specific id and steps
 | 
						// WorkflowCreate creates new workflow with specific id and steps
 | 
				
			||||||
	WorkflowCreate(ctx context.Context, id string, steps ...Step) (Workflow, error)
 | 
						WorkflowCreate(ctx context.Context, id string, steps ...Step) (Workflow, error)
 | 
				
			||||||
	// WorkflowSave saves workflow
 | 
						// WorkflowSave saves workflow
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										162
									
								
								flow/options.go
									
									
									
									
									
								
							
							
						
						
									
										162
									
								
								flow/options.go
									
									
									
									
									
								
							@@ -4,16 +4,14 @@ import (
 | 
				
			|||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro/v3/client"
 | 
						"go.unistack.org/micro/v4/client"
 | 
				
			||||||
	"go.unistack.org/micro/v3/logger"
 | 
						"go.unistack.org/micro/v4/logger"
 | 
				
			||||||
	"go.unistack.org/micro/v3/meter"
 | 
						"go.unistack.org/micro/v4/meter"
 | 
				
			||||||
	"go.unistack.org/micro/v3/store"
 | 
						"go.unistack.org/micro/v4/options"
 | 
				
			||||||
	"go.unistack.org/micro/v3/tracer"
 | 
						"go.unistack.org/micro/v4/store"
 | 
				
			||||||
 | 
						"go.unistack.org/micro/v4/tracer"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Option func
 | 
					 | 
				
			||||||
type Option func(*Options)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Options server struct
 | 
					// Options server struct
 | 
				
			||||||
type Options struct {
 | 
					type Options struct {
 | 
				
			||||||
	// Context holds the external options and can be used for flow shutdown
 | 
						// Context holds the external options and can be used for flow shutdown
 | 
				
			||||||
@@ -31,7 +29,7 @@ type Options struct {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewOptions returns new options struct with default or passed values
 | 
					// NewOptions returns new options struct with default or passed values
 | 
				
			||||||
func NewOptions(opts ...Option) Options {
 | 
					func NewOptions(opts ...options.Option) Options {
 | 
				
			||||||
	options := Options{
 | 
						options := Options{
 | 
				
			||||||
		Context: context.Background(),
 | 
							Context: context.Background(),
 | 
				
			||||||
		Logger:  logger.DefaultLogger,
 | 
							Logger:  logger.DefaultLogger,
 | 
				
			||||||
@@ -47,66 +45,12 @@ func NewOptions(opts ...Option) Options {
 | 
				
			|||||||
	return options
 | 
						return options
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Logger sets the logger option
 | 
					 | 
				
			||||||
func Logger(l logger.Logger) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Logger = l
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Meter sets the meter option
 | 
					 | 
				
			||||||
func Meter(m meter.Meter) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Meter = m
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Client to use for sync/async communication
 | 
					 | 
				
			||||||
func Client(c client.Client) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Client = c
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Context specifies a context for the service.
 | 
					 | 
				
			||||||
// Can be used to signal shutdown of the flow
 | 
					 | 
				
			||||||
// or can be used for extra option values.
 | 
					 | 
				
			||||||
func Context(ctx context.Context) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Context = ctx
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Tracer mechanism for distributed tracking
 | 
					 | 
				
			||||||
func Tracer(t tracer.Tracer) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Tracer = t
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Store used for intermediate results
 | 
					 | 
				
			||||||
func Store(s store.Store) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Store = s
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// WorkflowOption func signature
 | 
					 | 
				
			||||||
type WorkflowOption func(*WorkflowOptions)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// WorkflowOptions holds workflow options
 | 
					// WorkflowOptions holds workflow options
 | 
				
			||||||
type WorkflowOptions struct {
 | 
					type WorkflowOptions struct {
 | 
				
			||||||
	Context context.Context
 | 
						Context context.Context
 | 
				
			||||||
	ID      string
 | 
						ID      string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// WorkflowID set workflow id
 | 
					 | 
				
			||||||
func WorkflowID(id string) WorkflowOption {
 | 
					 | 
				
			||||||
	return func(o *WorkflowOptions) {
 | 
					 | 
				
			||||||
		o.ID = id
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ExecuteOptions holds execute options
 | 
					// ExecuteOptions holds execute options
 | 
				
			||||||
type ExecuteOptions struct {
 | 
					type ExecuteOptions struct {
 | 
				
			||||||
	// Client holds the client.Client
 | 
						// Client holds the client.Client
 | 
				
			||||||
@@ -129,67 +73,22 @@ type ExecuteOptions struct {
 | 
				
			|||||||
	Async bool
 | 
						Async bool
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ExecuteOption func signature
 | 
					// Reverse says that dag must be run in reverse order
 | 
				
			||||||
type ExecuteOption func(*ExecuteOptions)
 | 
					func Reverse(b bool) options.Option {
 | 
				
			||||||
 | 
						return func(src interface{}) error {
 | 
				
			||||||
// ExecuteClient pass client.Client to ExecuteOption
 | 
							return options.Set(src, b, ".Reverse")
 | 
				
			||||||
func ExecuteClient(c client.Client) ExecuteOption {
 | 
					 | 
				
			||||||
	return func(o *ExecuteOptions) {
 | 
					 | 
				
			||||||
		o.Client = c
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ExecuteTracer pass tracer.Tracer to ExecuteOption
 | 
					// Async says that caller does not wait for execution complete
 | 
				
			||||||
func ExecuteTracer(t tracer.Tracer) ExecuteOption {
 | 
					func Async(b bool) options.Option {
 | 
				
			||||||
	return func(o *ExecuteOptions) {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		o.Tracer = t
 | 
							return options.Set(src, b, ".Async")
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ExecuteLogger pass logger.Logger to ExecuteOption
 | 
					 | 
				
			||||||
func ExecuteLogger(l logger.Logger) ExecuteOption {
 | 
					 | 
				
			||||||
	return func(o *ExecuteOptions) {
 | 
					 | 
				
			||||||
		o.Logger = l
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ExecuteMeter pass meter.Meter to ExecuteOption
 | 
					 | 
				
			||||||
func ExecuteMeter(m meter.Meter) ExecuteOption {
 | 
					 | 
				
			||||||
	return func(o *ExecuteOptions) {
 | 
					 | 
				
			||||||
		o.Meter = m
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ExecuteContext pass context.Context ot ExecuteOption
 | 
					 | 
				
			||||||
func ExecuteContext(ctx context.Context) ExecuteOption {
 | 
					 | 
				
			||||||
	return func(o *ExecuteOptions) {
 | 
					 | 
				
			||||||
		o.Context = ctx
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ExecuteReverse says that dag must be run in reverse order
 | 
					 | 
				
			||||||
func ExecuteReverse(b bool) ExecuteOption {
 | 
					 | 
				
			||||||
	return func(o *ExecuteOptions) {
 | 
					 | 
				
			||||||
		o.Reverse = b
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ExecuteTimeout pass timeout time.Duration for execution
 | 
					 | 
				
			||||||
func ExecuteTimeout(td time.Duration) ExecuteOption {
 | 
					 | 
				
			||||||
	return func(o *ExecuteOptions) {
 | 
					 | 
				
			||||||
		o.Timeout = td
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ExecuteAsync says that caller does not wait for execution complete
 | 
					 | 
				
			||||||
func ExecuteAsync(b bool) ExecuteOption {
 | 
					 | 
				
			||||||
	return func(o *ExecuteOptions) {
 | 
					 | 
				
			||||||
		o.Async = b
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewExecuteOptions create new ExecuteOptions struct
 | 
					// NewExecuteOptions create new ExecuteOptions struct
 | 
				
			||||||
func NewExecuteOptions(opts ...ExecuteOption) ExecuteOptions {
 | 
					func NewExecuteOptions(opts ...options.Option) ExecuteOptions {
 | 
				
			||||||
	options := ExecuteOptions{
 | 
						options := ExecuteOptions{
 | 
				
			||||||
		Client:  client.DefaultClient,
 | 
							Client:  client.DefaultClient,
 | 
				
			||||||
		Logger:  logger.DefaultLogger,
 | 
							Logger:  logger.DefaultLogger,
 | 
				
			||||||
@@ -211,11 +110,8 @@ type StepOptions struct {
 | 
				
			|||||||
	Requires []string
 | 
						Requires []string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// StepOption func signature
 | 
					 | 
				
			||||||
type StepOption func(*StepOptions)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// NewStepOptions create new StepOptions struct
 | 
					// NewStepOptions create new StepOptions struct
 | 
				
			||||||
func NewStepOptions(opts ...StepOption) StepOptions {
 | 
					func NewStepOptions(opts ...options.Option) StepOptions {
 | 
				
			||||||
	options := StepOptions{
 | 
						options := StepOptions{
 | 
				
			||||||
		Context: context.Background(),
 | 
							Context: context.Background(),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -225,23 +121,23 @@ func NewStepOptions(opts ...StepOption) StepOptions {
 | 
				
			|||||||
	return options
 | 
						return options
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// StepID sets the step id for dag
 | 
					// Requires specifies required steps
 | 
				
			||||||
func StepID(id string) StepOption {
 | 
					func Requires(steps ...string) options.Option {
 | 
				
			||||||
	return func(o *StepOptions) {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		o.ID = id
 | 
							return options.Set(src, steps, ".Requires")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// StepRequires specifies required steps
 | 
					// Fallback set the step to run on error
 | 
				
			||||||
func StepRequires(steps ...string) StepOption {
 | 
					func Fallback(step string) options.Option {
 | 
				
			||||||
	return func(o *StepOptions) {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		o.Requires = steps
 | 
							return options.Set(src, step, ".Fallback")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// StepFallback set the step to run on error
 | 
					// ID sets the step ID
 | 
				
			||||||
func StepFallback(step string) StepOption {
 | 
					func StepID(id string) options.Option {
 | 
				
			||||||
	return func(o *StepOptions) {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		o.Fallback = step
 | 
							return options.Set(src, id, ".ID")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
package fsm // import "go.unistack.org/micro/v3/fsm"
 | 
					package fsm // import "go.unistack.org/micro/v4/fsm"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,7 +5,7 @@ import (
 | 
				
			|||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro/v3/logger"
 | 
						"go.unistack.org/micro/v4/logger"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestFSMStart(t *testing.T) {
 | 
					func TestFSMStart(t *testing.T) {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										19
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								go.mod
									
									
									
									
									
								
							@@ -1,9 +1,20 @@
 | 
				
			|||||||
module go.unistack.org/micro/v3
 | 
					module go.unistack.org/micro/v4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
go 1.19
 | 
					go 1.20
 | 
				
			||||||
 | 
					
 | 
				
			||||||
require (
 | 
					require (
 | 
				
			||||||
	github.com/imdario/mergo v0.3.14
 | 
						github.com/DATA-DOG/go-sqlmock v1.5.0
 | 
				
			||||||
 | 
						github.com/google/uuid v1.3.0
 | 
				
			||||||
 | 
						github.com/imdario/mergo v0.3.15
 | 
				
			||||||
	github.com/patrickmn/go-cache v2.1.0+incompatible
 | 
						github.com/patrickmn/go-cache v2.1.0+incompatible
 | 
				
			||||||
	github.com/silas/dag v0.0.0-20211117232152-9d50aa809f35
 | 
						github.com/silas/dag v0.0.0-20220518035006-a7e85ada93c5
 | 
				
			||||||
 | 
						golang.org/x/sync v0.1.0
 | 
				
			||||||
 | 
						golang.org/x/sys v0.7.0
 | 
				
			||||||
 | 
						google.golang.org/grpc v1.54.0
 | 
				
			||||||
 | 
						google.golang.org/protobuf v1.30.0
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					require (
 | 
				
			||||||
 | 
						github.com/golang/protobuf v1.5.3 // indirect
 | 
				
			||||||
 | 
						google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										32
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										32
									
								
								go.sum
									
									
									
									
									
								
							@@ -1,9 +1,33 @@
 | 
				
			|||||||
github.com/imdario/mergo v0.3.14 h1:fOqeC1+nCuuk6PKQdg9YmosXX7Y7mHX6R/0ZldI9iHo=
 | 
					github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60=
 | 
				
			||||||
github.com/imdario/mergo v0.3.14/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
 | 
					github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
 | 
				
			||||||
 | 
					github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
 | 
				
			||||||
 | 
					github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
 | 
				
			||||||
 | 
					github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
 | 
				
			||||||
 | 
					github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 | 
				
			||||||
 | 
					github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
 | 
				
			||||||
 | 
					github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
 | 
				
			||||||
 | 
					github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 | 
				
			||||||
 | 
					github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM=
 | 
				
			||||||
 | 
					github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
 | 
				
			||||||
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
 | 
					github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
 | 
				
			||||||
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
 | 
					github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
 | 
				
			||||||
github.com/silas/dag v0.0.0-20211117232152-9d50aa809f35 h1:4mohWoM/UGg1BvFFiqSPRl5uwJY3rVV0HQX0ETqauqQ=
 | 
					github.com/silas/dag v0.0.0-20220518035006-a7e85ada93c5 h1:G/FZtUu7a6NTWl3KUHMV9jkLAh/Rvtf03NWMHaEDl+E=
 | 
				
			||||||
github.com/silas/dag v0.0.0-20211117232152-9d50aa809f35/go.mod h1:7RTUFBdIRC9nZ7/3RyRNH1bdqIShrDejd1YbLwgPS+I=
 | 
					github.com/silas/dag v0.0.0-20220518035006-a7e85ada93c5/go.mod h1:7RTUFBdIRC9nZ7/3RyRNH1bdqIShrDejd1YbLwgPS+I=
 | 
				
			||||||
 | 
					golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
 | 
				
			||||||
 | 
					golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
 | 
				
			||||||
 | 
					golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
				
			||||||
 | 
					golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
 | 
				
			||||||
 | 
					golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
				
			||||||
 | 
					golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
 | 
				
			||||||
 | 
					golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
				
			||||||
 | 
					google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A=
 | 
				
			||||||
 | 
					google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU=
 | 
				
			||||||
 | 
					google.golang.org/grpc v1.54.0 h1:EhTqbhiYeixwWQtAEZAxmV9MGqcjEU2mFx52xCzNyag=
 | 
				
			||||||
 | 
					google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g=
 | 
				
			||||||
 | 
					google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
 | 
				
			||||||
 | 
					google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
 | 
				
			||||||
 | 
					google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
 | 
				
			||||||
 | 
					google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
 | 
				
			||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
					gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
				
			||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 | 
					gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 | 
				
			||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 | 
					gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,13 +20,3 @@ func NewContext(ctx context.Context, l Logger) context.Context {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	return context.WithValue(ctx, loggerKey{}, l)
 | 
						return context.WithValue(ctx, loggerKey{}, l)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
// SetOption returns a function to setup a context with given value
 | 
					 | 
				
			||||||
func SetOption(k, v interface{}) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		if o.Context == nil {
 | 
					 | 
				
			||||||
			o.Context = context.Background()
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		o.Context = context.WithValue(o.Context, k, v)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -40,14 +40,3 @@ func TestNewContext(t *testing.T) {
 | 
				
			|||||||
		t.Fatal("NewContext not works")
 | 
							t.Fatal("NewContext not works")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestSetOption(t *testing.T) {
 | 
					 | 
				
			||||||
	type key struct{}
 | 
					 | 
				
			||||||
	o := SetOption(key{}, "test")
 | 
					 | 
				
			||||||
	opts := &Options{}
 | 
					 | 
				
			||||||
	o(opts)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if v, ok := opts.Context.Value(key{}).(string); !ok || v == "" {
 | 
					 | 
				
			||||||
		t.Fatal("SetOption not works")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,6 +9,8 @@ import (
 | 
				
			|||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"go.unistack.org/micro/v4/options"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type defaultLogger struct {
 | 
					type defaultLogger struct {
 | 
				
			||||||
@@ -18,7 +20,7 @@ type defaultLogger struct {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Init(opts...) should only overwrite provided options
 | 
					// Init(opts...) should only overwrite provided options
 | 
				
			||||||
func (l *defaultLogger) Init(opts ...Option) error {
 | 
					func (l *defaultLogger) Init(opts ...options.Option) error {
 | 
				
			||||||
	l.Lock()
 | 
						l.Lock()
 | 
				
			||||||
	for _, o := range opts {
 | 
						for _, o := range opts {
 | 
				
			||||||
		o(&l.opts)
 | 
							o(&l.opts)
 | 
				
			||||||
@@ -33,7 +35,7 @@ func (l *defaultLogger) String() string {
 | 
				
			|||||||
	return "micro"
 | 
						return "micro"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (l *defaultLogger) Clone(opts ...Option) Logger {
 | 
					func (l *defaultLogger) Clone(opts ...options.Option) Logger {
 | 
				
			||||||
	newopts := NewOptions(opts...)
 | 
						newopts := NewOptions(opts...)
 | 
				
			||||||
	oldopts := l.opts
 | 
						oldopts := l.opts
 | 
				
			||||||
	for _, o := range opts {
 | 
						for _, o := range opts {
 | 
				
			||||||
@@ -221,7 +223,7 @@ func (l *defaultLogger) Options() Options {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewLogger builds a new logger based on options
 | 
					// NewLogger builds a new logger based on options
 | 
				
			||||||
func NewLogger(opts ...Option) Logger {
 | 
					func NewLogger(opts ...options.Option) Logger {
 | 
				
			||||||
	l := &defaultLogger{
 | 
						l := &defaultLogger{
 | 
				
			||||||
		opts: NewOptions(opts...),
 | 
							opts: NewOptions(opts...),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,9 +1,11 @@
 | 
				
			|||||||
// Package logger provides a log interface
 | 
					// Package logger provides a log interface
 | 
				
			||||||
package logger // import "go.unistack.org/micro/v3/logger"
 | 
					package logger // import "go.unistack.org/micro/v4/logger"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"go.unistack.org/micro/v4/options"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
@@ -18,9 +20,9 @@ var (
 | 
				
			|||||||
// Logger is a generic logging interface
 | 
					// Logger is a generic logging interface
 | 
				
			||||||
type Logger interface {
 | 
					type Logger interface {
 | 
				
			||||||
	// Init initialises options
 | 
						// Init initialises options
 | 
				
			||||||
	Init(opts ...Option) error
 | 
						Init(opts ...options.Option) error
 | 
				
			||||||
	// Clone create logger copy with new options
 | 
						// Clone create logger copy with new options
 | 
				
			||||||
	Clone(opts ...Option) Logger
 | 
						Clone(opts ...options.Option) Logger
 | 
				
			||||||
	// V compare provided verbosity level with current log level
 | 
						// V compare provided verbosity level with current log level
 | 
				
			||||||
	V(level Level) bool
 | 
						V(level Level) bool
 | 
				
			||||||
	// Level sets the log level for logger
 | 
						// Level sets the log level for logger
 | 
				
			||||||
@@ -130,7 +132,7 @@ func V(level Level) bool {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Init initialize logger
 | 
					// Init initialize logger
 | 
				
			||||||
func Init(opts ...Option) error {
 | 
					func Init(opts ...options.Option) error {
 | 
				
			||||||
	return DefaultLogger.Init(opts...)
 | 
						return DefaultLogger.Init(opts...)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,10 +4,9 @@ import (
 | 
				
			|||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Option func
 | 
						"go.unistack.org/micro/v4/options"
 | 
				
			||||||
type Option func(*Options)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Options holds logger options
 | 
					// Options holds logger options
 | 
				
			||||||
type Options struct {
 | 
					type Options struct {
 | 
				
			||||||
@@ -26,7 +25,7 @@ type Options struct {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewOptions creates new options struct
 | 
					// NewOptions creates new options struct
 | 
				
			||||||
func NewOptions(opts ...Option) Options {
 | 
					func NewOptions(opts ...options.Option) Options {
 | 
				
			||||||
	options := Options{
 | 
						options := Options{
 | 
				
			||||||
		Level:           DefaultLevel,
 | 
							Level:           DefaultLevel,
 | 
				
			||||||
		Fields:          make([]interface{}, 0, 6),
 | 
							Fields:          make([]interface{}, 0, 6),
 | 
				
			||||||
@@ -41,43 +40,29 @@ func NewOptions(opts ...Option) Options {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// WithFields set default fields for the logger
 | 
					// WithFields set default fields for the logger
 | 
				
			||||||
func WithFields(fields ...interface{}) Option {
 | 
					func WithFields(fields ...interface{}) options.Option {
 | 
				
			||||||
	return func(o *Options) {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		o.Fields = fields
 | 
							return options.Set(src, fields, ".Fields")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// WithLevel set default level for the logger
 | 
					// WithLevel set default level for the logger
 | 
				
			||||||
func WithLevel(level Level) Option {
 | 
					func WithLevel(lvl Level) options.Option {
 | 
				
			||||||
	return func(o *Options) {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		o.Level = level
 | 
							return options.Set(src, lvl, ".Level")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// WithOutput set default output writer for the logger
 | 
					// WithOutput set default output writer for the logger
 | 
				
			||||||
func WithOutput(out io.Writer) Option {
 | 
					func WithOutput(out io.Writer) options.Option {
 | 
				
			||||||
	return func(o *Options) {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		o.Out = out
 | 
							return options.Set(src, out, ".Out")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// WithCallerSkipCount set frame count to skip
 | 
					// WithCallerSkipCount set frame count to skip
 | 
				
			||||||
func WithCallerSkipCount(c int) Option {
 | 
					func WithCallerSkipCount(c int) options.Option {
 | 
				
			||||||
	return func(o *Options) {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		o.CallerSkipCount = c
 | 
							return options.Set(src, c, ".CallerSkipCount")
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// WithContext set context
 | 
					 | 
				
			||||||
func WithContext(ctx context.Context) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Context = ctx
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// WithName sets the name
 | 
					 | 
				
			||||||
func WithName(n string) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Name = n
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,7 @@ import (
 | 
				
			|||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro/v3/codec"
 | 
						"go.unistack.org/micro/v4/codec"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const sf = "0-+# "
 | 
					const sf = "0-+# "
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,7 +5,7 @@ import (
 | 
				
			|||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro/v3/codec"
 | 
						"go.unistack.org/micro/v4/codec"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestUnwrap(t *testing.T) {
 | 
					func TestUnwrap(t *testing.T) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,9 +5,9 @@ import (
 | 
				
			|||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro/v3/client"
 | 
						"go.unistack.org/micro/v4/client"
 | 
				
			||||||
	"go.unistack.org/micro/v3/logger"
 | 
						"go.unistack.org/micro/v4/logger"
 | 
				
			||||||
	"go.unistack.org/micro/v3/server"
 | 
						"go.unistack.org/micro/v4/server"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
@@ -29,15 +29,6 @@ var (
 | 
				
			|||||||
		return labels
 | 
							return labels
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// DefaultClientPublishObserver called by wrapper in client Publish
 | 
					 | 
				
			||||||
	DefaultClientPublishObserver = func(ctx context.Context, msg client.Message, opts []client.PublishOption, err error) []string {
 | 
					 | 
				
			||||||
		labels := []string{"endpoint", msg.Topic()}
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			labels = append(labels, "error", err.Error())
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return labels
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// DefaultServerHandlerObserver called by wrapper in server Handler
 | 
						// DefaultServerHandlerObserver called by wrapper in server Handler
 | 
				
			||||||
	DefaultServerHandlerObserver = func(ctx context.Context, req server.Request, rsp interface{}, err error) []string {
 | 
						DefaultServerHandlerObserver = func(ctx context.Context, req server.Request, rsp interface{}, err error) []string {
 | 
				
			||||||
		labels := []string{"service", req.Service(), "endpoint", req.Endpoint()}
 | 
							labels := []string{"service", req.Service(), "endpoint", req.Endpoint()}
 | 
				
			||||||
@@ -47,15 +38,6 @@ var (
 | 
				
			|||||||
		return labels
 | 
							return labels
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// DefaultServerSubscriberObserver called by wrapper in server Subscriber
 | 
					 | 
				
			||||||
	DefaultServerSubscriberObserver = func(ctx context.Context, msg server.Message, err error) []string {
 | 
					 | 
				
			||||||
		labels := []string{"endpoint", msg.Topic()}
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			labels = append(labels, "error", err.Error())
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return labels
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// DefaultClientCallFuncObserver called by wrapper in client CallFunc
 | 
						// DefaultClientCallFuncObserver called by wrapper in client CallFunc
 | 
				
			||||||
	DefaultClientCallFuncObserver = func(ctx context.Context, addr string, req client.Request, rsp interface{}, opts client.CallOptions, err error) []string {
 | 
						DefaultClientCallFuncObserver = func(ctx context.Context, addr string, req client.Request, rsp interface{}, opts client.CallOptions, err error) []string {
 | 
				
			||||||
		labels := []string{"service", req.Service(), "endpoint", req.Endpoint()}
 | 
							labels := []string{"service", req.Service(), "endpoint", req.Endpoint()}
 | 
				
			||||||
@@ -71,10 +53,9 @@ var (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
type lWrapper struct {
 | 
					type lWrapper struct {
 | 
				
			||||||
	client.Client
 | 
						client.Client
 | 
				
			||||||
	serverHandler    server.HandlerFunc
 | 
						serverHandler  server.HandlerFunc
 | 
				
			||||||
	serverSubscriber server.SubscriberFunc
 | 
						clientCallFunc client.CallFunc
 | 
				
			||||||
	clientCallFunc   client.CallFunc
 | 
						opts           Options
 | 
				
			||||||
	opts             Options
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type (
 | 
					type (
 | 
				
			||||||
@@ -82,14 +63,10 @@ type (
 | 
				
			|||||||
	ClientCallObserver func(context.Context, client.Request, interface{}, []client.CallOption, error) []string
 | 
						ClientCallObserver func(context.Context, client.Request, interface{}, []client.CallOption, error) []string
 | 
				
			||||||
	// ClientStreamObserver func signature
 | 
						// ClientStreamObserver func signature
 | 
				
			||||||
	ClientStreamObserver func(context.Context, client.Request, []client.CallOption, client.Stream, error) []string
 | 
						ClientStreamObserver func(context.Context, client.Request, []client.CallOption, client.Stream, error) []string
 | 
				
			||||||
	// ClientPublishObserver func signature
 | 
					 | 
				
			||||||
	ClientPublishObserver func(context.Context, client.Message, []client.PublishOption, error) []string
 | 
					 | 
				
			||||||
	// ClientCallFuncObserver func signature
 | 
						// ClientCallFuncObserver func signature
 | 
				
			||||||
	ClientCallFuncObserver func(context.Context, string, client.Request, interface{}, client.CallOptions, error) []string
 | 
						ClientCallFuncObserver func(context.Context, string, client.Request, interface{}, client.CallOptions, error) []string
 | 
				
			||||||
	// ServerHandlerObserver func signature
 | 
						// ServerHandlerObserver func signature
 | 
				
			||||||
	ServerHandlerObserver func(context.Context, server.Request, interface{}, error) []string
 | 
						ServerHandlerObserver func(context.Context, server.Request, interface{}, error) []string
 | 
				
			||||||
	// ServerSubscriberObserver func signature
 | 
					 | 
				
			||||||
	ServerSubscriberObserver func(context.Context, server.Message, error) []string
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Options struct for wrapper
 | 
					// Options struct for wrapper
 | 
				
			||||||
@@ -98,14 +75,10 @@ type Options struct {
 | 
				
			|||||||
	Logger logger.Logger
 | 
						Logger logger.Logger
 | 
				
			||||||
	// ServerHandlerObservers funcs
 | 
						// ServerHandlerObservers funcs
 | 
				
			||||||
	ServerHandlerObservers []ServerHandlerObserver
 | 
						ServerHandlerObservers []ServerHandlerObserver
 | 
				
			||||||
	// ServerSubscriberObservers funcs
 | 
					 | 
				
			||||||
	ServerSubscriberObservers []ServerSubscriberObserver
 | 
					 | 
				
			||||||
	// ClientCallObservers funcs
 | 
						// ClientCallObservers funcs
 | 
				
			||||||
	ClientCallObservers []ClientCallObserver
 | 
						ClientCallObservers []ClientCallObserver
 | 
				
			||||||
	// ClientStreamObservers funcs
 | 
						// ClientStreamObservers funcs
 | 
				
			||||||
	ClientStreamObservers []ClientStreamObserver
 | 
						ClientStreamObservers []ClientStreamObserver
 | 
				
			||||||
	// ClientPublishObservers funcs
 | 
					 | 
				
			||||||
	ClientPublishObservers []ClientPublishObserver
 | 
					 | 
				
			||||||
	// ClientCallFuncObservers funcs
 | 
						// ClientCallFuncObservers funcs
 | 
				
			||||||
	ClientCallFuncObservers []ClientCallFuncObserver
 | 
						ClientCallFuncObservers []ClientCallFuncObserver
 | 
				
			||||||
	// SkipEndpoints
 | 
						// SkipEndpoints
 | 
				
			||||||
@@ -122,15 +95,13 @@ type Option func(*Options)
 | 
				
			|||||||
// NewOptions creates Options from Option slice
 | 
					// NewOptions creates Options from Option slice
 | 
				
			||||||
func NewOptions(opts ...Option) Options {
 | 
					func NewOptions(opts ...Option) Options {
 | 
				
			||||||
	options := Options{
 | 
						options := Options{
 | 
				
			||||||
		Logger:                    logger.DefaultLogger,
 | 
							Logger:                  logger.DefaultLogger,
 | 
				
			||||||
		Level:                     logger.TraceLevel,
 | 
							Level:                   logger.TraceLevel,
 | 
				
			||||||
		ClientCallObservers:       []ClientCallObserver{DefaultClientCallObserver},
 | 
							ClientCallObservers:     []ClientCallObserver{DefaultClientCallObserver},
 | 
				
			||||||
		ClientStreamObservers:     []ClientStreamObserver{DefaultClientStreamObserver},
 | 
							ClientStreamObservers:   []ClientStreamObserver{DefaultClientStreamObserver},
 | 
				
			||||||
		ClientPublishObservers:    []ClientPublishObserver{DefaultClientPublishObserver},
 | 
							ClientCallFuncObservers: []ClientCallFuncObserver{DefaultClientCallFuncObserver},
 | 
				
			||||||
		ClientCallFuncObservers:   []ClientCallFuncObserver{DefaultClientCallFuncObserver},
 | 
							ServerHandlerObservers:  []ServerHandlerObserver{DefaultServerHandlerObserver},
 | 
				
			||||||
		ServerHandlerObservers:    []ServerHandlerObserver{DefaultServerHandlerObserver},
 | 
							SkipEndpoints:           DefaultSkipEndpoints,
 | 
				
			||||||
		ServerSubscriberObservers: []ServerSubscriberObserver{DefaultServerSubscriberObserver},
 | 
					 | 
				
			||||||
		SkipEndpoints:             DefaultSkipEndpoints,
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, o := range opts {
 | 
						for _, o := range opts {
 | 
				
			||||||
@@ -175,13 +146,6 @@ func WithClientStreamObservers(ob ...ClientStreamObserver) Option {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// WithClientPublishObservers funcs
 | 
					 | 
				
			||||||
func WithClientPublishObservers(ob ...ClientPublishObserver) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.ClientPublishObservers = ob
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// WithClientCallFuncObservers funcs
 | 
					// WithClientCallFuncObservers funcs
 | 
				
			||||||
func WithClientCallFuncObservers(ob ...ClientCallFuncObserver) Option {
 | 
					func WithClientCallFuncObservers(ob ...ClientCallFuncObserver) Option {
 | 
				
			||||||
	return func(o *Options) {
 | 
						return func(o *Options) {
 | 
				
			||||||
@@ -196,13 +160,6 @@ func WithServerHandlerObservers(ob ...ServerHandlerObserver) Option {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// WithServerSubscriberObservers funcs
 | 
					 | 
				
			||||||
func WithServerSubscriberObservers(ob ...ServerSubscriberObserver) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.ServerSubscriberObservers = ob
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// SkipEndpoins
 | 
					// SkipEndpoins
 | 
				
			||||||
func SkipEndpoints(eps ...string) Option {
 | 
					func SkipEndpoints(eps ...string) Option {
 | 
				
			||||||
	return func(o *Options) {
 | 
						return func(o *Options) {
 | 
				
			||||||
@@ -256,29 +213,6 @@ func (l *lWrapper) Stream(ctx context.Context, req client.Request, opts ...clien
 | 
				
			|||||||
	return stream, err
 | 
						return stream, err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (l *lWrapper) Publish(ctx context.Context, msg client.Message, opts ...client.PublishOption) error {
 | 
					 | 
				
			||||||
	err := l.Client.Publish(ctx, msg, opts...)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	endpoint := msg.Topic()
 | 
					 | 
				
			||||||
	for _, ep := range l.opts.SkipEndpoints {
 | 
					 | 
				
			||||||
		if ep == endpoint {
 | 
					 | 
				
			||||||
			return err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if !l.opts.Enabled {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	var labels []string
 | 
					 | 
				
			||||||
	for _, o := range l.opts.ClientPublishObservers {
 | 
					 | 
				
			||||||
		labels = append(labels, o(ctx, msg, opts, err)...)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	l.opts.Logger.Fields(labels).Log(ctx, l.opts.Level)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return err
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (l *lWrapper) ServerHandler(ctx context.Context, req server.Request, rsp interface{}) error {
 | 
					func (l *lWrapper) ServerHandler(ctx context.Context, req server.Request, rsp interface{}) error {
 | 
				
			||||||
	err := l.serverHandler(ctx, req, rsp)
 | 
						err := l.serverHandler(ctx, req, rsp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -302,29 +236,6 @@ func (l *lWrapper) ServerHandler(ctx context.Context, req server.Request, rsp in
 | 
				
			|||||||
	return err
 | 
						return err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (l *lWrapper) ServerSubscriber(ctx context.Context, msg server.Message) error {
 | 
					 | 
				
			||||||
	err := l.serverSubscriber(ctx, msg)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	endpoint := msg.Topic()
 | 
					 | 
				
			||||||
	for _, ep := range l.opts.SkipEndpoints {
 | 
					 | 
				
			||||||
		if ep == endpoint {
 | 
					 | 
				
			||||||
			return err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if !l.opts.Enabled {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	var labels []string
 | 
					 | 
				
			||||||
	for _, o := range l.opts.ServerSubscriberObservers {
 | 
					 | 
				
			||||||
		labels = append(labels, o(ctx, msg, err)...)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	l.opts.Logger.Fields(labels).Log(ctx, l.opts.Level)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return err
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// NewClientWrapper accepts an open options and returns a Client Wrapper
 | 
					// NewClientWrapper accepts an open options and returns a Client Wrapper
 | 
				
			||||||
func NewClientWrapper(opts ...Option) client.Wrapper {
 | 
					func NewClientWrapper(opts ...Option) client.Wrapper {
 | 
				
			||||||
	return func(c client.Client) client.Client {
 | 
						return func(c client.Client) client.Client {
 | 
				
			||||||
@@ -384,16 +295,3 @@ func NewServerHandlerWrapper(opts ...Option) server.HandlerWrapper {
 | 
				
			|||||||
		return l.ServerHandler
 | 
							return l.ServerHandler
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
// NewServerSubscriberWrapper accepts an options and returns a Subscriber Wrapper
 | 
					 | 
				
			||||||
func NewServerSubscriberWrapper(opts ...Option) server.SubscriberWrapper {
 | 
					 | 
				
			||||||
	return func(h server.SubscriberFunc) server.SubscriberFunc {
 | 
					 | 
				
			||||||
		options := NewOptions()
 | 
					 | 
				
			||||||
		for _, o := range opts {
 | 
					 | 
				
			||||||
			o(&options)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		l := &lWrapper{opts: options, serverSubscriber: h}
 | 
					 | 
				
			||||||
		return l.ServerSubscriber
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -39,8 +39,6 @@ func FromOutgoingContext(ctx context.Context) (Metadata, bool) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// FromContext returns metadata from the given context
 | 
					// FromContext returns metadata from the given context
 | 
				
			||||||
// returned metadata shoud not be modified or race condition happens
 | 
					// returned metadata shoud not be modified or race condition happens
 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Deprecated: use FromIncomingContext or FromOutgoingContext
 | 
					 | 
				
			||||||
func FromContext(ctx context.Context) (Metadata, bool) {
 | 
					func FromContext(ctx context.Context) (Metadata, bool) {
 | 
				
			||||||
	if ctx == nil {
 | 
						if ctx == nil {
 | 
				
			||||||
		return nil, false
 | 
							return nil, false
 | 
				
			||||||
@@ -53,8 +51,6 @@ func FromContext(ctx context.Context) (Metadata, bool) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewContext creates a new context with the given metadata
 | 
					// NewContext creates a new context with the given metadata
 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Deprecated: use NewIncomingContext or NewOutgoingContext
 | 
					 | 
				
			||||||
func NewContext(ctx context.Context, md Metadata) context.Context {
 | 
					func NewContext(ctx context.Context, md Metadata) context.Context {
 | 
				
			||||||
	if ctx == nil {
 | 
						if ctx == nil {
 | 
				
			||||||
		ctx = context.Background()
 | 
							ctx = context.Background()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,5 @@
 | 
				
			|||||||
// Package metadata is a way of defining message headers
 | 
					// Package metadata is a way of defining message headers
 | 
				
			||||||
package metadata // import "go.unistack.org/micro/v3/metadata"
 | 
					package metadata // import "go.unistack.org/micro/v4/metadata"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"net/textproto"
 | 
						"net/textproto"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,13 +22,3 @@ func NewContext(ctx context.Context, c Meter) context.Context {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	return context.WithValue(ctx, meterKey{}, c)
 | 
						return context.WithValue(ctx, meterKey{}, c)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
// SetOption returns a function to setup a context with given value
 | 
					 | 
				
			||||||
func SetOption(k, v interface{}) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		if o.Context == nil {
 | 
					 | 
				
			||||||
			o.Context = context.Background()
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		o.Context = context.WithValue(o.Context, k, v)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -40,14 +40,3 @@ func TestNewContext(t *testing.T) {
 | 
				
			|||||||
		t.Fatal("NewContext not works")
 | 
							t.Fatal("NewContext not works")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestSetOption(t *testing.T) {
 | 
					 | 
				
			||||||
	type key struct{}
 | 
					 | 
				
			||||||
	o := SetOption(key{}, "test")
 | 
					 | 
				
			||||||
	opts := &Options{}
 | 
					 | 
				
			||||||
	o(opts)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if v, ok := opts.Context.Value(key{}).(string); !ok || v == "" {
 | 
					 | 
				
			||||||
		t.Fatal("SetOption not works")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,5 @@
 | 
				
			|||||||
// Package meter is for instrumentation
 | 
					// Package meter is for instrumentation
 | 
				
			||||||
package meter // import "go.unistack.org/micro/v3/meter"
 | 
					package meter // import "go.unistack.org/micro/v4/meter"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
@@ -7,6 +7,8 @@ import (
 | 
				
			|||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"go.unistack.org/micro/v4/options"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
@@ -31,9 +33,9 @@ type Meter interface {
 | 
				
			|||||||
	// Name returns meter name
 | 
						// Name returns meter name
 | 
				
			||||||
	Name() string
 | 
						Name() string
 | 
				
			||||||
	// Init initialize meter
 | 
						// Init initialize meter
 | 
				
			||||||
	Init(opts ...Option) error
 | 
						Init(opts ...options.Option) error
 | 
				
			||||||
	// Clone create meter copy with new options
 | 
						// Clone create meter copy with new options
 | 
				
			||||||
	Clone(opts ...Option) Meter
 | 
						Clone(opts ...options.Option) Meter
 | 
				
			||||||
	// Counter get or create counter
 | 
						// Counter get or create counter
 | 
				
			||||||
	Counter(name string, labels ...string) Counter
 | 
						Counter(name string, labels ...string) Counter
 | 
				
			||||||
	// FloatCounter get or create float counter
 | 
						// FloatCounter get or create float counter
 | 
				
			||||||
@@ -41,7 +43,7 @@ type Meter interface {
 | 
				
			|||||||
	// Gauge get or create gauge
 | 
						// Gauge get or create gauge
 | 
				
			||||||
	Gauge(name string, fn func() float64, labels ...string) Gauge
 | 
						Gauge(name string, fn func() float64, labels ...string) Gauge
 | 
				
			||||||
	// Set create new meter metrics set
 | 
						// Set create new meter metrics set
 | 
				
			||||||
	Set(opts ...Option) Meter
 | 
						Set(opts ...options.Option) Meter
 | 
				
			||||||
	// Histogram get or create histogram
 | 
						// Histogram get or create histogram
 | 
				
			||||||
	Histogram(name string, labels ...string) Histogram
 | 
						Histogram(name string, labels ...string) Histogram
 | 
				
			||||||
	// Summary get or create summary
 | 
						// Summary get or create summary
 | 
				
			||||||
@@ -49,7 +51,7 @@ type Meter interface {
 | 
				
			|||||||
	// SummaryExt get or create summary with spcified quantiles and window time
 | 
						// SummaryExt get or create summary with spcified quantiles and window time
 | 
				
			||||||
	SummaryExt(name string, window time.Duration, quantiles []float64, labels ...string) Summary
 | 
						SummaryExt(name string, window time.Duration, quantiles []float64, labels ...string) Summary
 | 
				
			||||||
	// Write writes metrics to io.Writer
 | 
						// Write writes metrics to io.Writer
 | 
				
			||||||
	Write(w io.Writer, opts ...Option) error
 | 
						Write(w io.Writer, opts ...options.Option) error
 | 
				
			||||||
	// Options returns meter options
 | 
						// Options returns meter options
 | 
				
			||||||
	Options() Options
 | 
						Options() Options
 | 
				
			||||||
	// String return meter type
 | 
						// String return meter type
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,6 +3,8 @@ package meter
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"go.unistack.org/micro/v4/options"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NoopMeter is an noop implementation of Meter
 | 
					// NoopMeter is an noop implementation of Meter
 | 
				
			||||||
@@ -11,12 +13,12 @@ type noopMeter struct {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewMeter returns a configured noop reporter:
 | 
					// NewMeter returns a configured noop reporter:
 | 
				
			||||||
func NewMeter(opts ...Option) Meter {
 | 
					func NewMeter(opts ...options.Option) Meter {
 | 
				
			||||||
	return &noopMeter{opts: NewOptions(opts...)}
 | 
						return &noopMeter{opts: NewOptions(opts...)}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Clone return old meter with new options
 | 
					// Clone return old meter with new options
 | 
				
			||||||
func (r *noopMeter) Clone(opts ...Option) Meter {
 | 
					func (r *noopMeter) Clone(opts ...options.Option) Meter {
 | 
				
			||||||
	options := r.opts
 | 
						options := r.opts
 | 
				
			||||||
	for _, o := range opts {
 | 
						for _, o := range opts {
 | 
				
			||||||
		o(&options)
 | 
							o(&options)
 | 
				
			||||||
@@ -29,7 +31,7 @@ func (r *noopMeter) Name() string {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Init initialize options
 | 
					// Init initialize options
 | 
				
			||||||
func (r *noopMeter) Init(opts ...Option) error {
 | 
					func (r *noopMeter) Init(opts ...options.Option) error {
 | 
				
			||||||
	for _, o := range opts {
 | 
						for _, o := range opts {
 | 
				
			||||||
		o(&r.opts)
 | 
							o(&r.opts)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -67,7 +69,7 @@ func (r *noopMeter) Histogram(name string, labels ...string) Histogram {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Set implements the Meter interface
 | 
					// Set implements the Meter interface
 | 
				
			||||||
func (r *noopMeter) Set(opts ...Option) Meter {
 | 
					func (r *noopMeter) Set(opts ...options.Option) Meter {
 | 
				
			||||||
	m := &noopMeter{opts: r.opts}
 | 
						m := &noopMeter{opts: r.opts}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, o := range opts {
 | 
						for _, o := range opts {
 | 
				
			||||||
@@ -77,7 +79,7 @@ func (r *noopMeter) Set(opts ...Option) Meter {
 | 
				
			|||||||
	return m
 | 
						return m
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (r *noopMeter) Write(w io.Writer, opts ...Option) error {
 | 
					func (r *noopMeter) Write(_ io.Writer, _ ...options.Option) error {
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,13 +2,13 @@ package meter
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
 | 
						"reflect"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro/v3/logger"
 | 
						"go.unistack.org/micro/v4/logger"
 | 
				
			||||||
 | 
						"go.unistack.org/micro/v4/options"
 | 
				
			||||||
 | 
						rutil "go.unistack.org/micro/v4/util/reflect"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Option powers the configuration for metrics implementations:
 | 
					 | 
				
			||||||
type Option func(*Options)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Options for metrics implementations
 | 
					// Options for metrics implementations
 | 
				
			||||||
type Options struct {
 | 
					type Options struct {
 | 
				
			||||||
	// Logger used for logging
 | 
						// Logger used for logging
 | 
				
			||||||
@@ -34,7 +34,7 @@ type Options struct {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewOptions prepares a set of options:
 | 
					// NewOptions prepares a set of options:
 | 
				
			||||||
func NewOptions(opt ...Option) Options {
 | 
					func NewOptions(opt ...options.Option) Options {
 | 
				
			||||||
	opts := Options{
 | 
						opts := Options{
 | 
				
			||||||
		Address:      DefaultAddress,
 | 
							Address:      DefaultAddress,
 | 
				
			||||||
		Path:         DefaultPath,
 | 
							Path:         DefaultPath,
 | 
				
			||||||
@@ -52,37 +52,23 @@ func NewOptions(opt ...Option) Options {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// LabelPrefix sets the labels prefix
 | 
					// LabelPrefix sets the labels prefix
 | 
				
			||||||
func LabelPrefix(pref string) Option {
 | 
					func LabelPrefix(pref string) options.Option {
 | 
				
			||||||
	return func(o *Options) {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		o.LabelPrefix = pref
 | 
							return options.Set(src, pref, ".LabelPrefix")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// MetricPrefix sets the metric prefix
 | 
					// MetricPrefix sets the metric prefix
 | 
				
			||||||
func MetricPrefix(pref string) Option {
 | 
					func MetricPrefix(pref string) options.Option {
 | 
				
			||||||
	return func(o *Options) {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		o.MetricPrefix = pref
 | 
							return options.Set(src, pref, ".MetricPrefix")
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Context sets the metrics context
 | 
					 | 
				
			||||||
func Context(ctx context.Context) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Context = ctx
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Path used to serve metrics over HTTP
 | 
					// Path used to serve metrics over HTTP
 | 
				
			||||||
func Path(value string) Option {
 | 
					func Path(path string) options.Option {
 | 
				
			||||||
	return func(o *Options) {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		o.Path = value
 | 
							return options.Set(src, path, ".Path")
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Address is the listen address to serve metrics
 | 
					 | 
				
			||||||
func Address(value string) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Address = value
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -95,37 +81,34 @@ func TimingObjectives(value map[float64]float64) Option {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Logger sets the logger
 | 
					 | 
				
			||||||
func Logger(l logger.Logger) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Logger = l
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Labels sets the meter labels
 | 
					// Labels sets the meter labels
 | 
				
			||||||
func Labels(ls ...string) Option {
 | 
					func Labels(ls ...string) options.Option {
 | 
				
			||||||
	return func(o *Options) {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		o.Labels = append(o.Labels, ls...)
 | 
							v, err := options.Get(src, ".Labels")
 | 
				
			||||||
	}
 | 
							if err != nil {
 | 
				
			||||||
}
 | 
								return err
 | 
				
			||||||
 | 
							} else if rutil.IsZero(v) {
 | 
				
			||||||
// Name sets the name
 | 
								v = reflect.MakeSlice(reflect.TypeOf(v), 0, len(ls)).Interface()
 | 
				
			||||||
func Name(n string) Option {
 | 
							}
 | 
				
			||||||
	return func(o *Options) {
 | 
							cv := reflect.ValueOf(v)
 | 
				
			||||||
		o.Name = n
 | 
							for _, l := range ls {
 | 
				
			||||||
 | 
								reflect.Append(cv, reflect.ValueOf(l))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							err = options.Set(src, cv, ".Labels")
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// WriteProcessMetrics enable process metrics output for write
 | 
					// WriteProcessMetrics enable process metrics output for write
 | 
				
			||||||
func WriteProcessMetrics(b bool) Option {
 | 
					func WriteProcessMetrics(b bool) options.Option {
 | 
				
			||||||
	return func(o *Options) {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		o.WriteProcessMetrics = b
 | 
							return options.Set(src, b, ".WriteProcessMetrics")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// WriteFDMetrics enable fd metrics output for write
 | 
					// WriteFDMetrics enable fd metrics output for write
 | 
				
			||||||
func WriteFDMetrics(b bool) Option {
 | 
					func WriteFDMetrics(b bool) options.Option {
 | 
				
			||||||
	return func(o *Options) {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		o.WriteFDMetrics = b
 | 
							return options.Set(src, b, ".WriteFDMetrics")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,49 +1,17 @@
 | 
				
			|||||||
package wrapper // import "go.unistack.org/micro/v3/meter/wrapper"
 | 
					package wrapper // import "go.unistack.org/micro/v4/meter/wrapper"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro/v3/client"
 | 
						"go.unistack.org/micro/v4/client"
 | 
				
			||||||
	"go.unistack.org/micro/v3/meter"
 | 
						"go.unistack.org/micro/v4/meter"
 | 
				
			||||||
	"go.unistack.org/micro/v3/server"
 | 
						"go.unistack.org/micro/v4/semconv"
 | 
				
			||||||
 | 
						"go.unistack.org/micro/v4/server"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
	// ClientRequestDurationSeconds specifies meter metric name
 | 
					 | 
				
			||||||
	ClientRequestDurationSeconds = "client_request_duration_seconds"
 | 
					 | 
				
			||||||
	// ClientRequestLatencyMicroseconds specifies meter metric name
 | 
					 | 
				
			||||||
	ClientRequestLatencyMicroseconds = "client_request_latency_microseconds"
 | 
					 | 
				
			||||||
	// ClientRequestTotal specifies meter metric name
 | 
					 | 
				
			||||||
	ClientRequestTotal = "client_request_total"
 | 
					 | 
				
			||||||
	// ClientRequestInflight specifies meter metric name
 | 
					 | 
				
			||||||
	ClientRequestInflight = "client_request_inflight"
 | 
					 | 
				
			||||||
	// ServerRequestDurationSeconds specifies meter metric name
 | 
					 | 
				
			||||||
	ServerRequestDurationSeconds = "server_request_duration_seconds"
 | 
					 | 
				
			||||||
	// ServerRequestLatencyMicroseconds specifies meter metric name
 | 
					 | 
				
			||||||
	ServerRequestLatencyMicroseconds = "server_request_latency_microseconds"
 | 
					 | 
				
			||||||
	// ServerRequestTotal specifies meter metric name
 | 
					 | 
				
			||||||
	ServerRequestTotal = "server_request_total"
 | 
					 | 
				
			||||||
	// ServerRequestInflight specifies meter metric name
 | 
					 | 
				
			||||||
	ServerRequestInflight = "server_request_inflight"
 | 
					 | 
				
			||||||
	// PublishMessageDurationSeconds specifies meter metric name
 | 
					 | 
				
			||||||
	PublishMessageDurationSeconds = "publish_message_duration_seconds"
 | 
					 | 
				
			||||||
	// PublishMessageLatencyMicroseconds specifies meter metric name
 | 
					 | 
				
			||||||
	PublishMessageLatencyMicroseconds = "publish_message_latency_microseconds"
 | 
					 | 
				
			||||||
	// PublishMessageTotal specifies meter metric name
 | 
					 | 
				
			||||||
	PublishMessageTotal = "publish_message_total"
 | 
					 | 
				
			||||||
	// PublishMessageInflight specifies meter metric name
 | 
					 | 
				
			||||||
	PublishMessageInflight = "publish_message_inflight"
 | 
					 | 
				
			||||||
	// SubscribeMessageDurationSeconds specifies meter metric name
 | 
					 | 
				
			||||||
	SubscribeMessageDurationSeconds = "subscribe_message_duration_seconds"
 | 
					 | 
				
			||||||
	// SubscribeMessageLatencyMicroseconds specifies meter metric name
 | 
					 | 
				
			||||||
	SubscribeMessageLatencyMicroseconds = "subscribe_message_latency_microseconds"
 | 
					 | 
				
			||||||
	// SubscribeMessageTotal specifies meter metric name
 | 
					 | 
				
			||||||
	SubscribeMessageTotal = "subscribe_message_total"
 | 
					 | 
				
			||||||
	// SubscribeMessageInflight specifies meter metric name
 | 
					 | 
				
			||||||
	SubscribeMessageInflight = "subscribe_message_inflight"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	labelSuccess  = "success"
 | 
						labelSuccess  = "success"
 | 
				
			||||||
	labelFailure  = "failure"
 | 
						labelFailure  = "failure"
 | 
				
			||||||
	labelStatus   = "status"
 | 
						labelStatus   = "status"
 | 
				
			||||||
@@ -150,21 +118,21 @@ func (w *wrapper) CallFunc(ctx context.Context, addr string, req client.Request,
 | 
				
			|||||||
	labels := make([]string, 0, 4)
 | 
						labels := make([]string, 0, 4)
 | 
				
			||||||
	labels = append(labels, labelEndpoint, endpoint)
 | 
						labels = append(labels, labelEndpoint, endpoint)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	w.opts.Meter.Counter(ClientRequestInflight, labels...).Inc()
 | 
						w.opts.Meter.Counter(semconv.ClientRequestInflight, labels...).Inc()
 | 
				
			||||||
	ts := time.Now()
 | 
						ts := time.Now()
 | 
				
			||||||
	err := w.callFunc(ctx, addr, req, rsp, opts)
 | 
						err := w.callFunc(ctx, addr, req, rsp, opts)
 | 
				
			||||||
	te := time.Since(ts)
 | 
						te := time.Since(ts)
 | 
				
			||||||
	w.opts.Meter.Counter(ClientRequestInflight, labels...).Dec()
 | 
						w.opts.Meter.Counter(semconv.ClientRequestInflight, labels...).Dec()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	w.opts.Meter.Summary(ClientRequestLatencyMicroseconds, labels...).Update(te.Seconds())
 | 
						w.opts.Meter.Summary(semconv.ClientRequestLatencyMicroseconds, labels...).Update(te.Seconds())
 | 
				
			||||||
	w.opts.Meter.Histogram(ClientRequestDurationSeconds, labels...).Update(te.Seconds())
 | 
						w.opts.Meter.Histogram(semconv.ClientRequestDurationSeconds, labels...).Update(te.Seconds())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err == nil {
 | 
						if err == nil {
 | 
				
			||||||
		labels = append(labels, labelStatus, labelSuccess)
 | 
							labels = append(labels, labelStatus, labelSuccess)
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		labels = append(labels, labelStatus, labelFailure)
 | 
							labels = append(labels, labelStatus, labelFailure)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	w.opts.Meter.Counter(ClientRequestTotal, labels...).Inc()
 | 
						w.opts.Meter.Counter(semconv.ClientRequestTotal, labels...).Inc()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return err
 | 
						return err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -180,21 +148,21 @@ func (w *wrapper) Call(ctx context.Context, req client.Request, rsp interface{},
 | 
				
			|||||||
	labels := make([]string, 0, 4)
 | 
						labels := make([]string, 0, 4)
 | 
				
			||||||
	labels = append(labels, labelEndpoint, endpoint)
 | 
						labels = append(labels, labelEndpoint, endpoint)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	w.opts.Meter.Counter(ClientRequestInflight, labels...).Inc()
 | 
						w.opts.Meter.Counter(semconv.ClientRequestInflight, labels...).Inc()
 | 
				
			||||||
	ts := time.Now()
 | 
						ts := time.Now()
 | 
				
			||||||
	err := w.Client.Call(ctx, req, rsp, opts...)
 | 
						err := w.Client.Call(ctx, req, rsp, opts...)
 | 
				
			||||||
	te := time.Since(ts)
 | 
						te := time.Since(ts)
 | 
				
			||||||
	w.opts.Meter.Counter(ClientRequestInflight, labels...).Dec()
 | 
						w.opts.Meter.Counter(semconv.ClientRequestInflight, labels...).Dec()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	w.opts.Meter.Summary(ClientRequestLatencyMicroseconds, labels...).Update(te.Seconds())
 | 
						w.opts.Meter.Summary(semconv.ClientRequestLatencyMicroseconds, labels...).Update(te.Seconds())
 | 
				
			||||||
	w.opts.Meter.Histogram(ClientRequestDurationSeconds, labels...).Update(te.Seconds())
 | 
						w.opts.Meter.Histogram(semconv.ClientRequestDurationSeconds, labels...).Update(te.Seconds())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err == nil {
 | 
						if err == nil {
 | 
				
			||||||
		labels = append(labels, labelStatus, labelSuccess)
 | 
							labels = append(labels, labelStatus, labelSuccess)
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		labels = append(labels, labelStatus, labelFailure)
 | 
							labels = append(labels, labelStatus, labelFailure)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	w.opts.Meter.Counter(ClientRequestTotal, labels...).Inc()
 | 
						w.opts.Meter.Counter(semconv.ClientRequestTotal, labels...).Inc()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return err
 | 
						return err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -210,59 +178,25 @@ func (w *wrapper) Stream(ctx context.Context, req client.Request, opts ...client
 | 
				
			|||||||
	labels := make([]string, 0, 4)
 | 
						labels := make([]string, 0, 4)
 | 
				
			||||||
	labels = append(labels, labelEndpoint, endpoint)
 | 
						labels = append(labels, labelEndpoint, endpoint)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	w.opts.Meter.Counter(ClientRequestInflight, labels...).Inc()
 | 
						w.opts.Meter.Counter(semconv.ClientRequestInflight, labels...).Inc()
 | 
				
			||||||
	ts := time.Now()
 | 
						ts := time.Now()
 | 
				
			||||||
	stream, err := w.Client.Stream(ctx, req, opts...)
 | 
						stream, err := w.Client.Stream(ctx, req, opts...)
 | 
				
			||||||
	te := time.Since(ts)
 | 
						te := time.Since(ts)
 | 
				
			||||||
	w.opts.Meter.Counter(ClientRequestInflight, labels...).Dec()
 | 
						w.opts.Meter.Counter(semconv.ClientRequestInflight, labels...).Dec()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	w.opts.Meter.Summary(ClientRequestLatencyMicroseconds, labels...).Update(te.Seconds())
 | 
						w.opts.Meter.Summary(semconv.ClientRequestLatencyMicroseconds, labels...).Update(te.Seconds())
 | 
				
			||||||
	w.opts.Meter.Histogram(ClientRequestDurationSeconds, labels...).Update(te.Seconds())
 | 
						w.opts.Meter.Histogram(semconv.ClientRequestDurationSeconds, labels...).Update(te.Seconds())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err == nil {
 | 
						if err == nil {
 | 
				
			||||||
		labels = append(labels, labelStatus, labelSuccess)
 | 
							labels = append(labels, labelStatus, labelSuccess)
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		labels = append(labels, labelStatus, labelFailure)
 | 
							labels = append(labels, labelStatus, labelFailure)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	w.opts.Meter.Counter(ClientRequestTotal, labels...).Inc()
 | 
						w.opts.Meter.Counter(semconv.ClientRequestTotal, labels...).Inc()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return stream, err
 | 
						return stream, err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (w *wrapper) Publish(ctx context.Context, p client.Message, opts ...client.PublishOption) error {
 | 
					 | 
				
			||||||
	endpoint := p.Topic()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	labels := make([]string, 0, 4)
 | 
					 | 
				
			||||||
	labels = append(labels, labelEndpoint, endpoint)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	w.opts.Meter.Counter(PublishMessageInflight, labels...).Inc()
 | 
					 | 
				
			||||||
	ts := time.Now()
 | 
					 | 
				
			||||||
	err := w.Client.Publish(ctx, p, opts...)
 | 
					 | 
				
			||||||
	te := time.Since(ts)
 | 
					 | 
				
			||||||
	w.opts.Meter.Counter(PublishMessageInflight, labels...).Dec()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	w.opts.Meter.Summary(PublishMessageLatencyMicroseconds, labels...).Update(te.Seconds())
 | 
					 | 
				
			||||||
	w.opts.Meter.Histogram(PublishMessageDurationSeconds, labels...).Update(te.Seconds())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if err == nil {
 | 
					 | 
				
			||||||
		labels = append(labels, labelStatus, labelSuccess)
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		labels = append(labels, labelStatus, labelFailure)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	w.opts.Meter.Counter(PublishMessageTotal, labels...).Inc()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return err
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// NewHandlerWrapper create new server handler wrapper
 | 
					 | 
				
			||||||
// deprecated
 | 
					 | 
				
			||||||
func NewHandlerWrapper(opts ...Option) server.HandlerWrapper {
 | 
					 | 
				
			||||||
	handler := &wrapper{
 | 
					 | 
				
			||||||
		opts: NewOptions(opts...),
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return handler.HandlerFunc
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// NewServerHandlerWrapper create new server handler wrapper
 | 
					// NewServerHandlerWrapper create new server handler wrapper
 | 
				
			||||||
func NewServerHandlerWrapper(opts ...Option) server.HandlerWrapper {
 | 
					func NewServerHandlerWrapper(opts ...Option) server.HandlerWrapper {
 | 
				
			||||||
	handler := &wrapper{
 | 
						handler := &wrapper{
 | 
				
			||||||
@@ -283,64 +217,21 @@ func (w *wrapper) HandlerFunc(fn server.HandlerFunc) server.HandlerFunc {
 | 
				
			|||||||
		labels := make([]string, 0, 4)
 | 
							labels := make([]string, 0, 4)
 | 
				
			||||||
		labels = append(labels, labelEndpoint, endpoint)
 | 
							labels = append(labels, labelEndpoint, endpoint)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		w.opts.Meter.Counter(ServerRequestInflight, labels...).Inc()
 | 
							w.opts.Meter.Counter(semconv.ServerRequestInflight, labels...).Inc()
 | 
				
			||||||
		ts := time.Now()
 | 
							ts := time.Now()
 | 
				
			||||||
		err := fn(ctx, req, rsp)
 | 
							err := fn(ctx, req, rsp)
 | 
				
			||||||
		te := time.Since(ts)
 | 
							te := time.Since(ts)
 | 
				
			||||||
		w.opts.Meter.Counter(ServerRequestInflight, labels...).Dec()
 | 
							w.opts.Meter.Counter(semconv.ServerRequestInflight, labels...).Dec()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		w.opts.Meter.Summary(ServerRequestLatencyMicroseconds, labels...).Update(te.Seconds())
 | 
							w.opts.Meter.Summary(semconv.ServerRequestLatencyMicroseconds, labels...).Update(te.Seconds())
 | 
				
			||||||
		w.opts.Meter.Histogram(ServerRequestDurationSeconds, labels...).Update(te.Seconds())
 | 
							w.opts.Meter.Histogram(semconv.ServerRequestDurationSeconds, labels...).Update(te.Seconds())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if err == nil {
 | 
							if err == nil {
 | 
				
			||||||
			labels = append(labels, labelStatus, labelSuccess)
 | 
								labels = append(labels, labelStatus, labelSuccess)
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			labels = append(labels, labelStatus, labelFailure)
 | 
								labels = append(labels, labelStatus, labelFailure)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		w.opts.Meter.Counter(ServerRequestTotal, labels...).Inc()
 | 
							w.opts.Meter.Counter(semconv.ServerRequestTotal, labels...).Inc()
 | 
				
			||||||
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// NewSubscriberWrapper create server subscribe wrapper
 | 
					 | 
				
			||||||
// deprecated
 | 
					 | 
				
			||||||
func NewSubscriberWrapper(opts ...Option) server.SubscriberWrapper {
 | 
					 | 
				
			||||||
	handler := &wrapper{
 | 
					 | 
				
			||||||
		opts: NewOptions(opts...),
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return handler.SubscriberFunc
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func NewServerSubscriberWrapper(opts ...Option) server.SubscriberWrapper {
 | 
					 | 
				
			||||||
	handler := &wrapper{
 | 
					 | 
				
			||||||
		opts: NewOptions(opts...),
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return handler.SubscriberFunc
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (w *wrapper) SubscriberFunc(fn server.SubscriberFunc) server.SubscriberFunc {
 | 
					 | 
				
			||||||
	return func(ctx context.Context, msg server.Message) error {
 | 
					 | 
				
			||||||
		endpoint := msg.Topic()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		labels := make([]string, 0, 4)
 | 
					 | 
				
			||||||
		labels = append(labels, labelEndpoint, endpoint)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		w.opts.Meter.Counter(SubscribeMessageInflight, labels...).Inc()
 | 
					 | 
				
			||||||
		ts := time.Now()
 | 
					 | 
				
			||||||
		err := fn(ctx, msg)
 | 
					 | 
				
			||||||
		te := time.Since(ts)
 | 
					 | 
				
			||||||
		w.opts.Meter.Counter(SubscribeMessageInflight, labels...).Dec()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		w.opts.Meter.Summary(SubscribeMessageLatencyMicroseconds, labels...).Update(te.Seconds())
 | 
					 | 
				
			||||||
		w.opts.Meter.Histogram(SubscribeMessageDurationSeconds, labels...).Update(te.Seconds())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if err == nil {
 | 
					 | 
				
			||||||
			labels = append(labels, labelStatus, labelSuccess)
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			labels = append(labels, labelStatus, labelFailure)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		w.opts.Meter.Counter(SubscribeMessageTotal, labels...).Inc()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
package mtls // import "go.unistack.org/micro/v3/mtls"
 | 
					package mtls // import "go.unistack.org/micro/v4/mtls"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"bytes"
 | 
						"bytes"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,55 +0,0 @@
 | 
				
			|||||||
// Package network is for creating internetworks
 | 
					 | 
				
			||||||
package network // import "go.unistack.org/micro/v3/network"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"go.unistack.org/micro/v3/client"
 | 
					 | 
				
			||||||
	"go.unistack.org/micro/v3/server"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Error is network node errors
 | 
					 | 
				
			||||||
type Error interface {
 | 
					 | 
				
			||||||
	// Count is current count of errors
 | 
					 | 
				
			||||||
	Count() int
 | 
					 | 
				
			||||||
	// Msg is last error message
 | 
					 | 
				
			||||||
	Msg() string
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Status is node status
 | 
					 | 
				
			||||||
type Status interface {
 | 
					 | 
				
			||||||
	// Error reports error status
 | 
					 | 
				
			||||||
	Error() Error
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Node is network node
 | 
					 | 
				
			||||||
type Node interface {
 | 
					 | 
				
			||||||
	// Id is node id
 | 
					 | 
				
			||||||
	Id() string
 | 
					 | 
				
			||||||
	// Address is node bind address
 | 
					 | 
				
			||||||
	Address() string
 | 
					 | 
				
			||||||
	// Peers returns node peers
 | 
					 | 
				
			||||||
	Peers() []Node
 | 
					 | 
				
			||||||
	// Network is the network node is in
 | 
					 | 
				
			||||||
	Network() Network
 | 
					 | 
				
			||||||
	// Status returns node status
 | 
					 | 
				
			||||||
	Status() Status
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Network is micro network
 | 
					 | 
				
			||||||
type Network interface {
 | 
					 | 
				
			||||||
	// Node is network node
 | 
					 | 
				
			||||||
	Node
 | 
					 | 
				
			||||||
	// Initialise options
 | 
					 | 
				
			||||||
	Init(...Option) error
 | 
					 | 
				
			||||||
	// Options returns the network options
 | 
					 | 
				
			||||||
	Options() Options
 | 
					 | 
				
			||||||
	// Name of the network
 | 
					 | 
				
			||||||
	Name() string
 | 
					 | 
				
			||||||
	// Connect starts the resolver and tunnel server
 | 
					 | 
				
			||||||
	Connect() error
 | 
					 | 
				
			||||||
	// Close stops the tunnel and resolving
 | 
					 | 
				
			||||||
	Close() error
 | 
					 | 
				
			||||||
	// Client is micro client
 | 
					 | 
				
			||||||
	Client() client.Client
 | 
					 | 
				
			||||||
	// Server is micro server
 | 
					 | 
				
			||||||
	Server() server.Server
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,135 +0,0 @@
 | 
				
			|||||||
package network
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"go.unistack.org/micro/v3/logger"
 | 
					 | 
				
			||||||
	"go.unistack.org/micro/v3/meter"
 | 
					 | 
				
			||||||
	"go.unistack.org/micro/v3/network/tunnel"
 | 
					 | 
				
			||||||
	"go.unistack.org/micro/v3/proxy"
 | 
					 | 
				
			||||||
	"go.unistack.org/micro/v3/router"
 | 
					 | 
				
			||||||
	"go.unistack.org/micro/v3/tracer"
 | 
					 | 
				
			||||||
	"go.unistack.org/micro/v3/util/id"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Option func
 | 
					 | 
				
			||||||
type Option func(*Options)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Options configure network
 | 
					 | 
				
			||||||
type Options struct {
 | 
					 | 
				
			||||||
	// Router used for routing
 | 
					 | 
				
			||||||
	Router router.Router
 | 
					 | 
				
			||||||
	// Proxy holds the proxy
 | 
					 | 
				
			||||||
	Proxy proxy.Proxy
 | 
					 | 
				
			||||||
	// Logger used for logging
 | 
					 | 
				
			||||||
	Logger logger.Logger
 | 
					 | 
				
			||||||
	// Meter used for metrics
 | 
					 | 
				
			||||||
	Meter meter.Meter
 | 
					 | 
				
			||||||
	// Tracer used for tracing
 | 
					 | 
				
			||||||
	Tracer tracer.Tracer
 | 
					 | 
				
			||||||
	// Tunnel used for transfer data
 | 
					 | 
				
			||||||
	Tunnel tunnel.Tunnel
 | 
					 | 
				
			||||||
	// ID of the node
 | 
					 | 
				
			||||||
	ID string
 | 
					 | 
				
			||||||
	// Name of the network
 | 
					 | 
				
			||||||
	Name string
 | 
					 | 
				
			||||||
	// Address to bind to
 | 
					 | 
				
			||||||
	Address string
 | 
					 | 
				
			||||||
	// Advertise sets the address to advertise
 | 
					 | 
				
			||||||
	Advertise string
 | 
					 | 
				
			||||||
	// Nodes is a list of nodes to connect to
 | 
					 | 
				
			||||||
	Nodes []string
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ID sets the id of the network node
 | 
					 | 
				
			||||||
func ID(id string) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.ID = id
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Name sets the network name
 | 
					 | 
				
			||||||
func Name(n string) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Name = n
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Address sets the network address
 | 
					 | 
				
			||||||
func Address(a string) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Address = a
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Advertise sets the address to advertise
 | 
					 | 
				
			||||||
func Advertise(a string) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Advertise = a
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Nodes is a list of nodes to connect to
 | 
					 | 
				
			||||||
func Nodes(n ...string) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Nodes = n
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Tunnel sets the network tunnel
 | 
					 | 
				
			||||||
func Tunnel(t tunnel.Tunnel) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Tunnel = t
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Router sets the network router
 | 
					 | 
				
			||||||
func Router(r router.Router) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Router = r
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Proxy sets the network proxy
 | 
					 | 
				
			||||||
func Proxy(p proxy.Proxy) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Proxy = p
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Logger sets the network logger
 | 
					 | 
				
			||||||
func Logger(l logger.Logger) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Logger = l
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Meter sets the meter
 | 
					 | 
				
			||||||
func Meter(m meter.Meter) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Meter = m
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Tracer to be used for tracing
 | 
					 | 
				
			||||||
func Tracer(t tracer.Tracer) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Tracer = t
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// NewOptions returns network default options
 | 
					 | 
				
			||||||
func NewOptions(opts ...Option) Options {
 | 
					 | 
				
			||||||
	options := Options{
 | 
					 | 
				
			||||||
		ID:      id.Must(),
 | 
					 | 
				
			||||||
		Name:    "go.micro",
 | 
					 | 
				
			||||||
		Address: ":0",
 | 
					 | 
				
			||||||
		Logger:  logger.DefaultLogger,
 | 
					 | 
				
			||||||
		Meter:   meter.DefaultMeter,
 | 
					 | 
				
			||||||
		Tracer:  tracer.DefaultTracer,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for _, o := range opts {
 | 
					 | 
				
			||||||
		o(&options)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return options
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,34 +0,0 @@
 | 
				
			|||||||
package transport
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"context"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type transportKey struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// FromContext get transport from context
 | 
					 | 
				
			||||||
func FromContext(ctx context.Context) (Transport, bool) {
 | 
					 | 
				
			||||||
	if ctx == nil {
 | 
					 | 
				
			||||||
		return nil, false
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	c, ok := ctx.Value(transportKey{}).(Transport)
 | 
					 | 
				
			||||||
	return c, ok
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// NewContext put transport in context
 | 
					 | 
				
			||||||
func NewContext(ctx context.Context, c Transport) context.Context {
 | 
					 | 
				
			||||||
	if ctx == nil {
 | 
					 | 
				
			||||||
		ctx = context.Background()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return context.WithValue(ctx, transportKey{}, c)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// SetOption returns a function to setup a context with given value
 | 
					 | 
				
			||||||
func SetOption(k, v interface{}) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		if o.Context == nil {
 | 
					 | 
				
			||||||
			o.Context = context.Background()
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		o.Context = context.WithValue(o.Context, k, v)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,258 +0,0 @@
 | 
				
			|||||||
package transport
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"context"
 | 
					 | 
				
			||||||
	"errors"
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"net"
 | 
					 | 
				
			||||||
	"sync"
 | 
					 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	maddr "go.unistack.org/micro/v3/util/addr"
 | 
					 | 
				
			||||||
	mnet "go.unistack.org/micro/v3/util/net"
 | 
					 | 
				
			||||||
	"go.unistack.org/micro/v3/util/rand"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type memorySocket struct {
 | 
					 | 
				
			||||||
	ctx     context.Context
 | 
					 | 
				
			||||||
	recv    chan *Message
 | 
					 | 
				
			||||||
	exit    chan bool
 | 
					 | 
				
			||||||
	lexit   chan bool
 | 
					 | 
				
			||||||
	send    chan *Message
 | 
					 | 
				
			||||||
	local   string
 | 
					 | 
				
			||||||
	remote  string
 | 
					 | 
				
			||||||
	timeout time.Duration
 | 
					 | 
				
			||||||
	sync.RWMutex
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type memoryClient struct {
 | 
					 | 
				
			||||||
	*memorySocket
 | 
					 | 
				
			||||||
	opts DialOptions
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type memoryListener struct {
 | 
					 | 
				
			||||||
	lopts ListenOptions
 | 
					 | 
				
			||||||
	ctx   context.Context
 | 
					 | 
				
			||||||
	exit  chan bool
 | 
					 | 
				
			||||||
	conn  chan *memorySocket
 | 
					 | 
				
			||||||
	addr  string
 | 
					 | 
				
			||||||
	topts Options
 | 
					 | 
				
			||||||
	sync.RWMutex
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type memoryTransport struct {
 | 
					 | 
				
			||||||
	listeners map[string]*memoryListener
 | 
					 | 
				
			||||||
	opts      Options
 | 
					 | 
				
			||||||
	sync.RWMutex
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (ms *memorySocket) Recv(m *Message) error {
 | 
					 | 
				
			||||||
	ms.RLock()
 | 
					 | 
				
			||||||
	defer ms.RUnlock()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ctx := ms.ctx
 | 
					 | 
				
			||||||
	if ms.timeout > 0 {
 | 
					 | 
				
			||||||
		var cancel context.CancelFunc
 | 
					 | 
				
			||||||
		ctx, cancel = context.WithTimeout(ms.ctx, ms.timeout)
 | 
					 | 
				
			||||||
		defer cancel()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	select {
 | 
					 | 
				
			||||||
	case <-ctx.Done():
 | 
					 | 
				
			||||||
		return ctx.Err()
 | 
					 | 
				
			||||||
	case <-ms.exit:
 | 
					 | 
				
			||||||
		return errors.New("connection closed")
 | 
					 | 
				
			||||||
	case <-ms.lexit:
 | 
					 | 
				
			||||||
		return errors.New("server connection closed")
 | 
					 | 
				
			||||||
	case cm := <-ms.recv:
 | 
					 | 
				
			||||||
		*m = *cm
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (ms *memorySocket) Local() string {
 | 
					 | 
				
			||||||
	return ms.local
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (ms *memorySocket) Remote() string {
 | 
					 | 
				
			||||||
	return ms.remote
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (ms *memorySocket) Send(m *Message) error {
 | 
					 | 
				
			||||||
	ms.RLock()
 | 
					 | 
				
			||||||
	defer ms.RUnlock()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ctx := ms.ctx
 | 
					 | 
				
			||||||
	if ms.timeout > 0 {
 | 
					 | 
				
			||||||
		var cancel context.CancelFunc
 | 
					 | 
				
			||||||
		ctx, cancel = context.WithTimeout(ms.ctx, ms.timeout)
 | 
					 | 
				
			||||||
		defer cancel()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	select {
 | 
					 | 
				
			||||||
	case <-ctx.Done():
 | 
					 | 
				
			||||||
		return ctx.Err()
 | 
					 | 
				
			||||||
	case <-ms.exit:
 | 
					 | 
				
			||||||
		return errors.New("connection closed")
 | 
					 | 
				
			||||||
	case <-ms.lexit:
 | 
					 | 
				
			||||||
		return errors.New("server connection closed")
 | 
					 | 
				
			||||||
	case ms.send <- m:
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (ms *memorySocket) Close() error {
 | 
					 | 
				
			||||||
	ms.Lock()
 | 
					 | 
				
			||||||
	defer ms.Unlock()
 | 
					 | 
				
			||||||
	select {
 | 
					 | 
				
			||||||
	case <-ms.exit:
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		close(ms.exit)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *memoryListener) Addr() string {
 | 
					 | 
				
			||||||
	return m.addr
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *memoryListener) Close() error {
 | 
					 | 
				
			||||||
	m.Lock()
 | 
					 | 
				
			||||||
	defer m.Unlock()
 | 
					 | 
				
			||||||
	select {
 | 
					 | 
				
			||||||
	case <-m.exit:
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		close(m.exit)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *memoryListener) Accept(fn func(Socket)) error {
 | 
					 | 
				
			||||||
	for {
 | 
					 | 
				
			||||||
		select {
 | 
					 | 
				
			||||||
		case <-m.exit:
 | 
					 | 
				
			||||||
			return nil
 | 
					 | 
				
			||||||
		case c := <-m.conn:
 | 
					 | 
				
			||||||
			go fn(&memorySocket{
 | 
					 | 
				
			||||||
				lexit:   c.lexit,
 | 
					 | 
				
			||||||
				exit:    c.exit,
 | 
					 | 
				
			||||||
				send:    c.recv,
 | 
					 | 
				
			||||||
				recv:    c.send,
 | 
					 | 
				
			||||||
				local:   c.Remote(),
 | 
					 | 
				
			||||||
				remote:  c.Local(),
 | 
					 | 
				
			||||||
				timeout: m.topts.Timeout,
 | 
					 | 
				
			||||||
				ctx:     m.topts.Context,
 | 
					 | 
				
			||||||
			})
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *memoryTransport) Dial(ctx context.Context, addr string, opts ...DialOption) (Client, error) {
 | 
					 | 
				
			||||||
	m.RLock()
 | 
					 | 
				
			||||||
	defer m.RUnlock()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	listener, ok := m.listeners[addr]
 | 
					 | 
				
			||||||
	if !ok {
 | 
					 | 
				
			||||||
		return nil, errors.New("could not dial " + addr)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	options := NewDialOptions(opts...)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	client := &memoryClient{
 | 
					 | 
				
			||||||
		&memorySocket{
 | 
					 | 
				
			||||||
			send:    make(chan *Message),
 | 
					 | 
				
			||||||
			recv:    make(chan *Message),
 | 
					 | 
				
			||||||
			exit:    make(chan bool),
 | 
					 | 
				
			||||||
			lexit:   listener.exit,
 | 
					 | 
				
			||||||
			local:   addr,
 | 
					 | 
				
			||||||
			remote:  addr,
 | 
					 | 
				
			||||||
			timeout: m.opts.Timeout,
 | 
					 | 
				
			||||||
			ctx:     m.opts.Context,
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		options,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// pseudo connect
 | 
					 | 
				
			||||||
	select {
 | 
					 | 
				
			||||||
	case <-listener.exit:
 | 
					 | 
				
			||||||
		return nil, errors.New("connection error")
 | 
					 | 
				
			||||||
	case listener.conn <- client.memorySocket:
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return client, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *memoryTransport) Listen(ctx context.Context, addr string, opts ...ListenOption) (Listener, error) {
 | 
					 | 
				
			||||||
	m.Lock()
 | 
					 | 
				
			||||||
	defer m.Unlock()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	options := NewListenOptions(opts...)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	host, port, err := net.SplitHostPort(addr)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	addr, err = maddr.Extract(host)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// if zero port then randomly assign one
 | 
					 | 
				
			||||||
	if len(port) > 0 && port == "0" {
 | 
					 | 
				
			||||||
		var rng rand.Rand
 | 
					 | 
				
			||||||
		i := rng.Intn(20000)
 | 
					 | 
				
			||||||
		port = fmt.Sprintf("%d", 10000+i)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// set addr with port
 | 
					 | 
				
			||||||
	addr = mnet.HostPort(addr, port)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if _, ok := m.listeners[addr]; ok {
 | 
					 | 
				
			||||||
		return nil, errors.New("already listening on " + addr)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	listener := &memoryListener{
 | 
					 | 
				
			||||||
		lopts: options,
 | 
					 | 
				
			||||||
		topts: m.opts,
 | 
					 | 
				
			||||||
		addr:  addr,
 | 
					 | 
				
			||||||
		conn:  make(chan *memorySocket),
 | 
					 | 
				
			||||||
		exit:  make(chan bool),
 | 
					 | 
				
			||||||
		ctx:   m.opts.Context,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	m.listeners[addr] = listener
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return listener, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *memoryTransport) Init(opts ...Option) error {
 | 
					 | 
				
			||||||
	for _, o := range opts {
 | 
					 | 
				
			||||||
		o(&m.opts)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *memoryTransport) Options() Options {
 | 
					 | 
				
			||||||
	return m.opts
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *memoryTransport) String() string {
 | 
					 | 
				
			||||||
	return "memory"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *memoryTransport) Name() string {
 | 
					 | 
				
			||||||
	return m.opts.Name
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// NewTransport returns new memory transport with options
 | 
					 | 
				
			||||||
func NewTransport(opts ...Option) Transport {
 | 
					 | 
				
			||||||
	options := NewOptions(opts...)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return &memoryTransport{
 | 
					 | 
				
			||||||
		opts:      options,
 | 
					 | 
				
			||||||
		listeners: make(map[string]*memoryListener),
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,100 +0,0 @@
 | 
				
			|||||||
package transport
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"context"
 | 
					 | 
				
			||||||
	"os"
 | 
					 | 
				
			||||||
	"testing"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestMemoryTransport(t *testing.T) {
 | 
					 | 
				
			||||||
	tr := NewTransport()
 | 
					 | 
				
			||||||
	ctx := context.Background()
 | 
					 | 
				
			||||||
	// bind / listen
 | 
					 | 
				
			||||||
	l, err := tr.Listen(ctx, "127.0.0.1:8080")
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		t.Fatalf("Unexpected error listening %v", err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	defer l.Close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	cherr := make(chan error, 1)
 | 
					 | 
				
			||||||
	// accept
 | 
					 | 
				
			||||||
	go func() {
 | 
					 | 
				
			||||||
		if nerr := l.Accept(func(sock Socket) {
 | 
					 | 
				
			||||||
			for {
 | 
					 | 
				
			||||||
				var m Message
 | 
					 | 
				
			||||||
				if rerr := sock.Recv(&m); rerr != nil {
 | 
					 | 
				
			||||||
					cherr <- rerr
 | 
					 | 
				
			||||||
					return
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				if len(os.Getenv("INTEGRATION_TESTS")) == 0 {
 | 
					 | 
				
			||||||
					t.Logf("Server Received %s", string(m.Body))
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				if cerr := sock.Send(&Message{
 | 
					 | 
				
			||||||
					Body: []byte(`pong`),
 | 
					 | 
				
			||||||
				}); cerr != nil {
 | 
					 | 
				
			||||||
					cherr <- cerr
 | 
					 | 
				
			||||||
					return
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}); nerr != nil {
 | 
					 | 
				
			||||||
			cherr <- err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// dial
 | 
					 | 
				
			||||||
	c, err := tr.Dial(ctx, "127.0.0.1:8080")
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		t.Fatalf("Unexpected error dialing %v", err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	defer c.Close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	select {
 | 
					 | 
				
			||||||
	case err := <-cherr:
 | 
					 | 
				
			||||||
		t.Fatal(err)
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		// send <=> receive
 | 
					 | 
				
			||||||
		for i := 0; i < 3; i++ {
 | 
					 | 
				
			||||||
			if err := c.Send(&Message{
 | 
					 | 
				
			||||||
				Body: []byte(`ping`),
 | 
					 | 
				
			||||||
			}); err != nil {
 | 
					 | 
				
			||||||
				return
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			var m Message
 | 
					 | 
				
			||||||
			if err := c.Recv(&m); err != nil {
 | 
					 | 
				
			||||||
				return
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if len(os.Getenv("INTEGRATION_TESTS")) == 0 {
 | 
					 | 
				
			||||||
				t.Logf("Client Received %s", string(m.Body))
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestListener(t *testing.T) {
 | 
					 | 
				
			||||||
	tr := NewTransport()
 | 
					 | 
				
			||||||
	ctx := context.Background()
 | 
					 | 
				
			||||||
	// bind / listen on random port
 | 
					 | 
				
			||||||
	l, err := tr.Listen(ctx, ":0")
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		t.Fatalf("Unexpected error listening %v", err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	defer l.Close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// try again
 | 
					 | 
				
			||||||
	l2, err := tr.Listen(ctx, ":0")
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		t.Fatalf("Unexpected error listening %v", err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	defer l2.Close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// now make sure it still fails
 | 
					 | 
				
			||||||
	l3, err := tr.Listen(ctx, ":8080")
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		t.Fatalf("Unexpected error listening %v", err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	defer l3.Close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if _, err := tr.Listen(ctx, ":8080"); err == nil {
 | 
					 | 
				
			||||||
		t.Fatal("Expected error binding to :8080 got nil")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,175 +0,0 @@
 | 
				
			|||||||
package transport
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"context"
 | 
					 | 
				
			||||||
	"crypto/tls"
 | 
					 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"go.unistack.org/micro/v3/codec"
 | 
					 | 
				
			||||||
	"go.unistack.org/micro/v3/logger"
 | 
					 | 
				
			||||||
	"go.unistack.org/micro/v3/meter"
 | 
					 | 
				
			||||||
	"go.unistack.org/micro/v3/tracer"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Options struct holds the transport options
 | 
					 | 
				
			||||||
type Options struct {
 | 
					 | 
				
			||||||
	// Meter used for metrics
 | 
					 | 
				
			||||||
	Meter meter.Meter
 | 
					 | 
				
			||||||
	// Tracer used for tracing
 | 
					 | 
				
			||||||
	Tracer tracer.Tracer
 | 
					 | 
				
			||||||
	// Codec used for marshal/unmarshal messages
 | 
					 | 
				
			||||||
	Codec codec.Codec
 | 
					 | 
				
			||||||
	// Logger used for logging
 | 
					 | 
				
			||||||
	Logger logger.Logger
 | 
					 | 
				
			||||||
	// Context holds external options
 | 
					 | 
				
			||||||
	Context context.Context
 | 
					 | 
				
			||||||
	// TLSConfig holds tls.TLSConfig options
 | 
					 | 
				
			||||||
	TLSConfig *tls.Config
 | 
					 | 
				
			||||||
	// Name holds the transport name
 | 
					 | 
				
			||||||
	Name string
 | 
					 | 
				
			||||||
	// Addrs holds the transport addrs
 | 
					 | 
				
			||||||
	Addrs []string
 | 
					 | 
				
			||||||
	// Timeout holds the timeout
 | 
					 | 
				
			||||||
	Timeout time.Duration
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// NewOptions returns new options
 | 
					 | 
				
			||||||
func NewOptions(opts ...Option) Options {
 | 
					 | 
				
			||||||
	options := Options{
 | 
					 | 
				
			||||||
		Logger:  logger.DefaultLogger,
 | 
					 | 
				
			||||||
		Meter:   meter.DefaultMeter,
 | 
					 | 
				
			||||||
		Tracer:  tracer.DefaultTracer,
 | 
					 | 
				
			||||||
		Context: context.Background(),
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for _, o := range opts {
 | 
					 | 
				
			||||||
		o(&options)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return options
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// DialOptions struct
 | 
					 | 
				
			||||||
type DialOptions struct {
 | 
					 | 
				
			||||||
	// Context holds the external options
 | 
					 | 
				
			||||||
	Context context.Context
 | 
					 | 
				
			||||||
	// Timeout holds the timeout
 | 
					 | 
				
			||||||
	Timeout time.Duration
 | 
					 | 
				
			||||||
	// Stream flag
 | 
					 | 
				
			||||||
	Stream bool
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// NewDialOptions returns new DialOptions
 | 
					 | 
				
			||||||
func NewDialOptions(opts ...DialOption) DialOptions {
 | 
					 | 
				
			||||||
	options := DialOptions{
 | 
					 | 
				
			||||||
		Timeout: DefaultDialTimeout,
 | 
					 | 
				
			||||||
		Context: context.Background(),
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for _, o := range opts {
 | 
					 | 
				
			||||||
		o(&options)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return options
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ListenOptions struct
 | 
					 | 
				
			||||||
type ListenOptions struct {
 | 
					 | 
				
			||||||
	// TODO: add tls options when listening
 | 
					 | 
				
			||||||
	// Currently set in global options
 | 
					 | 
				
			||||||
	// Context holds the external options
 | 
					 | 
				
			||||||
	Context context.Context
 | 
					 | 
				
			||||||
	// TLSConfig holds the *tls.Config options
 | 
					 | 
				
			||||||
	TLSConfig *tls.Config
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// NewListenOptions returns new ListenOptions
 | 
					 | 
				
			||||||
func NewListenOptions(opts ...ListenOption) ListenOptions {
 | 
					 | 
				
			||||||
	options := ListenOptions{
 | 
					 | 
				
			||||||
		Context: context.Background(),
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for _, o := range opts {
 | 
					 | 
				
			||||||
		o(&options)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return options
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Addrs to use for transport
 | 
					 | 
				
			||||||
func Addrs(addrs ...string) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Addrs = addrs
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Logger sets the logger
 | 
					 | 
				
			||||||
func Logger(l logger.Logger) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Logger = l
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Meter sets the meter
 | 
					 | 
				
			||||||
func Meter(m meter.Meter) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Meter = m
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Context sets the context
 | 
					 | 
				
			||||||
func Context(ctx context.Context) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Context = ctx
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Codec sets the codec used for encoding where the transport
 | 
					 | 
				
			||||||
// does not support message headers
 | 
					 | 
				
			||||||
func Codec(c codec.Codec) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Codec = c
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Timeout sets the timeout for Send/Recv execution
 | 
					 | 
				
			||||||
func Timeout(t time.Duration) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Timeout = t
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// TLSConfig to be used for the transport.
 | 
					 | 
				
			||||||
func TLSConfig(t *tls.Config) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.TLSConfig = t
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// WithStream indicates whether this is a streaming connection
 | 
					 | 
				
			||||||
func WithStream() DialOption {
 | 
					 | 
				
			||||||
	return func(o *DialOptions) {
 | 
					 | 
				
			||||||
		o.Stream = true
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// WithTimeout used when dialling the remote side
 | 
					 | 
				
			||||||
func WithTimeout(d time.Duration) DialOption {
 | 
					 | 
				
			||||||
	return func(o *DialOptions) {
 | 
					 | 
				
			||||||
		o.Timeout = d
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Tracer to be used for tracing
 | 
					 | 
				
			||||||
func Tracer(t tracer.Tracer) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Tracer = t
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Name sets the name
 | 
					 | 
				
			||||||
func Name(n string) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Name = n
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,63 +0,0 @@
 | 
				
			|||||||
// Package transport is an interface for synchronous connection based communication
 | 
					 | 
				
			||||||
package transport // import "go.unistack.org/micro/v3/network/transport"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"context"
 | 
					 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"go.unistack.org/micro/v3/metadata"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var (
 | 
					 | 
				
			||||||
	// DefaultTransport is the global default transport
 | 
					 | 
				
			||||||
	DefaultTransport Transport = NewTransport()
 | 
					 | 
				
			||||||
	// DefaultDialTimeout the default dial timeout
 | 
					 | 
				
			||||||
	DefaultDialTimeout = time.Second * 5
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Transport is an interface which is used for communication between
 | 
					 | 
				
			||||||
// services. It uses connection based socket send/recv semantics and
 | 
					 | 
				
			||||||
// has various implementations; http, grpc, quic.
 | 
					 | 
				
			||||||
type Transport interface {
 | 
					 | 
				
			||||||
	Init(...Option) error
 | 
					 | 
				
			||||||
	Options() Options
 | 
					 | 
				
			||||||
	Dial(ctx context.Context, addr string, opts ...DialOption) (Client, error)
 | 
					 | 
				
			||||||
	Listen(ctx context.Context, addr string, opts ...ListenOption) (Listener, error)
 | 
					 | 
				
			||||||
	String() string
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Message is used to transfer data
 | 
					 | 
				
			||||||
type Message struct {
 | 
					 | 
				
			||||||
	Header metadata.Metadata
 | 
					 | 
				
			||||||
	Body   []byte
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Socket bastraction interface
 | 
					 | 
				
			||||||
type Socket interface {
 | 
					 | 
				
			||||||
	Recv(*Message) error
 | 
					 | 
				
			||||||
	Send(*Message) error
 | 
					 | 
				
			||||||
	Close() error
 | 
					 | 
				
			||||||
	Local() string
 | 
					 | 
				
			||||||
	Remote() string
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Client is the socket owner
 | 
					 | 
				
			||||||
type Client interface {
 | 
					 | 
				
			||||||
	Socket
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Listener is the interface for stream oriented messaging
 | 
					 | 
				
			||||||
type Listener interface {
 | 
					 | 
				
			||||||
	Addr() string
 | 
					 | 
				
			||||||
	Close() error
 | 
					 | 
				
			||||||
	Accept(func(Socket)) error
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Option is the option signature
 | 
					 | 
				
			||||||
type Option func(*Options)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// DialOption is the option signature
 | 
					 | 
				
			||||||
type DialOption func(*DialOptions)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ListenOption is the option signature
 | 
					 | 
				
			||||||
type ListenOption func(*ListenOptions)
 | 
					 | 
				
			||||||
@@ -1,356 +0,0 @@
 | 
				
			|||||||
// Package broker is a tunnel broker
 | 
					 | 
				
			||||||
package broker // import "go.unistack.org/micro/v3/network/tunnel/broker"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"context"
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"go.unistack.org/micro/v3/broker"
 | 
					 | 
				
			||||||
	"go.unistack.org/micro/v3/logger"
 | 
					 | 
				
			||||||
	"go.unistack.org/micro/v3/metadata"
 | 
					 | 
				
			||||||
	"go.unistack.org/micro/v3/network/transport"
 | 
					 | 
				
			||||||
	"go.unistack.org/micro/v3/network/tunnel"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type tunBroker struct {
 | 
					 | 
				
			||||||
	tunnel tunnel.Tunnel
 | 
					 | 
				
			||||||
	opts   broker.Options
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type tunSubscriber struct {
 | 
					 | 
				
			||||||
	listener tunnel.Listener
 | 
					 | 
				
			||||||
	handler  broker.Handler
 | 
					 | 
				
			||||||
	closed   chan bool
 | 
					 | 
				
			||||||
	topic    string
 | 
					 | 
				
			||||||
	opts     broker.SubscribeOptions
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type tunBatchSubscriber struct {
 | 
					 | 
				
			||||||
	listener tunnel.Listener
 | 
					 | 
				
			||||||
	handler  broker.BatchHandler
 | 
					 | 
				
			||||||
	closed   chan bool
 | 
					 | 
				
			||||||
	topic    string
 | 
					 | 
				
			||||||
	opts     broker.SubscribeOptions
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type tunEvent struct {
 | 
					 | 
				
			||||||
	err     error
 | 
					 | 
				
			||||||
	message *broker.Message
 | 
					 | 
				
			||||||
	topic   string
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// used to access tunnel from options context
 | 
					 | 
				
			||||||
type (
 | 
					 | 
				
			||||||
	tunnelKey  struct{}
 | 
					 | 
				
			||||||
	tunnelAddr struct{}
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (t *tunBroker) Init(opts ...broker.Option) error {
 | 
					 | 
				
			||||||
	for _, o := range opts {
 | 
					 | 
				
			||||||
		o(&t.opts)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (t *tunBroker) Name() string {
 | 
					 | 
				
			||||||
	return t.opts.Name
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (t *tunBroker) Options() broker.Options {
 | 
					 | 
				
			||||||
	return t.opts
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (t *tunBroker) Address() string {
 | 
					 | 
				
			||||||
	return t.tunnel.Address()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (t *tunBroker) Connect(ctx context.Context) error {
 | 
					 | 
				
			||||||
	return t.tunnel.Connect(ctx)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (t *tunBroker) Disconnect(ctx context.Context) error {
 | 
					 | 
				
			||||||
	return t.tunnel.Close(ctx)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (t *tunBroker) BatchPublish(ctx context.Context, msgs []*broker.Message, opts ...broker.PublishOption) error {
 | 
					 | 
				
			||||||
	// TODO: this is probably inefficient, we might want to just maintain an open connection
 | 
					 | 
				
			||||||
	// it may be easier to add broadcast to the tunnel
 | 
					 | 
				
			||||||
	topicMap := make(map[string]tunnel.Session)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	var err error
 | 
					 | 
				
			||||||
	for _, msg := range msgs {
 | 
					 | 
				
			||||||
		topic, _ := msg.Header.Get(metadata.HeaderTopic)
 | 
					 | 
				
			||||||
		c, ok := topicMap[topic]
 | 
					 | 
				
			||||||
		if !ok {
 | 
					 | 
				
			||||||
			c, err = t.tunnel.Dial(ctx, topic, tunnel.DialMode(tunnel.Multicast))
 | 
					 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				return err
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			defer c.Close()
 | 
					 | 
				
			||||||
			topicMap[topic] = c
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if err = c.Send(&transport.Message{
 | 
					 | 
				
			||||||
			Header: msg.Header,
 | 
					 | 
				
			||||||
			Body:   msg.Body,
 | 
					 | 
				
			||||||
		}); err != nil {
 | 
					 | 
				
			||||||
			//	msg.SetError(err)
 | 
					 | 
				
			||||||
			return err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (t *tunBroker) Publish(ctx context.Context, topic string, m *broker.Message, opts ...broker.PublishOption) error {
 | 
					 | 
				
			||||||
	// TODO: this is probably inefficient, we might want to just maintain an open connection
 | 
					 | 
				
			||||||
	// it may be easier to add broadcast to the tunnel
 | 
					 | 
				
			||||||
	c, err := t.tunnel.Dial(ctx, topic, tunnel.DialMode(tunnel.Multicast))
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	defer c.Close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return c.Send(&transport.Message{
 | 
					 | 
				
			||||||
		Header: m.Header,
 | 
					 | 
				
			||||||
		Body:   m.Body,
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (t *tunBroker) BatchSubscribe(ctx context.Context, topic string, h broker.BatchHandler, opts ...broker.SubscribeOption) (broker.Subscriber, error) {
 | 
					 | 
				
			||||||
	l, err := t.tunnel.Listen(ctx, topic, tunnel.ListenMode(tunnel.Multicast))
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	tunSub := &tunBatchSubscriber{
 | 
					 | 
				
			||||||
		topic:    topic,
 | 
					 | 
				
			||||||
		handler:  h,
 | 
					 | 
				
			||||||
		opts:     broker.NewSubscribeOptions(opts...),
 | 
					 | 
				
			||||||
		closed:   make(chan bool),
 | 
					 | 
				
			||||||
		listener: l,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// start processing
 | 
					 | 
				
			||||||
	go tunSub.run()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return tunSub, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (t *tunBroker) Subscribe(ctx context.Context, topic string, h broker.Handler, opts ...broker.SubscribeOption) (broker.Subscriber, error) {
 | 
					 | 
				
			||||||
	l, err := t.tunnel.Listen(ctx, topic, tunnel.ListenMode(tunnel.Multicast))
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	tunSub := &tunSubscriber{
 | 
					 | 
				
			||||||
		topic:    topic,
 | 
					 | 
				
			||||||
		handler:  h,
 | 
					 | 
				
			||||||
		opts:     broker.NewSubscribeOptions(opts...),
 | 
					 | 
				
			||||||
		closed:   make(chan bool),
 | 
					 | 
				
			||||||
		listener: l,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// start processing
 | 
					 | 
				
			||||||
	go tunSub.run()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return tunSub, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (t *tunBroker) String() string {
 | 
					 | 
				
			||||||
	return "tunnel"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (t *tunBatchSubscriber) run() {
 | 
					 | 
				
			||||||
	for {
 | 
					 | 
				
			||||||
		// accept a new connection
 | 
					 | 
				
			||||||
		c, err := t.listener.Accept()
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			select {
 | 
					 | 
				
			||||||
			case <-t.closed:
 | 
					 | 
				
			||||||
				return
 | 
					 | 
				
			||||||
			default:
 | 
					 | 
				
			||||||
				continue
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// receive message
 | 
					 | 
				
			||||||
		m := new(transport.Message)
 | 
					 | 
				
			||||||
		if err := c.Recv(m); err != nil {
 | 
					 | 
				
			||||||
			if logger.V(logger.ErrorLevel) {
 | 
					 | 
				
			||||||
				logger.Error(t.opts.Context, err.Error())
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if err = c.Close(); err != nil {
 | 
					 | 
				
			||||||
				if logger.V(logger.ErrorLevel) {
 | 
					 | 
				
			||||||
					logger.Error(t.opts.Context, err.Error())
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// close the connection
 | 
					 | 
				
			||||||
		c.Close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		evts := broker.Events{&tunEvent{
 | 
					 | 
				
			||||||
			topic: t.topic,
 | 
					 | 
				
			||||||
			message: &broker.Message{
 | 
					 | 
				
			||||||
				Header: m.Header,
 | 
					 | 
				
			||||||
				Body:   m.Body,
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		}}
 | 
					 | 
				
			||||||
		// handle the message
 | 
					 | 
				
			||||||
		go func() {
 | 
					 | 
				
			||||||
			_ = t.handler(evts)
 | 
					 | 
				
			||||||
		}()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (t *tunSubscriber) run() {
 | 
					 | 
				
			||||||
	for {
 | 
					 | 
				
			||||||
		// accept a new connection
 | 
					 | 
				
			||||||
		c, err := t.listener.Accept()
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			select {
 | 
					 | 
				
			||||||
			case <-t.closed:
 | 
					 | 
				
			||||||
				return
 | 
					 | 
				
			||||||
			default:
 | 
					 | 
				
			||||||
				continue
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// receive message
 | 
					 | 
				
			||||||
		m := new(transport.Message)
 | 
					 | 
				
			||||||
		if err := c.Recv(m); err != nil {
 | 
					 | 
				
			||||||
			if logger.V(logger.ErrorLevel) {
 | 
					 | 
				
			||||||
				logger.Error(t.opts.Context, err.Error())
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if err = c.Close(); err != nil {
 | 
					 | 
				
			||||||
				if logger.V(logger.ErrorLevel) {
 | 
					 | 
				
			||||||
					logger.Error(t.opts.Context, err.Error())
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// close the connection
 | 
					 | 
				
			||||||
		c.Close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// handle the message
 | 
					 | 
				
			||||||
		go func() {
 | 
					 | 
				
			||||||
			_ = t.handler(&tunEvent{
 | 
					 | 
				
			||||||
				topic: t.topic,
 | 
					 | 
				
			||||||
				message: &broker.Message{
 | 
					 | 
				
			||||||
					Header: m.Header,
 | 
					 | 
				
			||||||
					Body:   m.Body,
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			})
 | 
					 | 
				
			||||||
		}()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (t *tunBatchSubscriber) Options() broker.SubscribeOptions {
 | 
					 | 
				
			||||||
	return t.opts
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (t *tunBatchSubscriber) Topic() string {
 | 
					 | 
				
			||||||
	return t.topic
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (t *tunBatchSubscriber) Unsubscribe(ctx context.Context) error {
 | 
					 | 
				
			||||||
	select {
 | 
					 | 
				
			||||||
	case <-t.closed:
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		close(t.closed)
 | 
					 | 
				
			||||||
		return t.listener.Close()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (t *tunSubscriber) Options() broker.SubscribeOptions {
 | 
					 | 
				
			||||||
	return t.opts
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (t *tunSubscriber) Topic() string {
 | 
					 | 
				
			||||||
	return t.topic
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (t *tunSubscriber) Unsubscribe(ctx context.Context) error {
 | 
					 | 
				
			||||||
	select {
 | 
					 | 
				
			||||||
	case <-t.closed:
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		close(t.closed)
 | 
					 | 
				
			||||||
		return t.listener.Close()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (t *tunEvent) Topic() string {
 | 
					 | 
				
			||||||
	return t.topic
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (t *tunEvent) Message() *broker.Message {
 | 
					 | 
				
			||||||
	return t.message
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (t *tunEvent) Ack() error {
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (t *tunEvent) Error() error {
 | 
					 | 
				
			||||||
	return t.err
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (t *tunEvent) SetError(err error) {
 | 
					 | 
				
			||||||
	t.err = err
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// NewBroker returns new tunnel broker
 | 
					 | 
				
			||||||
func NewBroker(opts ...broker.Option) (broker.Broker, error) {
 | 
					 | 
				
			||||||
	options := broker.NewOptions(opts...)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	t, ok := options.Context.Value(tunnelKey{}).(tunnel.Tunnel)
 | 
					 | 
				
			||||||
	if !ok {
 | 
					 | 
				
			||||||
		return nil, fmt.Errorf("tunnel not set")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	a, ok := options.Context.Value(tunnelAddr{}).(string)
 | 
					 | 
				
			||||||
	if ok {
 | 
					 | 
				
			||||||
		// initialise address
 | 
					 | 
				
			||||||
		if err := t.Init(tunnel.Address(a)); err != nil {
 | 
					 | 
				
			||||||
			return nil, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if len(options.Addrs) > 0 {
 | 
					 | 
				
			||||||
		// initialise nodes
 | 
					 | 
				
			||||||
		if err := t.Init(tunnel.Nodes(options.Addrs...)); err != nil {
 | 
					 | 
				
			||||||
			return nil, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return &tunBroker{
 | 
					 | 
				
			||||||
		opts:   options,
 | 
					 | 
				
			||||||
		tunnel: t,
 | 
					 | 
				
			||||||
	}, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// WithAddress sets the tunnel address
 | 
					 | 
				
			||||||
func WithAddress(a string) broker.Option {
 | 
					 | 
				
			||||||
	return func(o *broker.Options) {
 | 
					 | 
				
			||||||
		if o.Context == nil {
 | 
					 | 
				
			||||||
			o.Context = context.Background()
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		o.Context = context.WithValue(o.Context, tunnelAddr{}, a)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// WithTunnel sets the internal tunnel
 | 
					 | 
				
			||||||
func WithTunnel(t tunnel.Tunnel) broker.Option {
 | 
					 | 
				
			||||||
	return func(o *broker.Options) {
 | 
					 | 
				
			||||||
		if o.Context == nil {
 | 
					 | 
				
			||||||
			o.Context = context.Background()
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		o.Context = context.WithValue(o.Context, tunnelKey{}, t)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,192 +0,0 @@
 | 
				
			|||||||
package tunnel
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"go.unistack.org/micro/v3/logger"
 | 
					 | 
				
			||||||
	"go.unistack.org/micro/v3/meter"
 | 
					 | 
				
			||||||
	"go.unistack.org/micro/v3/network/transport"
 | 
					 | 
				
			||||||
	"go.unistack.org/micro/v3/tracer"
 | 
					 | 
				
			||||||
	"go.unistack.org/micro/v3/util/id"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var (
 | 
					 | 
				
			||||||
	// DefaultAddress is default tunnel bind address
 | 
					 | 
				
			||||||
	DefaultAddress = ":0"
 | 
					 | 
				
			||||||
	// DefaultToken the shared default token
 | 
					 | 
				
			||||||
	DefaultToken = "go.micro.tunnel"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Option func signature
 | 
					 | 
				
			||||||
type Option func(*Options)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Options provides network configuration options
 | 
					 | 
				
			||||||
type Options struct {
 | 
					 | 
				
			||||||
	// Logger used for logging
 | 
					 | 
				
			||||||
	Logger logger.Logger
 | 
					 | 
				
			||||||
	// Meter used for metrics
 | 
					 | 
				
			||||||
	Meter meter.Meter
 | 
					 | 
				
			||||||
	// Tracer used for tracing
 | 
					 | 
				
			||||||
	Tracer tracer.Tracer
 | 
					 | 
				
			||||||
	// Transport used for communication
 | 
					 | 
				
			||||||
	Transport transport.Transport
 | 
					 | 
				
			||||||
	// Token the shared auth token
 | 
					 | 
				
			||||||
	Token string
 | 
					 | 
				
			||||||
	// Name holds the tunnel name
 | 
					 | 
				
			||||||
	Name string
 | 
					 | 
				
			||||||
	// ID holds the tunnel id
 | 
					 | 
				
			||||||
	ID string
 | 
					 | 
				
			||||||
	// Address holds the tunnel address
 | 
					 | 
				
			||||||
	Address string
 | 
					 | 
				
			||||||
	// Nodes holds the tunnel nodes
 | 
					 | 
				
			||||||
	Nodes []string
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// DialOption func
 | 
					 | 
				
			||||||
type DialOption func(*DialOptions)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// DialOptions provides dial options
 | 
					 | 
				
			||||||
type DialOptions struct {
 | 
					 | 
				
			||||||
	// Link specifies the link to use
 | 
					 | 
				
			||||||
	Link string
 | 
					 | 
				
			||||||
	// specify mode of the session
 | 
					 | 
				
			||||||
	Mode Mode
 | 
					 | 
				
			||||||
	// Wait for connection to be accepted
 | 
					 | 
				
			||||||
	Wait bool
 | 
					 | 
				
			||||||
	// the dial timeout
 | 
					 | 
				
			||||||
	Timeout time.Duration
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ListenOption func
 | 
					 | 
				
			||||||
type ListenOption func(*ListenOptions)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ListenOptions provides listen options
 | 
					 | 
				
			||||||
type ListenOptions struct {
 | 
					 | 
				
			||||||
	// Mode specify mode of the session
 | 
					 | 
				
			||||||
	Mode Mode
 | 
					 | 
				
			||||||
	// Timeout the read timeout
 | 
					 | 
				
			||||||
	Timeout time.Duration
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ID sets the tunnel id
 | 
					 | 
				
			||||||
func ID(id string) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.ID = id
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Logger sets the logger
 | 
					 | 
				
			||||||
func Logger(l logger.Logger) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Logger = l
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Meter sets the meter
 | 
					 | 
				
			||||||
func Meter(m meter.Meter) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Meter = m
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Address sets the tunnel address
 | 
					 | 
				
			||||||
func Address(a string) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Address = a
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Nodes specify remote network nodes
 | 
					 | 
				
			||||||
func Nodes(n ...string) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Nodes = n
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Token sets the shared token for auth
 | 
					 | 
				
			||||||
func Token(t string) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Token = t
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Transport listens for incoming connections
 | 
					 | 
				
			||||||
func Transport(t transport.Transport) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Transport = t
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ListenMode option
 | 
					 | 
				
			||||||
func ListenMode(m Mode) ListenOption {
 | 
					 | 
				
			||||||
	return func(o *ListenOptions) {
 | 
					 | 
				
			||||||
		o.Mode = m
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ListenTimeout for reads and writes on the listener session
 | 
					 | 
				
			||||||
func ListenTimeout(t time.Duration) ListenOption {
 | 
					 | 
				
			||||||
	return func(o *ListenOptions) {
 | 
					 | 
				
			||||||
		o.Timeout = t
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// DialMode multicast sets the multicast option to send only to those mapped
 | 
					 | 
				
			||||||
func DialMode(m Mode) DialOption {
 | 
					 | 
				
			||||||
	return func(o *DialOptions) {
 | 
					 | 
				
			||||||
		o.Mode = m
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// DialTimeout sets the dial timeout of the connection
 | 
					 | 
				
			||||||
func DialTimeout(t time.Duration) DialOption {
 | 
					 | 
				
			||||||
	return func(o *DialOptions) {
 | 
					 | 
				
			||||||
		o.Timeout = t
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// DialLink specifies the link to pin this connection to.
 | 
					 | 
				
			||||||
// This is not applicable if the multicast option is set.
 | 
					 | 
				
			||||||
func DialLink(id string) DialOption {
 | 
					 | 
				
			||||||
	return func(o *DialOptions) {
 | 
					 | 
				
			||||||
		o.Link = id
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// DialWait specifies whether to wait for the connection
 | 
					 | 
				
			||||||
// to be accepted before returning the session
 | 
					 | 
				
			||||||
func DialWait(b bool) DialOption {
 | 
					 | 
				
			||||||
	return func(o *DialOptions) {
 | 
					 | 
				
			||||||
		o.Wait = b
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// NewOptions returns router default options with filled values
 | 
					 | 
				
			||||||
func NewOptions(opts ...Option) Options {
 | 
					 | 
				
			||||||
	options := Options{
 | 
					 | 
				
			||||||
		ID:      id.Must(),
 | 
					 | 
				
			||||||
		Address: DefaultAddress,
 | 
					 | 
				
			||||||
		Token:   DefaultToken,
 | 
					 | 
				
			||||||
		Logger:  logger.DefaultLogger,
 | 
					 | 
				
			||||||
		Meter:   meter.DefaultMeter,
 | 
					 | 
				
			||||||
		Tracer:  tracer.DefaultTracer,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for _, o := range opts {
 | 
					 | 
				
			||||||
		o(&options)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return options
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Tracer to be used for tracing
 | 
					 | 
				
			||||||
func Tracer(t tracer.Tracer) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Tracer = t
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Name sets the name
 | 
					 | 
				
			||||||
func Name(n string) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Name = n
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,30 +0,0 @@
 | 
				
			|||||||
package transport
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"go.unistack.org/micro/v3/network/transport"
 | 
					 | 
				
			||||||
	"go.unistack.org/micro/v3/network/tunnel"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type tunListener struct {
 | 
					 | 
				
			||||||
	l tunnel.Listener
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (t *tunListener) Addr() string {
 | 
					 | 
				
			||||||
	return t.l.Channel()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (t *tunListener) Close() error {
 | 
					 | 
				
			||||||
	return t.l.Close()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (t *tunListener) Accept(fn func(socket transport.Socket)) error {
 | 
					 | 
				
			||||||
	for {
 | 
					 | 
				
			||||||
		// accept connection
 | 
					 | 
				
			||||||
		c, err := t.l.Accept()
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		// execute the function
 | 
					 | 
				
			||||||
		go fn(c)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,113 +0,0 @@
 | 
				
			|||||||
// Package transport provides a tunnel transport
 | 
					 | 
				
			||||||
package transport // import "go.unistack.org/micro/v3/network/tunnel/transport"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"context"
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"go.unistack.org/micro/v3/network/transport"
 | 
					 | 
				
			||||||
	"go.unistack.org/micro/v3/network/tunnel"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type tunTransport struct {
 | 
					 | 
				
			||||||
	tunnel  tunnel.Tunnel
 | 
					 | 
				
			||||||
	options transport.Options
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type tunnelKey struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type transportKey struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (t *tunTransport) Init(opts ...transport.Option) error {
 | 
					 | 
				
			||||||
	for _, o := range opts {
 | 
					 | 
				
			||||||
		o(&t.options)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// close the existing tunnel
 | 
					 | 
				
			||||||
	if t.tunnel != nil {
 | 
					 | 
				
			||||||
		t.tunnel.Close(context.TODO())
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// get the tunnel
 | 
					 | 
				
			||||||
	tun, ok := t.options.Context.Value(tunnelKey{}).(tunnel.Tunnel)
 | 
					 | 
				
			||||||
	if !ok {
 | 
					 | 
				
			||||||
		return fmt.Errorf("tunnel not set")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// get the transport
 | 
					 | 
				
			||||||
	tr, ok := t.options.Context.Value(transportKey{}).(transport.Transport)
 | 
					 | 
				
			||||||
	if ok {
 | 
					 | 
				
			||||||
		_ = tun.Init(tunnel.Transport(tr))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// set the tunnel
 | 
					 | 
				
			||||||
	t.tunnel = tun
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (t *tunTransport) Dial(ctx context.Context, addr string, opts ...transport.DialOption) (transport.Client, error) {
 | 
					 | 
				
			||||||
	if err := t.tunnel.Connect(ctx); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	c, err := t.tunnel.Dial(ctx, addr)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return c, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (t *tunTransport) Listen(ctx context.Context, addr string, opts ...transport.ListenOption) (transport.Listener, error) {
 | 
					 | 
				
			||||||
	if err := t.tunnel.Connect(ctx); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	l, err := t.tunnel.Listen(ctx, addr)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return &tunListener{l}, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (t *tunTransport) Options() transport.Options {
 | 
					 | 
				
			||||||
	return t.options
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (t *tunTransport) String() string {
 | 
					 | 
				
			||||||
	return "tunnel"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// NewTransport honours the initialiser used in
 | 
					 | 
				
			||||||
func NewTransport(opts ...transport.Option) transport.Transport {
 | 
					 | 
				
			||||||
	t := &tunTransport{
 | 
					 | 
				
			||||||
		options: transport.Options{},
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// initialise
 | 
					 | 
				
			||||||
	// t.Init(opts...)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return t
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// WithTunnel sets the internal tunnel
 | 
					 | 
				
			||||||
func WithTunnel(t tunnel.Tunnel) transport.Option {
 | 
					 | 
				
			||||||
	return func(o *transport.Options) {
 | 
					 | 
				
			||||||
		if o.Context == nil {
 | 
					 | 
				
			||||||
			o.Context = context.Background()
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		o.Context = context.WithValue(o.Context, tunnelKey{}, t)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// WithTransport sets the internal transport
 | 
					 | 
				
			||||||
func WithTransport(t transport.Transport) transport.Option {
 | 
					 | 
				
			||||||
	return func(o *transport.Options) {
 | 
					 | 
				
			||||||
		if o.Context == nil {
 | 
					 | 
				
			||||||
			o.Context = context.Background()
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		o.Context = context.WithValue(o.Context, transportKey{}, t)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,106 +0,0 @@
 | 
				
			|||||||
// Package tunnel provides gre network tunnelling
 | 
					 | 
				
			||||||
package tunnel // import "go.unistack.org/micro/v3/network/transport/tunnel"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"context"
 | 
					 | 
				
			||||||
	"errors"
 | 
					 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"go.unistack.org/micro/v3/network/transport"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// DefaultTunnel contains default tunnel implementation
 | 
					 | 
				
			||||||
var DefaultTunnel Tunnel
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const (
 | 
					 | 
				
			||||||
	// Unicast send over one link
 | 
					 | 
				
			||||||
	Unicast Mode = iota
 | 
					 | 
				
			||||||
	// Multicast send to all channel listeners
 | 
					 | 
				
			||||||
	Multicast
 | 
					 | 
				
			||||||
	// Broadcast send to all links
 | 
					 | 
				
			||||||
	Broadcast
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var (
 | 
					 | 
				
			||||||
	// DefaultDialTimeout is the dial timeout if none is specified
 | 
					 | 
				
			||||||
	DefaultDialTimeout = time.Second * 5
 | 
					 | 
				
			||||||
	// ErrDialTimeout is returned by a call to Dial where the timeout occurs
 | 
					 | 
				
			||||||
	ErrDialTimeout = errors.New("dial timeout")
 | 
					 | 
				
			||||||
	// ErrDiscoverChan is returned when we failed to receive the "announce" back from a discovery
 | 
					 | 
				
			||||||
	ErrDiscoverChan = errors.New("failed to discover channel")
 | 
					 | 
				
			||||||
	// ErrLinkNotFound is returned when a link is specified at dial time and does not exist
 | 
					 | 
				
			||||||
	ErrLinkNotFound = errors.New("link not found")
 | 
					 | 
				
			||||||
	// ErrLinkDisconnected is returned when a link we attempt to send to is disconnected
 | 
					 | 
				
			||||||
	ErrLinkDisconnected = errors.New("link not connected")
 | 
					 | 
				
			||||||
	// ErrLinkLoopback is returned when attempting to send an outbound message over loopback link
 | 
					 | 
				
			||||||
	ErrLinkLoopback = errors.New("link is loopback")
 | 
					 | 
				
			||||||
	// ErrLinkRemote is returned when attempting to send a loopback message over remote link
 | 
					 | 
				
			||||||
	ErrLinkRemote = errors.New("link is remote")
 | 
					 | 
				
			||||||
	// ErrReadTimeout is a timeout on session.Recv
 | 
					 | 
				
			||||||
	ErrReadTimeout = errors.New("read timeout")
 | 
					 | 
				
			||||||
	// ErrDecryptingData is for when theres a nonce error
 | 
					 | 
				
			||||||
	ErrDecryptingData = errors.New("error decrypting data")
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Mode of the session
 | 
					 | 
				
			||||||
type Mode uint8
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Tunnel creates a gre tunnel on top of the micro/transport.
 | 
					 | 
				
			||||||
// It establishes multiple streams using the Micro-Tunnel-Channel header
 | 
					 | 
				
			||||||
// and Micro-Tunnel-Session header. The tunnel id is a hash of
 | 
					 | 
				
			||||||
// the address being requested.
 | 
					 | 
				
			||||||
type Tunnel interface {
 | 
					 | 
				
			||||||
	// Init initializes tunnel with options
 | 
					 | 
				
			||||||
	Init(opts ...Option) error
 | 
					 | 
				
			||||||
	// Address returns the address the tunnel is listening on
 | 
					 | 
				
			||||||
	Address() string
 | 
					 | 
				
			||||||
	// Connect connects the tunnel
 | 
					 | 
				
			||||||
	Connect(ctx context.Context) error
 | 
					 | 
				
			||||||
	// Close closes the tunnel
 | 
					 | 
				
			||||||
	Close(ctx context.Context) error
 | 
					 | 
				
			||||||
	// Links returns all the links the tunnel is connected to
 | 
					 | 
				
			||||||
	Links() []Link
 | 
					 | 
				
			||||||
	// Dial allows a client to connect to a channel
 | 
					 | 
				
			||||||
	Dial(ctx context.Context, channel string, opts ...DialOption) (Session, error)
 | 
					 | 
				
			||||||
	// Listen allows to accept connections on a channel
 | 
					 | 
				
			||||||
	Listen(ctx context.Context, channel string, opts ...ListenOption) (Listener, error)
 | 
					 | 
				
			||||||
	// String returns the name of the tunnel implementation
 | 
					 | 
				
			||||||
	String() string
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Link represents internal links to the tunnel
 | 
					 | 
				
			||||||
type Link interface {
 | 
					 | 
				
			||||||
	// Id returns the link unique Id
 | 
					 | 
				
			||||||
	Id() string
 | 
					 | 
				
			||||||
	// Delay is the current load on the link (lower is better)
 | 
					 | 
				
			||||||
	Delay() int64
 | 
					 | 
				
			||||||
	// Length returns the roundtrip time as nanoseconds (lower is better)
 | 
					 | 
				
			||||||
	Length() int64
 | 
					 | 
				
			||||||
	// Current transfer rate as bits per second (lower is better)
 | 
					 | 
				
			||||||
	Rate() float64
 | 
					 | 
				
			||||||
	// Is this a loopback link
 | 
					 | 
				
			||||||
	Loopback() bool
 | 
					 | 
				
			||||||
	// State of the link: connected/closed/error
 | 
					 | 
				
			||||||
	State() string
 | 
					 | 
				
			||||||
	// honours transport socket
 | 
					 | 
				
			||||||
	transport.Socket
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Listener provides similar constructs to the transport.Listener
 | 
					 | 
				
			||||||
type Listener interface {
 | 
					 | 
				
			||||||
	Accept() (Session, error)
 | 
					 | 
				
			||||||
	Channel() string
 | 
					 | 
				
			||||||
	Close() error
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Session is a unique session created when dialling or accepting connections on the tunnel
 | 
					 | 
				
			||||||
type Session interface {
 | 
					 | 
				
			||||||
	// The unique session id
 | 
					 | 
				
			||||||
	Id() string
 | 
					 | 
				
			||||||
	// The channel name
 | 
					 | 
				
			||||||
	Channel() string
 | 
					 | 
				
			||||||
	// The link the session is on
 | 
					 | 
				
			||||||
	Link() string
 | 
					 | 
				
			||||||
	// a transport socket
 | 
					 | 
				
			||||||
	transport.Socket
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										79
									
								
								options.go
									
									
									
									
									
								
							
							
						
						
									
										79
									
								
								options.go
									
									
									
									
									
								
							@@ -5,17 +5,18 @@ import (
 | 
				
			|||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro/v3/broker"
 | 
						"go.unistack.org/micro/v4/broker"
 | 
				
			||||||
	"go.unistack.org/micro/v3/client"
 | 
						"go.unistack.org/micro/v4/client"
 | 
				
			||||||
	"go.unistack.org/micro/v3/config"
 | 
						"go.unistack.org/micro/v4/config"
 | 
				
			||||||
	"go.unistack.org/micro/v3/logger"
 | 
						"go.unistack.org/micro/v4/logger"
 | 
				
			||||||
	"go.unistack.org/micro/v3/metadata"
 | 
						"go.unistack.org/micro/v4/metadata"
 | 
				
			||||||
	"go.unistack.org/micro/v3/meter"
 | 
						"go.unistack.org/micro/v4/meter"
 | 
				
			||||||
	"go.unistack.org/micro/v3/register"
 | 
						"go.unistack.org/micro/v4/options"
 | 
				
			||||||
	"go.unistack.org/micro/v3/router"
 | 
						"go.unistack.org/micro/v4/register"
 | 
				
			||||||
	"go.unistack.org/micro/v3/server"
 | 
						"go.unistack.org/micro/v4/router"
 | 
				
			||||||
	"go.unistack.org/micro/v3/store"
 | 
						"go.unistack.org/micro/v4/server"
 | 
				
			||||||
	"go.unistack.org/micro/v3/tracer"
 | 
						"go.unistack.org/micro/v4/store"
 | 
				
			||||||
 | 
						"go.unistack.org/micro/v4/tracer"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Options for micro service
 | 
					// Options for micro service
 | 
				
			||||||
@@ -90,33 +91,7 @@ type Option func(*Options) error
 | 
				
			|||||||
// Broker to be used for client and server
 | 
					// Broker to be used for client and server
 | 
				
			||||||
func Broker(b broker.Broker, opts ...BrokerOption) Option {
 | 
					func Broker(b broker.Broker, opts ...BrokerOption) Option {
 | 
				
			||||||
	return func(o *Options) error {
 | 
						return func(o *Options) error {
 | 
				
			||||||
		var err error
 | 
							o.Brokers = []broker.Broker{b}
 | 
				
			||||||
		bopts := brokerOptions{}
 | 
					 | 
				
			||||||
		for _, opt := range opts {
 | 
					 | 
				
			||||||
			opt(&bopts)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		all := false
 | 
					 | 
				
			||||||
		if len(opts) == 0 {
 | 
					 | 
				
			||||||
			all = true
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		for _, srv := range o.Servers {
 | 
					 | 
				
			||||||
			for _, os := range bopts.servers {
 | 
					 | 
				
			||||||
				if srv.Name() == os || all {
 | 
					 | 
				
			||||||
					if err = srv.Init(server.Broker(b)); err != nil {
 | 
					 | 
				
			||||||
						return err
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		for _, cli := range o.Clients {
 | 
					 | 
				
			||||||
			for _, oc := range bopts.clients {
 | 
					 | 
				
			||||||
				if cli.Name() == oc || all {
 | 
					 | 
				
			||||||
					if err = cli.Init(client.Broker(b)); err != nil {
 | 
					 | 
				
			||||||
						return err
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -227,7 +202,7 @@ func Logger(l logger.Logger, opts ...LoggerOption) Option {
 | 
				
			|||||||
		for _, srv := range o.Servers {
 | 
							for _, srv := range o.Servers {
 | 
				
			||||||
			for _, os := range lopts.servers {
 | 
								for _, os := range lopts.servers {
 | 
				
			||||||
				if srv.Name() == os || all {
 | 
									if srv.Name() == os || all {
 | 
				
			||||||
					if err = srv.Init(server.Logger(l)); err != nil {
 | 
										if err = srv.Init(options.Logger(l)); err != nil {
 | 
				
			||||||
						return err
 | 
											return err
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
@@ -236,7 +211,7 @@ func Logger(l logger.Logger, opts ...LoggerOption) Option {
 | 
				
			|||||||
		for _, cli := range o.Clients {
 | 
							for _, cli := range o.Clients {
 | 
				
			||||||
			for _, oc := range lopts.clients {
 | 
								for _, oc := range lopts.clients {
 | 
				
			||||||
				if cli.Name() == oc || all {
 | 
									if cli.Name() == oc || all {
 | 
				
			||||||
					if err = cli.Init(client.Logger(l)); err != nil {
 | 
										if err = cli.Init(options.Logger(l)); err != nil {
 | 
				
			||||||
						return err
 | 
											return err
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
@@ -245,7 +220,7 @@ func Logger(l logger.Logger, opts ...LoggerOption) Option {
 | 
				
			|||||||
		for _, brk := range o.Brokers {
 | 
							for _, brk := range o.Brokers {
 | 
				
			||||||
			for _, ob := range lopts.brokers {
 | 
								for _, ob := range lopts.brokers {
 | 
				
			||||||
				if brk.Name() == ob || all {
 | 
									if brk.Name() == ob || all {
 | 
				
			||||||
					if err = brk.Init(broker.Logger(l)); err != nil {
 | 
										if err = brk.Init(options.Logger(l)); err != nil {
 | 
				
			||||||
						return err
 | 
											return err
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
@@ -263,7 +238,7 @@ func Logger(l logger.Logger, opts ...LoggerOption) Option {
 | 
				
			|||||||
		for _, str := range o.Stores {
 | 
							for _, str := range o.Stores {
 | 
				
			||||||
			for _, or := range lopts.stores {
 | 
								for _, or := range lopts.stores {
 | 
				
			||||||
				if str.Name() == or || all {
 | 
									if str.Name() == or || all {
 | 
				
			||||||
					if err = str.Init(store.Logger(l)); err != nil {
 | 
										if err = str.Init(options.Logger(l)); err != nil {
 | 
				
			||||||
						return err
 | 
											return err
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
@@ -272,7 +247,7 @@ func Logger(l logger.Logger, opts ...LoggerOption) Option {
 | 
				
			|||||||
		for _, mtr := range o.Meters {
 | 
							for _, mtr := range o.Meters {
 | 
				
			||||||
			for _, or := range lopts.meters {
 | 
								for _, or := range lopts.meters {
 | 
				
			||||||
				if mtr.Name() == or || all {
 | 
									if mtr.Name() == or || all {
 | 
				
			||||||
					if err = mtr.Init(meter.Logger(l)); err != nil {
 | 
										if err = mtr.Init(options.Logger(l)); err != nil {
 | 
				
			||||||
						return err
 | 
											return err
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
@@ -281,7 +256,7 @@ func Logger(l logger.Logger, opts ...LoggerOption) Option {
 | 
				
			|||||||
		for _, trc := range o.Tracers {
 | 
							for _, trc := range o.Tracers {
 | 
				
			||||||
			for _, ot := range lopts.tracers {
 | 
								for _, ot := range lopts.tracers {
 | 
				
			||||||
				if trc.Name() == ot || all {
 | 
									if trc.Name() == ot || all {
 | 
				
			||||||
					if err = trc.Init(tracer.Logger(l)); err != nil {
 | 
										if err = trc.Init(options.Logger(l)); err != nil {
 | 
				
			||||||
						return err
 | 
											return err
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
@@ -355,7 +330,7 @@ func Register(r register.Register, opts ...RegisterOption) Option {
 | 
				
			|||||||
		for _, srv := range o.Servers {
 | 
							for _, srv := range o.Servers {
 | 
				
			||||||
			for _, os := range ropts.servers {
 | 
								for _, os := range ropts.servers {
 | 
				
			||||||
				if srv.Name() == os || all {
 | 
									if srv.Name() == os || all {
 | 
				
			||||||
					if err = srv.Init(server.Register(r)); err != nil {
 | 
										if err = srv.Init(options.Register(r)); err != nil {
 | 
				
			||||||
						return err
 | 
											return err
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
@@ -364,7 +339,7 @@ func Register(r register.Register, opts ...RegisterOption) Option {
 | 
				
			|||||||
		for _, brk := range o.Brokers {
 | 
							for _, brk := range o.Brokers {
 | 
				
			||||||
			for _, os := range ropts.brokers {
 | 
								for _, os := range ropts.brokers {
 | 
				
			||||||
				if brk.Name() == os || all {
 | 
									if brk.Name() == os || all {
 | 
				
			||||||
					if err = brk.Init(broker.Register(r)); err != nil {
 | 
										if err = brk.Init(options.Register(r)); err != nil {
 | 
				
			||||||
						return err
 | 
											return err
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
@@ -421,7 +396,7 @@ func Tracer(t tracer.Tracer, opts ...TracerOption) Option {
 | 
				
			|||||||
		for _, srv := range o.Servers {
 | 
							for _, srv := range o.Servers {
 | 
				
			||||||
			for _, os := range topts.servers {
 | 
								for _, os := range topts.servers {
 | 
				
			||||||
				if srv.Name() == os || all {
 | 
									if srv.Name() == os || all {
 | 
				
			||||||
					if err = srv.Init(server.Tracer(t)); err != nil {
 | 
										if err = srv.Init(options.Tracer(t)); err != nil {
 | 
				
			||||||
						return err
 | 
											return err
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
@@ -430,7 +405,7 @@ func Tracer(t tracer.Tracer, opts ...TracerOption) Option {
 | 
				
			|||||||
		for _, cli := range o.Clients {
 | 
							for _, cli := range o.Clients {
 | 
				
			||||||
			for _, os := range topts.clients {
 | 
								for _, os := range topts.clients {
 | 
				
			||||||
				if cli.Name() == os || all {
 | 
									if cli.Name() == os || all {
 | 
				
			||||||
					if err = cli.Init(client.Tracer(t)); err != nil {
 | 
										if err = cli.Init(options.Tracer(t)); err != nil {
 | 
				
			||||||
						return err
 | 
											return err
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
@@ -439,7 +414,7 @@ func Tracer(t tracer.Tracer, opts ...TracerOption) Option {
 | 
				
			|||||||
		for _, str := range o.Stores {
 | 
							for _, str := range o.Stores {
 | 
				
			||||||
			for _, os := range topts.stores {
 | 
								for _, os := range topts.stores {
 | 
				
			||||||
				if str.Name() == os || all {
 | 
									if str.Name() == os || all {
 | 
				
			||||||
					if err = str.Init(store.Tracer(t)); err != nil {
 | 
										if err = str.Init(options.Tracer(t)); err != nil {
 | 
				
			||||||
						return err
 | 
											return err
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
@@ -448,7 +423,7 @@ func Tracer(t tracer.Tracer, opts ...TracerOption) Option {
 | 
				
			|||||||
		for _, brk := range o.Brokers {
 | 
							for _, brk := range o.Brokers {
 | 
				
			||||||
			for _, os := range topts.brokers {
 | 
								for _, os := range topts.brokers {
 | 
				
			||||||
				if brk.Name() == os || all {
 | 
									if brk.Name() == os || all {
 | 
				
			||||||
					if err = brk.Init(broker.Tracer(t)); err != nil {
 | 
										if err = brk.Init(options.Tracer(t)); err != nil {
 | 
				
			||||||
						return err
 | 
											return err
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
@@ -547,7 +522,7 @@ func Router(r router.Router, opts ...RouterOption) Option {
 | 
				
			|||||||
		for _, cli := range o.Clients {
 | 
							for _, cli := range o.Clients {
 | 
				
			||||||
			for _, os := range ropts.clients {
 | 
								for _, os := range ropts.clients {
 | 
				
			||||||
				if cli.Name() == os || all {
 | 
									if cli.Name() == os || all {
 | 
				
			||||||
					if err = cli.Init(client.Router(r)); err != nil {
 | 
										if err = cli.Init(options.Router(r)); err != nil {
 | 
				
			||||||
						return err
 | 
											return err
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
@@ -582,7 +557,7 @@ func Address(addr string) Option {
 | 
				
			|||||||
		default:
 | 
							default:
 | 
				
			||||||
			return fmt.Errorf("cant set same address for multiple servers")
 | 
								return fmt.Errorf("cant set same address for multiple servers")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return o.Servers[0].Init(server.Address(addr))
 | 
							return o.Servers[0].Init(options.Address(addr))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
package options // import "go.unistack.org/micro/v3/options"
 | 
					package options // import "go.unistack.org/micro/v4/options"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Hook func interface
 | 
					// Hook func interface
 | 
				
			||||||
type Hook interface{}
 | 
					type Hook interface{}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										189
									
								
								options/options.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										189
									
								
								options/options.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,189 @@
 | 
				
			|||||||
 | 
					package options
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"crypto/tls"
 | 
				
			||||||
 | 
						"reflect"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"go.unistack.org/micro/v4/metadata"
 | 
				
			||||||
 | 
						rutil "go.unistack.org/micro/v4/util/reflect"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Option func signature
 | 
				
			||||||
 | 
					type Option func(interface{}) error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Set assign value to struct by its path
 | 
				
			||||||
 | 
					func Set(src interface{}, dst interface{}, path string) error {
 | 
				
			||||||
 | 
						return rutil.SetFieldByPath(src, dst, path)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Get returns value from struct by its path
 | 
				
			||||||
 | 
					func Get(src interface{}, path string) (interface{}, error) {
 | 
				
			||||||
 | 
						return rutil.StructFieldByPath(src, path)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Name set Name value
 | 
				
			||||||
 | 
					func Name(v ...string) Option {
 | 
				
			||||||
 | 
						return func(src interface{}) error {
 | 
				
			||||||
 | 
							return Set(src, v, ".Name")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Address set Address value to single string or slice of strings
 | 
				
			||||||
 | 
					func Address(v ...string) Option {
 | 
				
			||||||
 | 
						return func(src interface{}) error {
 | 
				
			||||||
 | 
							return Set(src, v, ".Address")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Broker set Broker value
 | 
				
			||||||
 | 
					func Broker(v interface{}) Option {
 | 
				
			||||||
 | 
						return func(src interface{}) error {
 | 
				
			||||||
 | 
							return Set(src, v, ".Broker")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Logger set Logger value
 | 
				
			||||||
 | 
					func Logger(v interface{}) Option {
 | 
				
			||||||
 | 
						return func(src interface{}) error {
 | 
				
			||||||
 | 
							return Set(src, v, ".Logger")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Meter set Meter value
 | 
				
			||||||
 | 
					func Meter(v interface{}) Option {
 | 
				
			||||||
 | 
						return func(src interface{}) error {
 | 
				
			||||||
 | 
							return Set(src, v, ".Meter")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Tracer set Tracer value
 | 
				
			||||||
 | 
					func Tracer(v interface{}) Option {
 | 
				
			||||||
 | 
						return func(src interface{}) error {
 | 
				
			||||||
 | 
							return Set(src, v, ".Tracer")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Store set Store value
 | 
				
			||||||
 | 
					func Store(v interface{}) Option {
 | 
				
			||||||
 | 
						return func(src interface{}) error {
 | 
				
			||||||
 | 
							return Set(src, v, ".Store")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Register set Register value
 | 
				
			||||||
 | 
					func Register(v interface{}) Option {
 | 
				
			||||||
 | 
						return func(src interface{}) error {
 | 
				
			||||||
 | 
							return Set(src, v, ".Register")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Router set Router value
 | 
				
			||||||
 | 
					func Router(v interface{}) Option {
 | 
				
			||||||
 | 
						return func(src interface{}) error {
 | 
				
			||||||
 | 
							return Set(src, v, ".Router")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Codec set Codec value
 | 
				
			||||||
 | 
					func Codec(v interface{}) Option {
 | 
				
			||||||
 | 
						return func(src interface{}) error {
 | 
				
			||||||
 | 
							return Set(src, v, ".Codec")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Client set Client value
 | 
				
			||||||
 | 
					func Client(v interface{}) Option {
 | 
				
			||||||
 | 
						return func(src interface{}) error {
 | 
				
			||||||
 | 
							return Set(src, v, ".Client")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Codecs to be used to encode/decode requests for a given content type
 | 
				
			||||||
 | 
					func Codecs(ct string, v interface{}) Option {
 | 
				
			||||||
 | 
						return func(src interface{}) error {
 | 
				
			||||||
 | 
							cm, err := Get(src, ".Codecs")
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							} else if rutil.IsZero(cm) {
 | 
				
			||||||
 | 
								cm = reflect.MakeMap(reflect.TypeOf(cm)).Interface()
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							cv := reflect.ValueOf(cm)
 | 
				
			||||||
 | 
							cv.SetMapIndex(reflect.ValueOf(ct), reflect.ValueOf(v))
 | 
				
			||||||
 | 
							return Set(src, cv.Interface(), ".Codecs")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Context set Context value
 | 
				
			||||||
 | 
					func Context(v context.Context) Option {
 | 
				
			||||||
 | 
						return func(src interface{}) error {
 | 
				
			||||||
 | 
							return Set(src, v, ".Context")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TLSConfig set TLSConfig value
 | 
				
			||||||
 | 
					func TLSConfig(v *tls.Config) Option {
 | 
				
			||||||
 | 
						return func(src interface{}) error {
 | 
				
			||||||
 | 
							return Set(src, v, ".TLSConfig")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ContextOption(k, v interface{}) Option {
 | 
				
			||||||
 | 
						return func(src interface{}) error {
 | 
				
			||||||
 | 
							ctx, err := Get(src, ".Context")
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if ctx == nil {
 | 
				
			||||||
 | 
								ctx = context.Background()
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							err = Set(src, context.WithValue(ctx.(context.Context), k, v), ".Context")
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ContentType pass ContentType for message data
 | 
				
			||||||
 | 
					func ContentType(ct string) Option {
 | 
				
			||||||
 | 
						return func(src interface{}) error {
 | 
				
			||||||
 | 
							return Set(src, ct, ".ContentType")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Metadata pass additional metadata
 | 
				
			||||||
 | 
					func Metadata(md metadata.Metadata) Option {
 | 
				
			||||||
 | 
						return func(src interface{}) error {
 | 
				
			||||||
 | 
							return Set(src, metadata.Copy(md), ".Metadata")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Namespace to use
 | 
				
			||||||
 | 
					func Namespace(ns string) Option {
 | 
				
			||||||
 | 
						return func(src interface{}) error {
 | 
				
			||||||
 | 
							return Set(src, ns, ".Namespace")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Labels sets the labels
 | 
				
			||||||
 | 
					func Labels(ls ...interface{}) Option {
 | 
				
			||||||
 | 
						return func(src interface{}) error {
 | 
				
			||||||
 | 
							v, err := Get(src, ".Labels")
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							} else if rutil.IsZero(v) {
 | 
				
			||||||
 | 
								v = reflect.MakeSlice(reflect.TypeOf(v), 0, len(ls)).Interface()
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							cv := reflect.ValueOf(v)
 | 
				
			||||||
 | 
							for _, l := range ls {
 | 
				
			||||||
 | 
								cv = reflect.Append(cv, reflect.ValueOf(l))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return Set(src, cv.Interface(), ".Labels")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Timeout pass timeout time.Duration
 | 
				
			||||||
 | 
					func Timeout(td time.Duration) Option {
 | 
				
			||||||
 | 
						return func(src interface{}) error {
 | 
				
			||||||
 | 
							return Set(src, td, ".Timeout")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										86
									
								
								options/options_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								options/options_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,86 @@
 | 
				
			|||||||
 | 
					package options_test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"go.unistack.org/micro/v4/codec"
 | 
				
			||||||
 | 
						"go.unistack.org/micro/v4/options"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestAddress(t *testing.T) {
 | 
				
			||||||
 | 
						var err error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						type s struct {
 | 
				
			||||||
 | 
							Address []string
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						src := &s{}
 | 
				
			||||||
 | 
						var opts []options.Option
 | 
				
			||||||
 | 
						opts = append(opts, options.Address("host:port"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, o := range opts {
 | 
				
			||||||
 | 
							if err = o(src); err != nil {
 | 
				
			||||||
 | 
								t.Fatal(err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if src.Address[0] != "host:port" {
 | 
				
			||||||
 | 
							t.Fatal("failed to set Address")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestCodecs(t *testing.T) {
 | 
				
			||||||
 | 
						var err error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						type s struct {
 | 
				
			||||||
 | 
							Codecs map[string]codec.Codec
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						src := &s{}
 | 
				
			||||||
 | 
						var opts []options.Option
 | 
				
			||||||
 | 
						c := codec.NewCodec()
 | 
				
			||||||
 | 
						opts = append(opts, options.Codecs("text/html", c))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, o := range opts {
 | 
				
			||||||
 | 
							if err = o(src); err != nil {
 | 
				
			||||||
 | 
								t.Fatal(err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for k, v := range src.Codecs {
 | 
				
			||||||
 | 
							if k != "text/html" || v != c {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t.Fatalf("failed to set Codecs")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestLabels(t *testing.T) {
 | 
				
			||||||
 | 
						type str1 struct {
 | 
				
			||||||
 | 
							Labels []string
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						type str2 struct {
 | 
				
			||||||
 | 
							Labels []interface{}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						x1 := &str1{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := options.Labels("one", "two")(x1); err != nil {
 | 
				
			||||||
 | 
							t.Fatal(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(x1.Labels) != 2 {
 | 
				
			||||||
 | 
							t.Fatal("failed to set labels")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						x2 := &str2{}
 | 
				
			||||||
 | 
						if err := options.Labels("key", "val")(x2); err != nil {
 | 
				
			||||||
 | 
							t.Fatal(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(x2.Labels) != 2 {
 | 
				
			||||||
 | 
							t.Fatal("failed to set labels")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if x2.Labels[0] != "key" {
 | 
				
			||||||
 | 
							t.Fatal("failed to set labels")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,5 +1,5 @@
 | 
				
			|||||||
// Package http enables the http profiler
 | 
					// Package http enables the http profiler
 | 
				
			||||||
package http // import "go.unistack.org/micro/v3/profiler/http"
 | 
					package http // import "go.unistack.org/micro/v4/profiler/http"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
@@ -7,7 +7,7 @@ import (
 | 
				
			|||||||
	"net/http/pprof"
 | 
						"net/http/pprof"
 | 
				
			||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	profile "go.unistack.org/micro/v3/profiler"
 | 
						profile "go.unistack.org/micro/v4/profiler"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type httpProfile struct {
 | 
					type httpProfile struct {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,5 @@
 | 
				
			|||||||
// Package pprof provides a pprof profiler which writes output to /tmp/[name].{cpu,mem}.pprof
 | 
					// Package pprof provides a pprof profiler which writes output to /tmp/[name].{cpu,mem}.pprof
 | 
				
			||||||
package pprof // import "go.unistack.org/micro/v3/profiler/pprof"
 | 
					package pprof // import "go.unistack.org/micro/v4/profiler/pprof"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
@@ -9,7 +9,7 @@ import (
 | 
				
			|||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	profile "go.unistack.org/micro/v3/profiler"
 | 
						profile "go.unistack.org/micro/v4/profiler"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type profiler struct {
 | 
					type profiler struct {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,5 @@
 | 
				
			|||||||
// Package profiler is for profilers
 | 
					// Package profiler is for profilers
 | 
				
			||||||
package profiler // import "go.unistack.org/micro/v3/profiler"
 | 
					package profiler // import "go.unistack.org/micro/v4/profiler"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Profiler interface
 | 
					// Profiler interface
 | 
				
			||||||
type Profiler interface {
 | 
					type Profiler interface {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,98 +0,0 @@
 | 
				
			|||||||
// Package proxy is a transparent proxy built on the micro/server
 | 
					 | 
				
			||||||
package proxy
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"go.unistack.org/micro/v3/client"
 | 
					 | 
				
			||||||
	"go.unistack.org/micro/v3/logger"
 | 
					 | 
				
			||||||
	"go.unistack.org/micro/v3/meter"
 | 
					 | 
				
			||||||
	"go.unistack.org/micro/v3/router"
 | 
					 | 
				
			||||||
	"go.unistack.org/micro/v3/tracer"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Options for proxy
 | 
					 | 
				
			||||||
type Options struct {
 | 
					 | 
				
			||||||
	// Tracer used for tracing
 | 
					 | 
				
			||||||
	Tracer tracer.Tracer
 | 
					 | 
				
			||||||
	// Client for communication
 | 
					 | 
				
			||||||
	Client client.Client
 | 
					 | 
				
			||||||
	// Router for routing
 | 
					 | 
				
			||||||
	Router router.Router
 | 
					 | 
				
			||||||
	// Logger used for logging
 | 
					 | 
				
			||||||
	Logger logger.Logger
 | 
					 | 
				
			||||||
	// Meter used for metrics
 | 
					 | 
				
			||||||
	Meter meter.Meter
 | 
					 | 
				
			||||||
	// Links holds the communication links
 | 
					 | 
				
			||||||
	Links map[string]client.Client
 | 
					 | 
				
			||||||
	// Endpoint holds the destination address
 | 
					 | 
				
			||||||
	Endpoint string
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Option func signature
 | 
					 | 
				
			||||||
type Option func(o *Options)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// NewOptions returns new options struct that filled by opts
 | 
					 | 
				
			||||||
func NewOptions(opts ...Option) Options {
 | 
					 | 
				
			||||||
	options := Options{
 | 
					 | 
				
			||||||
		Logger: logger.DefaultLogger,
 | 
					 | 
				
			||||||
		Meter:  meter.DefaultMeter,
 | 
					 | 
				
			||||||
		Tracer: tracer.DefaultTracer,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for _, o := range opts {
 | 
					 | 
				
			||||||
		o(&options)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return options
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// WithEndpoint sets a proxy endpoint
 | 
					 | 
				
			||||||
func WithEndpoint(e string) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Endpoint = e
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// WithClient sets the client
 | 
					 | 
				
			||||||
func WithClient(c client.Client) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Client = c
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// WithRouter specifies the router to use
 | 
					 | 
				
			||||||
func WithRouter(r router.Router) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Router = r
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// WithLogger specifies the logger to use
 | 
					 | 
				
			||||||
func WithLogger(l logger.Logger) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Logger = l
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// WithMeter specifies the meter to use
 | 
					 | 
				
			||||||
func WithMeter(m meter.Meter) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Meter = m
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// WithLink sets a link for outbound requests
 | 
					 | 
				
			||||||
func WithLink(name string, c client.Client) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		if o.Links == nil {
 | 
					 | 
				
			||||||
			o.Links = make(map[string]client.Client)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		o.Links[name] = c
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Tracer to be used for tracing
 | 
					 | 
				
			||||||
func Tracer(t tracer.Tracer) Option {
 | 
					 | 
				
			||||||
	return func(o *Options) {
 | 
					 | 
				
			||||||
		o.Tracer = t
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,21 +0,0 @@
 | 
				
			|||||||
// Package proxy is a transparent proxy built on the micro/server
 | 
					 | 
				
			||||||
package proxy // import "go.unistack.org/micro/v3/proxy"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"context"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"go.unistack.org/micro/v3/server"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// DefaultEndpoint holds default proxy address
 | 
					 | 
				
			||||||
var DefaultEndpoint = "localhost:9090"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Proxy can be used as a proxy server for micro services
 | 
					 | 
				
			||||||
type Proxy interface {
 | 
					 | 
				
			||||||
	// ProcessMessage handles inbound messages
 | 
					 | 
				
			||||||
	ProcessMessage(context.Context, server.Message) error
 | 
					 | 
				
			||||||
	// ServeRequest handles inbound requests
 | 
					 | 
				
			||||||
	ServeRequest(context.Context, server.Request, server.Response) error
 | 
					 | 
				
			||||||
	// Name of the proxy protocol
 | 
					 | 
				
			||||||
	String() string
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -6,7 +6,7 @@ import (
 | 
				
			|||||||
	"unicode"
 | 
						"unicode"
 | 
				
			||||||
	"unicode/utf8"
 | 
						"unicode/utf8"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro/v3/metadata"
 | 
						"go.unistack.org/micro/v4/metadata"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ExtractValue from reflect.Type from specified depth
 | 
					// ExtractValue from reflect.Type from specified depth
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,8 +5,8 @@ import (
 | 
				
			|||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro/v3/logger"
 | 
						"go.unistack.org/micro/v4/logger"
 | 
				
			||||||
	"go.unistack.org/micro/v3/util/id"
 | 
						"go.unistack.org/micro/v4/util/id"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,9 +5,9 @@ import (
 | 
				
			|||||||
	"crypto/tls"
 | 
						"crypto/tls"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro/v3/logger"
 | 
						"go.unistack.org/micro/v4/logger"
 | 
				
			||||||
	"go.unistack.org/micro/v3/meter"
 | 
						"go.unistack.org/micro/v4/meter"
 | 
				
			||||||
	"go.unistack.org/micro/v3/tracer"
 | 
						"go.unistack.org/micro/v4/tracer"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Options holds options for register
 | 
					// Options holds options for register
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,11 +1,11 @@
 | 
				
			|||||||
// Package register is an interface for service discovery
 | 
					// Package register is an interface for service discovery
 | 
				
			||||||
package register // import "go.unistack.org/micro/v3/register"
 | 
					package register // import "go.unistack.org/micro/v4/register"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro/v3/metadata"
 | 
						"go.unistack.org/micro/v4/metadata"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,5 @@
 | 
				
			|||||||
// Package dns resolves names to dns records
 | 
					// Package dns resolves names to dns records
 | 
				
			||||||
package dns // import "go.unistack.org/micro/v3/resolver/dns"
 | 
					package dns // import "go.unistack.org/micro/v4/resolver/dns"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
@@ -7,7 +7,7 @@ import (
 | 
				
			|||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro/v3/resolver"
 | 
						"go.unistack.org/micro/v4/resolver"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Resolver is a DNS network resolve
 | 
					// Resolver is a DNS network resolve
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,11 +1,11 @@
 | 
				
			|||||||
// Package dnssrv resolves names to dns srv records
 | 
					// Package dnssrv resolves names to dns srv records
 | 
				
			||||||
package dnssrv // import "go.unistack.org/micro/v3/resolver/dnssrv"
 | 
					package dnssrv // import "go.unistack.org/micro/v4/resolver/dnssrv"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"net"
 | 
						"net"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro/v3/resolver"
 | 
						"go.unistack.org/micro/v4/resolver"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Resolver is a DNS network resolve
 | 
					// Resolver is a DNS network resolve
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,5 @@
 | 
				
			|||||||
// Package http resolves names to network addresses using a http request
 | 
					// Package http resolves names to network addresses using a http request
 | 
				
			||||||
package http // import "go.unistack.org/micro/v3/resolver/http"
 | 
					package http // import "go.unistack.org/micro/v4/resolver/http"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"encoding/json"
 | 
						"encoding/json"
 | 
				
			||||||
@@ -8,7 +8,7 @@ import (
 | 
				
			|||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
	"net/url"
 | 
						"net/url"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro/v3/resolver"
 | 
						"go.unistack.org/micro/v4/resolver"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// nolint: golint,revive
 | 
					// nolint: golint,revive
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,8 +1,8 @@
 | 
				
			|||||||
// Package noop is a noop resolver
 | 
					// Package noop is a noop resolver
 | 
				
			||||||
package noop // import "go.unistack.org/micro/v3/resolver/noop"
 | 
					package noop // import "go.unistack.org/micro/v4/resolver/noop"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"go.unistack.org/micro/v3/resolver"
 | 
						"go.unistack.org/micro/v4/resolver"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Resolver contains noop resolver
 | 
					// Resolver contains noop resolver
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,11 +1,11 @@
 | 
				
			|||||||
// Package register resolves names using the micro register
 | 
					// Package register resolves names using the micro register
 | 
				
			||||||
package register // import "go.unistack.org/micro/v3/resolver/registry"
 | 
					package register // import "go.unistack.org/micro/v4/resolver/registry"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro/v3/register"
 | 
						"go.unistack.org/micro/v4/register"
 | 
				
			||||||
	"go.unistack.org/micro/v3/resolver"
 | 
						"go.unistack.org/micro/v4/resolver"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Resolver is a register network resolver
 | 
					// Resolver is a register network resolver
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,5 @@
 | 
				
			|||||||
// Package resolver resolves network names to addresses
 | 
					// Package resolver resolves network names to addresses
 | 
				
			||||||
package resolver // import "go.unistack.org/micro/v3/resolver"
 | 
					package resolver // import "go.unistack.org/micro/v4/resolver"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Resolver is network resolver. It's used to find network nodes
 | 
					// Resolver is network resolver. It's used to find network nodes
 | 
				
			||||||
// via the name to connect to. This is done based on Network.Name().
 | 
					// via the name to connect to. This is done based on Network.Name().
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,8 +1,8 @@
 | 
				
			|||||||
// Package static is a static resolver
 | 
					// Package static is a static resolver
 | 
				
			||||||
package static // import "go.unistack.org/micro/v3/resolver/static"
 | 
					package static // import "go.unistack.org/micro/v4/resolver/static"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"go.unistack.org/micro/v3/resolver"
 | 
						"go.unistack.org/micro/v4/resolver"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Resolver returns a static list of nodes. In the event the node list
 | 
					// Resolver returns a static list of nodes. In the event the node list
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,9 +3,9 @@ package router
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro/v3/logger"
 | 
						"go.unistack.org/micro/v4/logger"
 | 
				
			||||||
	"go.unistack.org/micro/v3/register"
 | 
						"go.unistack.org/micro/v4/register"
 | 
				
			||||||
	"go.unistack.org/micro/v3/util/id"
 | 
						"go.unistack.org/micro/v4/util/id"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Options are router options
 | 
					// Options are router options
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,7 +3,7 @@ package router
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"hash/fnv"
 | 
						"hash/fnv"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro/v3/metadata"
 | 
						"go.unistack.org/micro/v4/metadata"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,5 @@
 | 
				
			|||||||
// Package router provides a network routing control plane
 | 
					// Package router provides a network routing control plane
 | 
				
			||||||
package router // import "go.unistack.org/micro/v3/router"
 | 
					package router // import "go.unistack.org/micro/v4/router"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,8 +1,8 @@
 | 
				
			|||||||
package random // import "go.unistack.org/micro/v3/selector/random"
 | 
					package random // import "go.unistack.org/micro/v4/selector/random"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"go.unistack.org/micro/v3/selector"
 | 
						"go.unistack.org/micro/v4/selector"
 | 
				
			||||||
	"go.unistack.org/micro/v3/util/rand"
 | 
						"go.unistack.org/micro/v4/util/rand"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type random struct{}
 | 
					type random struct{}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,7 +3,7 @@ package random
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro/v3/selector"
 | 
						"go.unistack.org/micro/v4/selector"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestRandom(t *testing.T) {
 | 
					func TestRandom(t *testing.T) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,8 +1,8 @@
 | 
				
			|||||||
package roundrobin // import "go.unistack.org/micro/v3/selector/roundrobin"
 | 
					package roundrobin // import "go.unistack.org/micro/v4/selector/roundrobin"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"go.unistack.org/micro/v3/selector"
 | 
						"go.unistack.org/micro/v4/selector"
 | 
				
			||||||
	"go.unistack.org/micro/v3/util/rand"
 | 
						"go.unistack.org/micro/v4/util/rand"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewSelector returns an initialised round robin selector
 | 
					// NewSelector returns an initialised round robin selector
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,7 +3,7 @@ package roundrobin
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro/v3/selector"
 | 
						"go.unistack.org/micro/v4/selector"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestRoundRobin(t *testing.T) {
 | 
					func TestRoundRobin(t *testing.T) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,5 @@
 | 
				
			|||||||
// Package selector is for node selection and load balancing
 | 
					// Package selector is for node selection and load balancing
 | 
				
			||||||
package selector // import "go.unistack.org/micro/v3/selector"
 | 
					package selector // import "go.unistack.org/micro/v4/selector"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										20
									
								
								semconv/broker.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								semconv/broker.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
				
			|||||||
 | 
					package semconv
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						// PublishMessageDurationSeconds specifies meter metric name
 | 
				
			||||||
 | 
						PublishMessageDurationSeconds = "publish_message_duration_seconds"
 | 
				
			||||||
 | 
						// PublishMessageLatencyMicroseconds specifies meter metric name
 | 
				
			||||||
 | 
						PublishMessageLatencyMicroseconds = "publish_message_latency_microseconds"
 | 
				
			||||||
 | 
						// PublishMessageTotal specifies meter metric name
 | 
				
			||||||
 | 
						PublishMessageTotal = "publish_message_total"
 | 
				
			||||||
 | 
						// PublishMessageInflight specifies meter metric name
 | 
				
			||||||
 | 
						PublishMessageInflight = "publish_message_inflight"
 | 
				
			||||||
 | 
						// SubscribeMessageDurationSeconds specifies meter metric name
 | 
				
			||||||
 | 
						SubscribeMessageDurationSeconds = "subscribe_message_duration_seconds"
 | 
				
			||||||
 | 
						// SubscribeMessageLatencyMicroseconds specifies meter metric name
 | 
				
			||||||
 | 
						SubscribeMessageLatencyMicroseconds = "subscribe_message_latency_microseconds"
 | 
				
			||||||
 | 
						// SubscribeMessageTotal specifies meter metric name
 | 
				
			||||||
 | 
						SubscribeMessageTotal = "subscribe_message_total"
 | 
				
			||||||
 | 
						// SubscribeMessageInflight specifies meter metric name
 | 
				
			||||||
 | 
						SubscribeMessageInflight = "subscribe_message_inflight"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
							
								
								
									
										12
									
								
								semconv/client.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								semconv/client.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					package semconv
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						// ClientRequestDurationSeconds specifies meter metric name
 | 
				
			||||||
 | 
						ClientRequestDurationSeconds = "client_request_duration_seconds"
 | 
				
			||||||
 | 
						// ClientRequestLatencyMicroseconds specifies meter metric name
 | 
				
			||||||
 | 
						ClientRequestLatencyMicroseconds = "client_request_latency_microseconds"
 | 
				
			||||||
 | 
						// ClientRequestTotal specifies meter metric name
 | 
				
			||||||
 | 
						ClientRequestTotal = "client_request_total"
 | 
				
			||||||
 | 
						// ClientRequestInflight specifies meter metric name
 | 
				
			||||||
 | 
						ClientRequestInflight = "client_request_inflight"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user