Compare commits
60 Commits
Author | SHA1 | Date | |
---|---|---|---|
6e55d07636 | |||
919520219c | |||
60a5e737f8 | |||
34f0b209cc | |||
ba8e1889fe | |||
dae5c57a60 | |||
ea590d57df | |||
|
9aa6969836 | ||
|
c00c705c24 | ||
|
0239f795d8 | ||
|
e69b43881d | ||
3a48a613fe | |||
86626c5922 | |||
ee11f39a2f | |||
3bdfdd8fd2 | |||
6dfdff7fd8 | |||
00a4785df3 | |||
|
bae3b0ef94 | ||
|
89b0565062 | ||
1f8b0aeb61 | |||
|
5b6f849e0a | ||
|
3b416fffde | ||
3a60103aed | |||
41837a67f8 | |||
852f19598d | |||
6537b35773 | |||
b733f1316f | |||
|
840af5574c | ||
|
56e5b7001c | ||
|
11dc6fd752 | ||
a2695d8699 | |||
618421de05 | |||
|
30baaabd9f | ||
df5bce1191 | |||
|
089d0fe4df | ||
a06f535303 | |||
|
eba586a329 | ||
|
d74a8645e8 | ||
|
5a00786192 | ||
|
b3e9941634 | ||
|
a5a5904302 | ||
|
a59832e57e | ||
0e42033e7f | |||
52d8255974 | |||
9830cb48a9 | |||
92d7ab2105 | |||
d2935ef399 | |||
ce4c96ae0a | |||
|
14026d15be | ||
|
2df0c7643e | ||
e13c2c48fd | |||
8db55d2e55 | |||
ed61cad961 | |||
040fc4548f | |||
6189a1b980 | |||
eb2a450a7b | |||
|
d2a30a5da1 | ||
65889c66f6 | |||
dcdf133d5b | |||
8742b55305 |
19
.github/dependabot.yml
vendored
Normal file
19
.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
# To get started with Dependabot version updates, you'll need to specify which
|
||||
# package ecosystems to update and where the package manifests are located.
|
||||
# Please see the documentation for all configuration options:
|
||||
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
|
||||
# Maintain dependencies for GitHub Actions
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
|
||||
# Maintain dependencies for Golang
|
||||
- package-ecosystem: "gomod"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
15
.github/generate.sh
vendored
15
.github/generate.sh
vendored
@@ -1,15 +0,0 @@
|
||||
#!/bin/bash -e
|
||||
|
||||
find . -type f -name '*.pb.*.go' -o -name '*.pb.go' -a ! -name 'message.pb.go' -delete
|
||||
PROTOS=$(find . -type f -name '*.proto' | grep -v proto/google/api)
|
||||
|
||||
mkdir -p proto/google/api
|
||||
curl -s -o proto/google/api/annotations.proto -L https://raw.githubusercontent.com/googleapis/googleapis/master/google/api/annotations.proto
|
||||
curl -s -o proto/google/api/http.proto -L https://raw.githubusercontent.com/googleapis/googleapis/master/google/api/http.proto
|
||||
|
||||
for PROTO in $PROTOS; do
|
||||
echo $PROTO
|
||||
protoc -I./proto -I. -I$(dirname $PROTO) --go-grpc_out=paths=source_relative:. --go_out=paths=source_relative:. --micro_out=paths=source_relative:. $PROTO
|
||||
done
|
||||
|
||||
rm -r proto
|
20
.github/renovate.json
vendored
20
.github/renovate.json
vendored
@@ -1,20 +0,0 @@
|
||||
{
|
||||
"extends": [
|
||||
"config:base"
|
||||
],
|
||||
"postUpdateOptions": ["gomodTidy"],
|
||||
"packageRules": [
|
||||
{
|
||||
"matchUpdateTypes": ["minor", "patch", "pin", "digest"],
|
||||
"automerge": true
|
||||
},
|
||||
{
|
||||
"groupName": "all deps",
|
||||
"separateMajorMinor": true,
|
||||
"groupSlug": "all",
|
||||
"packagePatterns": [
|
||||
"*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
13
.github/stale.sh
vendored
13
.github/stale.sh
vendored
@@ -1,13 +0,0 @@
|
||||
#!/bin/bash -ex
|
||||
|
||||
export PATH=$PATH:$(pwd)/bin
|
||||
export GO111MODULE=on
|
||||
export GOBIN=$(pwd)/bin
|
||||
|
||||
#go get github.com/rvflash/goup@v0.4.1
|
||||
|
||||
#goup -v ./...
|
||||
#go get github.com/psampaz/go-mod-outdated@v0.6.0
|
||||
go list -u -m -mod=mod -json all | go-mod-outdated -update -direct -ci || true
|
||||
|
||||
#go list -u -m -json all | go-mod-outdated -update
|
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@@ -53,7 +53,7 @@ jobs:
|
||||
continue-on-error: true
|
||||
with:
|
||||
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
|
||||
version: v1.30
|
||||
version: v1.39
|
||||
# Optional: working directory, useful for monorepos
|
||||
# working-directory: somedir
|
||||
# Optional: golangci-lint command line arguments.
|
||||
|
2
.github/workflows/pr.yml
vendored
2
.github/workflows/pr.yml
vendored
@@ -53,7 +53,7 @@ jobs:
|
||||
continue-on-error: true
|
||||
with:
|
||||
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
|
||||
version: v1.30
|
||||
version: v1.39
|
||||
# Optional: working directory, useful for monorepos
|
||||
# working-directory: somedir
|
||||
# Optional: golangci-lint command line arguments.
|
||||
|
@@ -1,30 +1,44 @@
|
||||
run:
|
||||
concurrency: 4
|
||||
deadline: 5m
|
||||
modules-download-mode: readonly
|
||||
skip-files:
|
||||
- ".*\\.pb\\.go$"
|
||||
- ".*\\.pb\\.micro\\.go$"
|
||||
issues-exit-code: 1
|
||||
tests: true
|
||||
|
||||
linters-settings:
|
||||
govet:
|
||||
check-shadowing: true
|
||||
enable:
|
||||
- fieldalignment
|
||||
|
||||
linters:
|
||||
disable-all: false
|
||||
enable-all: false
|
||||
enable:
|
||||
- megacheck
|
||||
- staticcheck
|
||||
- deadcode
|
||||
- varcheck
|
||||
- gosimple
|
||||
- unused
|
||||
- prealloc
|
||||
- scopelint
|
||||
- gocritic
|
||||
- goimports
|
||||
- unconvert
|
||||
- govet
|
||||
- nakedret
|
||||
- deadcode
|
||||
- errcheck
|
||||
- govet
|
||||
- ineffassign
|
||||
- staticcheck
|
||||
- structcheck
|
||||
- gosec
|
||||
disable:
|
||||
- maligned
|
||||
- interfacer
|
||||
- typecheck
|
||||
- dupl
|
||||
- unused
|
||||
- varcheck
|
||||
- bodyclose
|
||||
- gci
|
||||
- goconst
|
||||
- gocritic
|
||||
- gosimple
|
||||
- gofmt
|
||||
- gofumpt
|
||||
- goimports
|
||||
- golint
|
||||
- gosec
|
||||
- makezero
|
||||
- misspell
|
||||
- nakedret
|
||||
- nestif
|
||||
- nilerr
|
||||
- noctx
|
||||
- prealloc
|
||||
- unconvert
|
||||
- unparam
|
||||
disable-all: false
|
||||
|
@@ -149,5 +149,4 @@ func TestValidate(t *testing.T) {
|
||||
if err := Validate(epPcreInvalid); err == nil {
|
||||
t.Fatalf("invalid pcre %v", epPcreInvalid.Path[0])
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -6,10 +6,8 @@ import (
|
||||
"github.com/unistack-org/micro/v3/logger"
|
||||
)
|
||||
|
||||
var (
|
||||
// DefaultMaxRecvSize specifies max recv size for handler
|
||||
DefaultMaxRecvSize int64 = 1024 * 1024 * 100 // 10Mb
|
||||
)
|
||||
// DefaultMaxRecvSize specifies max recv size for handler
|
||||
var DefaultMaxRecvSize int64 = 1024 * 1024 * 100 // 10Mb
|
||||
|
||||
// Options struct holds handler options
|
||||
type Options struct {
|
||||
|
@@ -15,12 +15,12 @@ import (
|
||||
// NewResolver creates new subdomain api resolver
|
||||
func NewResolver(parent resolver.Resolver, opts ...resolver.Option) resolver.Resolver {
|
||||
options := resolver.NewOptions(opts...)
|
||||
return &subdomainResolver{options, parent}
|
||||
return &subdomainResolver{opts: options, Resolver: parent}
|
||||
}
|
||||
|
||||
type subdomainResolver struct {
|
||||
opts resolver.Options
|
||||
resolver.Resolver
|
||||
opts resolver.Options
|
||||
}
|
||||
|
||||
// Resolve resolve endpoint based on subdomain
|
||||
|
@@ -19,9 +19,7 @@ type vpathResolver struct {
|
||||
opts resolver.Options
|
||||
}
|
||||
|
||||
var (
|
||||
re = regexp.MustCompile("^v[0-9]+$")
|
||||
)
|
||||
var re = regexp.MustCompile("^v[0-9]+$")
|
||||
|
||||
// Resolve endpoint
|
||||
func (r *vpathResolver) Resolve(req *http.Request, opts ...resolver.ResolveOption) (*resolver.Endpoint, error) {
|
||||
|
@@ -7,10 +7,8 @@ import (
|
||||
"github.com/unistack-org/micro/v3/api"
|
||||
)
|
||||
|
||||
var (
|
||||
// DefaultRouter contains default router implementation
|
||||
DefaultRouter Router
|
||||
)
|
||||
// DefaultRouter contains default router implementation
|
||||
var DefaultRouter Router
|
||||
|
||||
// Router is used to determine an endpoint for a request
|
||||
type Router interface {
|
||||
|
@@ -30,7 +30,7 @@ var (
|
||||
// Auth provides authentication and authorization
|
||||
type Auth interface {
|
||||
// Init the auth
|
||||
Init(opts ...Option)
|
||||
Init(opts ...Option) error
|
||||
// Options set for auth
|
||||
Options() Options
|
||||
// Generate a new account
|
||||
|
@@ -14,10 +14,11 @@ func (n *noopAuth) String() string {
|
||||
}
|
||||
|
||||
// Init the auth
|
||||
func (n *noopAuth) Init(opts ...Option) {
|
||||
func (n *noopAuth) Init(opts ...Option) error {
|
||||
for _, o := range opts {
|
||||
o(&n.opts)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Options set for auth
|
||||
|
@@ -24,11 +24,11 @@ func TestVerify(t *testing.T) {
|
||||
}
|
||||
|
||||
tt := []struct {
|
||||
Name string
|
||||
Rules []*Rule
|
||||
Error error
|
||||
Account *Account
|
||||
Resource *Resource
|
||||
Error error
|
||||
Name string
|
||||
Rules []*Rule
|
||||
}{
|
||||
{
|
||||
Name: "NoRules",
|
||||
|
@@ -7,10 +7,8 @@ import (
|
||||
"github.com/unistack-org/micro/v3/metadata"
|
||||
)
|
||||
|
||||
var (
|
||||
// DefaultBroker default broker
|
||||
DefaultBroker Broker = NewBroker()
|
||||
)
|
||||
// DefaultBroker default broker
|
||||
var DefaultBroker Broker = NewBroker()
|
||||
|
||||
// Broker is an interface used for asynchronous messaging.
|
||||
type Broker interface {
|
||||
|
@@ -13,27 +13,27 @@ import (
|
||||
)
|
||||
|
||||
type memoryBroker struct {
|
||||
opts Options
|
||||
Subscribers map[string][]*memorySubscriber
|
||||
addr string
|
||||
opts Options
|
||||
sync.RWMutex
|
||||
connected bool
|
||||
}
|
||||
|
||||
type memoryEvent struct {
|
||||
opts Options
|
||||
err error
|
||||
message interface{}
|
||||
topic string
|
||||
opts Options
|
||||
}
|
||||
|
||||
type memorySubscriber struct {
|
||||
opts SubscribeOptions
|
||||
ctx context.Context
|
||||
exit chan bool
|
||||
handler Handler
|
||||
id string
|
||||
topic string
|
||||
opts SubscribeOptions
|
||||
}
|
||||
|
||||
func (m *memoryBroker) Options() Options {
|
||||
|
@@ -9,16 +9,10 @@ import (
|
||||
"github.com/unistack-org/micro/v3/metadata"
|
||||
)
|
||||
|
||||
var (
|
||||
// DefaultCodecs will be used to encode/decode data
|
||||
DefaultCodecs = map[string]codec.Codec{
|
||||
//"application/json": cjson.NewCodec,
|
||||
//"application/json-rpc": cjsonrpc.NewCodec,
|
||||
//"application/protobuf": cproto.NewCodec,
|
||||
//"application/proto-rpc": cprotorpc.NewCodec,
|
||||
"application/octet-stream": codec.NewCodec(),
|
||||
}
|
||||
)
|
||||
// DefaultCodecs will be used to encode/decode data
|
||||
var DefaultCodecs = map[string]codec.Codec{
|
||||
"application/octet-stream": codec.NewCodec(),
|
||||
}
|
||||
|
||||
type noopClient struct {
|
||||
opts Options
|
||||
@@ -227,5 +221,8 @@ func (n *noopClient) Publish(ctx context.Context, p Message, opts ...PublishOpti
|
||||
return n.opts.Broker.Publish(ctx, topic, &broker.Message{
|
||||
Header: md,
|
||||
Body: body,
|
||||
}, broker.PublishContext(options.Context))
|
||||
},
|
||||
broker.PublishContext(options.Context),
|
||||
broker.PublishBodyOnly(options.BodyOnly),
|
||||
)
|
||||
}
|
||||
|
@@ -2,6 +2,7 @@ package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"time"
|
||||
|
||||
"github.com/unistack-org/micro/v3/broker"
|
||||
@@ -18,8 +19,8 @@ import (
|
||||
|
||||
// Options holds client options
|
||||
type Options struct {
|
||||
// CallOptions contains default CallOptions
|
||||
CallOptions CallOptions
|
||||
// Selector used to select needed address
|
||||
Selector selector.Selector
|
||||
// Logger used to log messages
|
||||
Logger logger.Logger
|
||||
// Tracer used for tracing
|
||||
@@ -30,24 +31,26 @@ type Options struct {
|
||||
Meter meter.Meter
|
||||
// Router used to get route
|
||||
Router router.Router
|
||||
// Selector used to select needed address
|
||||
Selector selector.Selector
|
||||
// Transport used for transfer messages
|
||||
Transport transport.Transport
|
||||
// Context is used for external options
|
||||
Context context.Context
|
||||
// Codecs map
|
||||
Codecs map[string]codec.Codec
|
||||
// Lookup func used to get destination addr
|
||||
Lookup LookupFunc
|
||||
// Codecs map
|
||||
Codecs map[string]codec.Codec
|
||||
// TLSConfig specifies tls.Config for secure connection
|
||||
TLSConfig *tls.Config
|
||||
// Proxy is used for proxy requests
|
||||
Proxy string
|
||||
// ContentType is Used to select codec
|
||||
// ContentType is used to select codec
|
||||
ContentType string
|
||||
// Name is the client name
|
||||
Name string
|
||||
// Wrappers contains wrappers
|
||||
Wrappers []Wrapper
|
||||
// CallOptions contains default CallOptions
|
||||
CallOptions CallOptions
|
||||
// PoolSize connection pool size
|
||||
PoolSize int
|
||||
// PoolTTL connection pool ttl
|
||||
@@ -77,6 +80,8 @@ type CallOptions struct {
|
||||
Backoff BackoffFunc
|
||||
// Network name
|
||||
Network string
|
||||
// Content-Type
|
||||
ContentType string
|
||||
// CallWrappers call wrappers
|
||||
CallWrappers []CallWrapper
|
||||
// SelectOptions selector options
|
||||
@@ -113,6 +118,8 @@ func NewPublishOptions(opts ...PublishOption) PublishOptions {
|
||||
|
||||
// PublishOptions holds publish options
|
||||
type PublishOptions struct {
|
||||
// BodyOnly will publish only message body
|
||||
BodyOnly bool
|
||||
// Context used for external options
|
||||
Context context.Context
|
||||
// Exchange topic exchange name
|
||||
@@ -167,14 +174,16 @@ func NewOptions(opts ...Option) Options {
|
||||
RequestTimeout: DefaultRequestTimeout,
|
||||
DialTimeout: transport.DefaultDialTimeout,
|
||||
},
|
||||
Lookup: LookupRoute,
|
||||
PoolSize: DefaultPoolSize,
|
||||
PoolTTL: DefaultPoolTTL,
|
||||
Selector: random.NewSelector(),
|
||||
Logger: logger.DefaultLogger,
|
||||
Broker: broker.DefaultBroker,
|
||||
Meter: meter.DefaultMeter,
|
||||
Tracer: tracer.DefaultTracer,
|
||||
Lookup: LookupRoute,
|
||||
PoolSize: DefaultPoolSize,
|
||||
PoolTTL: DefaultPoolTTL,
|
||||
Selector: random.NewSelector(),
|
||||
Logger: logger.DefaultLogger,
|
||||
Broker: broker.DefaultBroker,
|
||||
Meter: meter.DefaultMeter,
|
||||
Tracer: tracer.DefaultTracer,
|
||||
Router: router.DefaultRouter,
|
||||
Transport: transport.DefaultTransport,
|
||||
}
|
||||
|
||||
for _, o := range opts {
|
||||
@@ -312,6 +321,22 @@ func Lookup(l LookupFunc) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// TLSConfig specifies a *tls.Config
|
||||
func TLSConfig(t *tls.Config) Option {
|
||||
return func(o *Options) {
|
||||
// set the internal tls
|
||||
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.
|
||||
func Retries(i int) Option {
|
||||
return func(o *Options) {
|
||||
@@ -354,6 +379,13 @@ func WithExchange(e string) PublishOption {
|
||||
}
|
||||
}
|
||||
|
||||
// WithBodyOnly publish only message body
|
||||
func WithBodyOnly(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) {
|
||||
@@ -361,6 +393,13 @@ func PublishContext(ctx context.Context) PublishOption {
|
||||
}
|
||||
}
|
||||
|
||||
// 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) {
|
||||
@@ -465,16 +504,16 @@ func WithMessageContentType(ct string) MessageOption {
|
||||
}
|
||||
}
|
||||
|
||||
// WithContentType specifies request content type
|
||||
func WithContentType(ct string) RequestOption {
|
||||
// StreamingRequest specifies that request is streaming
|
||||
func StreamingRequest(b bool) RequestOption {
|
||||
return func(o *RequestOptions) {
|
||||
o.Stream = b
|
||||
}
|
||||
}
|
||||
|
||||
// RequestContentType specifies request content type
|
||||
func RequestContentType(ct string) RequestOption {
|
||||
return func(o *RequestOptions) {
|
||||
o.ContentType = ct
|
||||
}
|
||||
}
|
||||
|
||||
// StreamingRequest specifies that request is streaming
|
||||
func StreamingRequest() RequestOption {
|
||||
return func(o *RequestOptions) {
|
||||
o.Stream = true
|
||||
}
|
||||
}
|
||||
|
@@ -5,13 +5,13 @@ import (
|
||||
)
|
||||
|
||||
type testRequest struct {
|
||||
opts RequestOptions
|
||||
codec codec.Codec
|
||||
body interface{}
|
||||
service string
|
||||
method string
|
||||
endpoint string
|
||||
contentType string
|
||||
service string
|
||||
opts RequestOptions
|
||||
}
|
||||
|
||||
func (r *testRequest) ContentType() string {
|
||||
|
@@ -28,6 +28,8 @@ var (
|
||||
DefaultMaxMsgSize int = 1024 * 1024 * 4 // 4Mb
|
||||
// DefaultCodec is the global default codec
|
||||
DefaultCodec Codec = NewCodec()
|
||||
// DefaultTagName specifies struct tag name to control codec Marshal/Unmarshal
|
||||
DefaultTagName = "codec"
|
||||
)
|
||||
|
||||
// MessageType specifies message type for codec
|
||||
|
@@ -5,8 +5,7 @@ import (
|
||||
"io"
|
||||
)
|
||||
|
||||
type noopCodec struct {
|
||||
}
|
||||
type noopCodec struct{}
|
||||
|
||||
func (c *noopCodec) ReadHeader(conn io.Reader, m *Message, t MessageType) error {
|
||||
return nil
|
||||
|
@@ -6,10 +6,8 @@ import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
var (
|
||||
// DefaultConfig default config
|
||||
DefaultConfig Config = NewConfig()
|
||||
)
|
||||
// DefaultConfig default config
|
||||
var DefaultConfig Config = NewConfig()
|
||||
|
||||
var (
|
||||
// ErrCodecMissing is returned when codec needed and not specified
|
||||
@@ -37,10 +35,10 @@ type Config interface {
|
||||
}
|
||||
|
||||
// Watcher is the config watcher
|
||||
//type Watcher interface {
|
||||
// type Watcher interface {
|
||||
// Next() (, error)
|
||||
// Stop() error
|
||||
//}
|
||||
// }
|
||||
|
||||
// Load loads config from config sources
|
||||
func Load(ctx context.Context, cs ...Config) error {
|
||||
|
@@ -35,7 +35,7 @@ func (c *defaultConfig) Load(ctx context.Context) error {
|
||||
src, err := rutil.Zero(c.opts.Struct)
|
||||
if err == nil {
|
||||
valueOf := reflect.ValueOf(src)
|
||||
if err = c.fillValues(ctx, valueOf); err == nil {
|
||||
if err = c.fillValues(valueOf); err == nil {
|
||||
err = mergo.Merge(c.opts.Struct, src, mergo.WithOverride, mergo.WithTypeCheck, mergo.WithAppendSlice)
|
||||
}
|
||||
}
|
||||
@@ -54,7 +54,7 @@ func (c *defaultConfig) Load(ctx context.Context) error {
|
||||
}
|
||||
|
||||
//nolint:gocyclo
|
||||
func (c *defaultConfig) fillValue(ctx context.Context, value reflect.Value, val string) error {
|
||||
func (c *defaultConfig) fillValue(value reflect.Value, val string) error {
|
||||
if !rutil.IsEmpty(value) {
|
||||
return nil
|
||||
}
|
||||
@@ -71,10 +71,10 @@ func (c *defaultConfig) fillValue(ctx context.Context, value reflect.Value, val
|
||||
kv := strings.FieldsFunc(nval, func(c rune) bool { return c == '=' })
|
||||
mkey := reflect.Indirect(reflect.New(kt))
|
||||
mval := reflect.Indirect(reflect.New(et))
|
||||
if err := c.fillValue(ctx, mkey, kv[0]); err != nil {
|
||||
if err := c.fillValue(mkey, kv[0]); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := c.fillValue(ctx, mval, kv[1]); err != nil {
|
||||
if err := c.fillValue(mval, kv[1]); err != nil {
|
||||
return err
|
||||
}
|
||||
value.SetMapIndex(mkey, mval)
|
||||
@@ -84,7 +84,7 @@ func (c *defaultConfig) fillValue(ctx context.Context, value reflect.Value, val
|
||||
value.Set(reflect.MakeSlice(reflect.SliceOf(value.Type().Elem()), len(nvals), len(nvals)))
|
||||
for idx, nval := range nvals {
|
||||
nvalue := reflect.Indirect(reflect.New(value.Type().Elem()))
|
||||
if err := c.fillValue(ctx, nvalue, nval); err != nil {
|
||||
if err := c.fillValue(nvalue, nval); err != nil {
|
||||
return err
|
||||
}
|
||||
value.Index(idx).Set(nvalue)
|
||||
@@ -173,7 +173,7 @@ func (c *defaultConfig) fillValue(ctx context.Context, value reflect.Value, val
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *defaultConfig) fillValues(ctx context.Context, valueOf reflect.Value) error {
|
||||
func (c *defaultConfig) fillValues(valueOf reflect.Value) error {
|
||||
var values reflect.Value
|
||||
|
||||
if valueOf.Kind() == reflect.Ptr {
|
||||
@@ -200,7 +200,7 @@ func (c *defaultConfig) fillValues(ctx context.Context, valueOf reflect.Value) e
|
||||
switch value.Kind() {
|
||||
case reflect.Struct:
|
||||
value.Set(reflect.Indirect(reflect.New(value.Type())))
|
||||
if err := c.fillValues(ctx, value); err != nil {
|
||||
if err := c.fillValues(value); err != nil {
|
||||
return err
|
||||
}
|
||||
continue
|
||||
@@ -214,7 +214,7 @@ func (c *defaultConfig) fillValues(ctx context.Context, valueOf reflect.Value) e
|
||||
value.Set(reflect.New(value.Type().Elem()))
|
||||
}
|
||||
value = value.Elem()
|
||||
if err := c.fillValues(ctx, value); err != nil {
|
||||
if err := c.fillValues(value); err != nil {
|
||||
return err
|
||||
}
|
||||
continue
|
||||
@@ -224,7 +224,7 @@ func (c *defaultConfig) fillValues(ctx context.Context, valueOf reflect.Value) e
|
||||
continue
|
||||
}
|
||||
|
||||
if err := c.fillValue(ctx, value, tag); err != nil {
|
||||
if err := c.fillValue(value, tag); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@@ -10,30 +10,30 @@ import (
|
||||
|
||||
type Cfg struct {
|
||||
StringValue string `default:"string_value"`
|
||||
IntValue int `default:"99"`
|
||||
IgnoreValue string `json:"-"`
|
||||
StructValue struct {
|
||||
StringValue string `default:"string_value"`
|
||||
}
|
||||
IntValue int `default:"99"`
|
||||
}
|
||||
|
||||
func TestDefault(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
conf := &Cfg{IntValue: 10}
|
||||
blfn := func(ctx context.Context, cfg config.Config) error {
|
||||
conf, ok := cfg.Options().Struct.(*Cfg)
|
||||
nconf, ok := cfg.Options().Struct.(*Cfg)
|
||||
if !ok {
|
||||
return fmt.Errorf("failed to get Struct from options: %v", cfg.Options())
|
||||
}
|
||||
conf.StringValue = "before_load"
|
||||
nconf.StringValue = "before_load"
|
||||
return nil
|
||||
}
|
||||
alfn := func(ctx context.Context, cfg config.Config) error {
|
||||
conf, ok := cfg.Options().Struct.(*Cfg)
|
||||
nconf, ok := cfg.Options().Struct.(*Cfg)
|
||||
if !ok {
|
||||
return fmt.Errorf("failed to get Struct from options: %v", cfg.Options())
|
||||
}
|
||||
conf.StringValue = "after_load"
|
||||
nconf.StringValue = "after_load"
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@@ -7,9 +7,9 @@ import (
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Value string
|
||||
SubConfig *SubConfig
|
||||
Config *Config
|
||||
Value string
|
||||
}
|
||||
|
||||
type SubConfig struct {
|
||||
|
@@ -17,7 +17,6 @@ func TestFromError(t *testing.T) {
|
||||
if merr.Id != "go.micro.test" || merr.Code != 404 {
|
||||
t.Fatalf("invalid conversation %v != %v", err, merr)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestEqual(t *testing.T) {
|
||||
@@ -32,7 +31,6 @@ func TestEqual(t *testing.T) {
|
||||
if Equal(err1, err3) {
|
||||
t.Fatal("errors must be not equal")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestErrors(t *testing.T) {
|
||||
|
@@ -44,10 +44,10 @@ func TestDag(t *testing.T) {
|
||||
var steps [][]string
|
||||
fn := func(n dag.Vertex, idx int) error {
|
||||
if idx == 0 {
|
||||
steps = make([][]string, 1, 1)
|
||||
steps = make([][]string, 1)
|
||||
steps[0] = make([]string, 0, 1)
|
||||
} else if idx >= len(steps) {
|
||||
tsteps := make([][]string, idx+1, idx+1)
|
||||
tsteps := make([][]string, idx+1)
|
||||
copy(tsteps, steps)
|
||||
steps = tsteps
|
||||
steps[idx] = make([]string, 0, 1)
|
||||
|
14
flow/flow.go
14
flow/flow.go
@@ -1,7 +1,17 @@
|
||||
// Package flow is an interface used for saga pattern messaging
|
||||
// Package flow is an interface used for saga pattern microservice workflow
|
||||
package flow
|
||||
|
||||
type Step interface {
|
||||
// Endpoint returns service_name.service_method
|
||||
// Endpoint returns rpc endpoint service_name.service_method or broker topic
|
||||
Endpoint() string
|
||||
}
|
||||
|
||||
type Workflow interface {
|
||||
Steps() [][]Step
|
||||
Stop() error
|
||||
}
|
||||
|
||||
type Flow interface {
|
||||
Start(Workflow) error
|
||||
Stop(Workflow)
|
||||
}
|
||||
|
@@ -1,3 +0,0 @@
|
||||
package micro
|
||||
|
||||
//go:generate ./.github/generate.sh
|
2
go.mod
2
go.mod
@@ -9,5 +9,5 @@ require (
|
||||
github.com/imdario/mergo v0.3.12
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||
github.com/silas/dag v0.0.0-20210121180416-41cf55125c34
|
||||
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4
|
||||
golang.org/x/net v0.0.0-20210510120150-4163338589ed
|
||||
)
|
||||
|
8
go.sum
8
go.sum
@@ -10,12 +10,12 @@ github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaR
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
||||
github.com/silas/dag v0.0.0-20210121180416-41cf55125c34 h1:vBfVmA5mZhsQa2jr1FOL9nfA37N/jnbBmi5XUfviVTI=
|
||||
github.com/silas/dag v0.0.0-20210121180416-41cf55125c34/go.mod h1:7RTUFBdIRC9nZ7/3RyRNH1bdqIShrDejd1YbLwgPS+I=
|
||||
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4 h1:b0LrWgu8+q7z4J+0Y3Umo5q1dL7NXBkKBWkaVkAq17E=
|
||||
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
||||
golang.org/x/net v0.0.0-20210510120150-4163338589ed h1:p9UgmWI9wKpfYmgaV/IZKGdXc5qEK45tDwwwDyjS26I=
|
||||
golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||
|
@@ -21,8 +21,8 @@ func init() {
|
||||
}
|
||||
|
||||
type defaultLogger struct {
|
||||
opts Options
|
||||
enc *json.Encoder
|
||||
opts Options
|
||||
sync.RWMutex
|
||||
}
|
||||
|
||||
|
@@ -76,7 +76,7 @@ func WithContext(ctx context.Context) Option {
|
||||
}
|
||||
|
||||
// WithName sets the name
|
||||
func withName(n string) Option {
|
||||
func WithName(n string) Option {
|
||||
return func(o *Options) {
|
||||
o.Name = n
|
||||
}
|
||||
|
@@ -3,6 +3,7 @@ package wrapper
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/unistack-org/micro/v3/client"
|
||||
"github.com/unistack-org/micro/v3/logger"
|
||||
@@ -57,6 +58,8 @@ var (
|
||||
}
|
||||
return labels
|
||||
}
|
||||
|
||||
DefaultSkipEndpoints = []string{"Meter.Metrics"}
|
||||
)
|
||||
|
||||
type lWrapper struct {
|
||||
@@ -67,21 +70,23 @@ type lWrapper struct {
|
||||
opts Options
|
||||
}
|
||||
|
||||
type ClientCallObserver func(context.Context, client.Request, interface{}, []client.CallOption, error) []string
|
||||
type ClientStreamObserver func(context.Context, client.Request, []client.CallOption, client.Stream, error) []string
|
||||
type ClientPublishObserver func(context.Context, client.Message, []client.PublishOption, error) []string
|
||||
type ClientCallFuncObserver func(context.Context, string, client.Request, interface{}, client.CallOptions, error) []string
|
||||
type ServerHandlerObserver func(context.Context, server.Request, interface{}, error) []string
|
||||
type ServerSubscriberObserver func(context.Context, server.Message, error) []string
|
||||
type (
|
||||
ClientCallObserver func(context.Context, client.Request, interface{}, []client.CallOption, error) []string
|
||||
ClientStreamObserver func(context.Context, client.Request, []client.CallOption, client.Stream, error) []string
|
||||
ClientPublishObserver func(context.Context, client.Message, []client.PublishOption, error) []string
|
||||
ClientCallFuncObserver func(context.Context, string, client.Request, interface{}, client.CallOptions, error) []string
|
||||
ServerHandlerObserver func(context.Context, server.Request, interface{}, error) []string
|
||||
ServerSubscriberObserver func(context.Context, server.Message, error) []string
|
||||
)
|
||||
|
||||
// Options struct for wrapper
|
||||
type Options struct {
|
||||
// Logger that used for log
|
||||
Logger logger.Logger
|
||||
// Level for logger
|
||||
Level logger.Level
|
||||
// Enabled flag
|
||||
Enabled bool
|
||||
// ServerHandlerObservers funcs
|
||||
ServerHandlerObservers []ServerHandlerObserver
|
||||
// ServerSubscriberObservers funcs
|
||||
ServerSubscriberObservers []ServerSubscriberObserver
|
||||
// ClientCallObservers funcs
|
||||
ClientCallObservers []ClientCallObserver
|
||||
// ClientStreamObservers funcs
|
||||
@@ -90,10 +95,12 @@ type Options struct {
|
||||
ClientPublishObservers []ClientPublishObserver
|
||||
// ClientCallFuncObservers funcs
|
||||
ClientCallFuncObservers []ClientCallFuncObserver
|
||||
// ServerHandlerObservers funcs
|
||||
ServerHandlerObservers []ServerHandlerObserver
|
||||
// ServerSubscriberObservers funcs
|
||||
ServerSubscriberObservers []ServerSubscriberObserver
|
||||
// SkipEndpoints
|
||||
SkipEndpoints []string
|
||||
// Level for logger
|
||||
Level logger.Level
|
||||
// Enabled flag
|
||||
Enabled bool
|
||||
}
|
||||
|
||||
// Option func signature
|
||||
@@ -110,6 +117,7 @@ func NewOptions(opts ...Option) Options {
|
||||
ClientCallFuncObservers: []ClientCallFuncObserver{DefaultClientCallFuncObserver},
|
||||
ServerHandlerObservers: []ServerHandlerObserver{DefaultServerHandlerObserver},
|
||||
ServerSubscriberObservers: []ServerSubscriberObserver{DefaultServerSubscriberObserver},
|
||||
SkipEndpoints: DefaultSkipEndpoints,
|
||||
}
|
||||
|
||||
for _, o := range opts {
|
||||
@@ -182,9 +190,23 @@ func WithServerSubscriberObservers(ob ...ServerSubscriberObserver) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// SkipEndpoins
|
||||
func SkipEndpoints(eps ...string) Option {
|
||||
return func(o *Options) {
|
||||
o.SkipEndpoints = append(o.SkipEndpoints, eps...)
|
||||
}
|
||||
}
|
||||
|
||||
func (l *lWrapper) Call(ctx context.Context, req client.Request, rsp interface{}, opts ...client.CallOption) error {
|
||||
err := l.Client.Call(ctx, req, rsp, opts...)
|
||||
|
||||
endpoint := fmt.Sprintf("%s.%s", req.Service(), req.Endpoint())
|
||||
for _, ep := range l.opts.SkipEndpoints {
|
||||
if ep == endpoint {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if !l.opts.Enabled {
|
||||
return err
|
||||
}
|
||||
@@ -193,7 +215,7 @@ func (l *lWrapper) Call(ctx context.Context, req client.Request, rsp interface{}
|
||||
for _, o := range l.opts.ClientCallObservers {
|
||||
labels = append(labels, o(ctx, req, rsp, opts, err)...)
|
||||
}
|
||||
fields := make(map[string]interface{}, int(len(labels)/2))
|
||||
fields := make(map[string]interface{}, len(labels)/2)
|
||||
for i := 0; i < len(labels); i += 2 {
|
||||
fields[labels[i]] = labels[i+1]
|
||||
}
|
||||
@@ -205,6 +227,13 @@ func (l *lWrapper) Call(ctx context.Context, req client.Request, rsp interface{}
|
||||
func (l *lWrapper) Stream(ctx context.Context, req client.Request, opts ...client.CallOption) (client.Stream, error) {
|
||||
stream, err := l.Client.Stream(ctx, req, opts...)
|
||||
|
||||
endpoint := fmt.Sprintf("%s.%s", req.Service(), req.Endpoint())
|
||||
for _, ep := range l.opts.SkipEndpoints {
|
||||
if ep == endpoint {
|
||||
return stream, err
|
||||
}
|
||||
}
|
||||
|
||||
if !l.opts.Enabled {
|
||||
return stream, err
|
||||
}
|
||||
@@ -213,7 +242,7 @@ func (l *lWrapper) Stream(ctx context.Context, req client.Request, opts ...clien
|
||||
for _, o := range l.opts.ClientStreamObservers {
|
||||
labels = append(labels, o(ctx, req, opts, stream, err)...)
|
||||
}
|
||||
fields := make(map[string]interface{}, int(len(labels)/2))
|
||||
fields := make(map[string]interface{}, len(labels)/2)
|
||||
for i := 0; i < len(labels); i += 2 {
|
||||
fields[labels[i]] = labels[i+1]
|
||||
}
|
||||
@@ -225,6 +254,13 @@ func (l *lWrapper) Stream(ctx context.Context, req client.Request, opts ...clien
|
||||
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
|
||||
}
|
||||
@@ -233,7 +269,7 @@ func (l *lWrapper) Publish(ctx context.Context, msg client.Message, opts ...clie
|
||||
for _, o := range l.opts.ClientPublishObservers {
|
||||
labels = append(labels, o(ctx, msg, opts, err)...)
|
||||
}
|
||||
fields := make(map[string]interface{}, int(len(labels)/2))
|
||||
fields := make(map[string]interface{}, len(labels)/2)
|
||||
for i := 0; i < len(labels); i += 2 {
|
||||
fields[labels[i]] = labels[i+1]
|
||||
}
|
||||
@@ -245,6 +281,13 @@ func (l *lWrapper) Publish(ctx context.Context, msg client.Message, opts ...clie
|
||||
func (l *lWrapper) ServerHandler(ctx context.Context, req server.Request, rsp interface{}) error {
|
||||
err := l.serverHandler(ctx, req, rsp)
|
||||
|
||||
endpoint := req.Endpoint()
|
||||
for _, ep := range l.opts.SkipEndpoints {
|
||||
if ep == endpoint {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if !l.opts.Enabled {
|
||||
return err
|
||||
}
|
||||
@@ -253,7 +296,7 @@ func (l *lWrapper) ServerHandler(ctx context.Context, req server.Request, rsp in
|
||||
for _, o := range l.opts.ServerHandlerObservers {
|
||||
labels = append(labels, o(ctx, req, rsp, err)...)
|
||||
}
|
||||
fields := make(map[string]interface{}, int(len(labels)/2))
|
||||
fields := make(map[string]interface{}, len(labels)/2)
|
||||
for i := 0; i < len(labels); i += 2 {
|
||||
fields[labels[i]] = labels[i+1]
|
||||
}
|
||||
@@ -265,6 +308,13 @@ func (l *lWrapper) ServerHandler(ctx context.Context, req server.Request, rsp in
|
||||
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
|
||||
}
|
||||
@@ -273,7 +323,7 @@ func (l *lWrapper) ServerSubscriber(ctx context.Context, msg server.Message) err
|
||||
for _, o := range l.opts.ServerSubscriberObservers {
|
||||
labels = append(labels, o(ctx, msg, err)...)
|
||||
}
|
||||
fields := make(map[string]interface{}, int(len(labels)/2))
|
||||
fields := make(map[string]interface{}, len(labels)/2)
|
||||
for i := 0; i < len(labels); i += 2 {
|
||||
fields[labels[i]] = labels[i+1]
|
||||
}
|
||||
@@ -309,6 +359,13 @@ func NewClientCallWrapper(opts ...Option) client.CallWrapper {
|
||||
func (l *lWrapper) ClientCallFunc(ctx context.Context, addr string, req client.Request, rsp interface{}, opts client.CallOptions) error {
|
||||
err := l.clientCallFunc(ctx, addr, req, rsp, opts)
|
||||
|
||||
endpoint := fmt.Sprintf("%s.%s", req.Service(), req.Endpoint())
|
||||
for _, ep := range l.opts.SkipEndpoints {
|
||||
if ep == endpoint {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if !l.opts.Enabled {
|
||||
return err
|
||||
}
|
||||
@@ -317,7 +374,7 @@ func (l *lWrapper) ClientCallFunc(ctx context.Context, addr string, req client.R
|
||||
for _, o := range l.opts.ClientCallFuncObservers {
|
||||
labels = append(labels, o(ctx, addr, req, rsp, opts, err)...)
|
||||
}
|
||||
fields := make(map[string]interface{}, int(len(labels)/2))
|
||||
fields := make(map[string]interface{}, len(labels)/2)
|
||||
for i := 0; i < len(labels); i += 2 {
|
||||
fields[labels[i]] = labels[i+1]
|
||||
}
|
||||
|
@@ -5,9 +5,11 @@ import (
|
||||
"context"
|
||||
)
|
||||
|
||||
type mdIncomingKey struct{}
|
||||
type mdOutgoingKey struct{}
|
||||
type mdKey struct{}
|
||||
type (
|
||||
mdIncomingKey struct{}
|
||||
mdOutgoingKey struct{}
|
||||
mdKey struct{}
|
||||
)
|
||||
|
||||
// FromIncomingContext returns metadata from incoming ctx
|
||||
// returned metadata shoud not be modified or race condition happens
|
||||
|
@@ -6,10 +6,8 @@ import (
|
||||
"sort"
|
||||
)
|
||||
|
||||
var (
|
||||
// HeaderPrefix for all headers passed
|
||||
HeaderPrefix = "Micro-"
|
||||
)
|
||||
// HeaderPrefix for all headers passed
|
||||
var HeaderPrefix = "Micro-"
|
||||
|
||||
// Metadata is our way of representing request headers internally.
|
||||
// They're used at the RPC level and translate back and forth
|
||||
@@ -20,10 +18,8 @@ type rawMetadata struct {
|
||||
md Metadata
|
||||
}
|
||||
|
||||
var (
|
||||
// defaultMetadataSize used when need to init new Metadata
|
||||
defaultMetadataSize = 2
|
||||
)
|
||||
// defaultMetadataSize used when need to init new Metadata
|
||||
var defaultMetadataSize = 2
|
||||
|
||||
// Iterator used to iterate over metadata with order
|
||||
type Iterator struct {
|
||||
|
@@ -76,7 +76,7 @@ func TestIterator(t *testing.T) {
|
||||
var k, v string
|
||||
|
||||
for iter.Next(&k, &v) {
|
||||
//fmt.Printf("k: %s, v: %s\n", k, v)
|
||||
// fmt.Printf("k: %s, v: %s\n", k, v)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,7 +102,6 @@ func TestMedataCanonicalKey(t *testing.T) {
|
||||
} else if v != "12345" {
|
||||
t.Fatalf("invalid metadata value: %s != %s", "12345", v)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestMetadataSet(t *testing.T) {
|
||||
@@ -130,7 +129,6 @@ func TestMetadataDelete(t *testing.T) {
|
||||
if ok {
|
||||
t.Fatal("key Baz not deleted")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestNilContext(t *testing.T) {
|
||||
|
@@ -1,33 +1,64 @@
|
||||
package pb
|
||||
package handler
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
|
||||
"github.com/unistack-org/micro/v3/codec"
|
||||
"github.com/unistack-org/micro/v3/errors"
|
||||
"github.com/unistack-org/micro/v3/meter"
|
||||
)
|
||||
|
||||
var (
|
||||
// guard to fail early
|
||||
_ MeterServer = &handler{}
|
||||
)
|
||||
// guard to fail early
|
||||
var _ MeterServer = &Handler{}
|
||||
|
||||
type Empty struct{}
|
||||
|
||||
type handler struct {
|
||||
meter meter.Meter
|
||||
opts []meter.Option
|
||||
type Handler struct {
|
||||
opts Options
|
||||
}
|
||||
|
||||
func NewHandler(meter meter.Meter, opts ...meter.Option) *handler {
|
||||
return &handler{meter: meter, opts: opts}
|
||||
type Option func(*Options)
|
||||
|
||||
type Options struct {
|
||||
Meter meter.Meter
|
||||
Name string
|
||||
MeterOptions []meter.Option
|
||||
}
|
||||
|
||||
func (h *handler) Metrics(ctx context.Context, req *Empty, rsp *codec.Frame) error {
|
||||
func Meter(m meter.Meter) Option {
|
||||
return func(o *Options) {
|
||||
o.Meter = m
|
||||
}
|
||||
}
|
||||
|
||||
func Name(name string) Option {
|
||||
return func(o *Options) {
|
||||
o.Name = name
|
||||
}
|
||||
}
|
||||
|
||||
func MeterOptions(opts ...meter.Option) Option {
|
||||
return func(o *Options) {
|
||||
o.MeterOptions = append(o.MeterOptions, opts...)
|
||||
}
|
||||
}
|
||||
|
||||
func NewOptions(opts ...Option) Options {
|
||||
options := Options{Meter: meter.DefaultMeter}
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
}
|
||||
return options
|
||||
}
|
||||
|
||||
func NewHandler(opts ...Option) *Handler {
|
||||
options := NewOptions(opts...)
|
||||
return &Handler{opts: options}
|
||||
}
|
||||
|
||||
func (h *Handler) Metrics(ctx context.Context, req *codec.Frame, rsp *codec.Frame) error {
|
||||
buf := bytes.NewBuffer(nil)
|
||||
if err := h.meter.Write(buf, h.opts...); err != nil {
|
||||
return err
|
||||
if err := h.opts.Meter.Write(buf, h.opts.MeterOptions...); err != nil {
|
||||
return errors.InternalServerError(h.opts.Name, "%v", err)
|
||||
}
|
||||
|
||||
rsp.Data = buf.Bytes()
|
||||
|
@@ -1,14 +1,14 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package meter;
|
||||
option go_package = "github.com/unistack-org/micro/v3/meter/handler;pb";
|
||||
package micro.meter.handler;
|
||||
option go_package = "github.com/unistack-org/micro/v3/meter/handler;handler";
|
||||
|
||||
import "api/annotations.proto";
|
||||
import "openapiv2/annotations.proto";
|
||||
import "codec/frame.proto";
|
||||
|
||||
service Meter {
|
||||
rpc Metrics(Empty) returns (micro.codec.Frame) {
|
||||
rpc Metrics(micro.codec.Frame) returns (micro.codec.Frame) {
|
||||
option (micro.openapiv2.openapiv2_operation) = {
|
||||
operation_id: "Metrics";
|
||||
responses: {
|
||||
@@ -17,7 +17,7 @@ service Meter {
|
||||
description: "Error response";
|
||||
schema: {
|
||||
json_schema: {
|
||||
ref: "Empty";
|
||||
ref: "micro.codec.Frame";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,5 +26,3 @@ service Meter {
|
||||
option (micro.api.http) = { get: "/metrics"; };
|
||||
};
|
||||
};
|
||||
|
||||
message Empty{};
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-micro
|
||||
// source: handler.proto
|
||||
package pb
|
||||
package handler
|
||||
|
||||
import (
|
||||
context "context"
|
||||
@@ -20,5 +20,5 @@ func NewMeterEndpoints() []*api.Endpoint {
|
||||
}
|
||||
|
||||
type MeterServer interface {
|
||||
Metrics(ctx context.Context, req *Empty, rsp *codec.Frame) error
|
||||
Metrics(ctx context.Context, req *codec.Frame, rsp *codec.Frame) error
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-micro
|
||||
// source: handler.proto
|
||||
package pb
|
||||
package handler
|
||||
|
||||
import (
|
||||
context "context"
|
||||
@@ -13,20 +13,21 @@ type meterServer struct {
|
||||
MeterServer
|
||||
}
|
||||
|
||||
func (h *meterServer) Metrics(ctx context.Context, req *Empty, rsp *codec.Frame) error {
|
||||
func (h *meterServer) Metrics(ctx context.Context, req *codec.Frame, rsp *codec.Frame) error {
|
||||
return h.MeterServer.Metrics(ctx, req, rsp)
|
||||
}
|
||||
|
||||
func RegisterMeterServer(s server.Server, sh MeterServer, opts ...server.HandlerOption) error {
|
||||
type meter interface {
|
||||
Metrics(ctx context.Context, req *Empty, rsp *codec.Frame) error
|
||||
Metrics(ctx context.Context, req *codec.Frame, rsp *codec.Frame) error
|
||||
}
|
||||
type Meter struct {
|
||||
meter
|
||||
}
|
||||
h := &meterServer{sh}
|
||||
var nopts []server.HandlerOption
|
||||
for _, endpoint := range NewMeterEndpoints() {
|
||||
opts = append(opts, api.WithEndpoint(endpoint))
|
||||
nopts = append(nopts, api.WithEndpoint(endpoint))
|
||||
}
|
||||
return s.Handle(s.NewHandler(&Meter{h}, opts...))
|
||||
return s.Handle(s.NewHandler(&Meter{h}, append(nopts, opts...)...))
|
||||
}
|
||||
|
@@ -29,13 +29,13 @@ var (
|
||||
type Meter interface {
|
||||
Name() string
|
||||
Init(opts ...Option) error
|
||||
Counter(name string, opts ...Option) Counter
|
||||
FloatCounter(name string, opts ...Option) FloatCounter
|
||||
Gauge(name string, fn func() float64, opts ...Option) Gauge
|
||||
Counter(name string, labels ...string) Counter
|
||||
FloatCounter(name string, labels ...string) FloatCounter
|
||||
Gauge(name string, fn func() float64, labels ...string) Gauge
|
||||
Set(opts ...Option) Meter
|
||||
Histogram(name string, opts ...Option) Histogram
|
||||
Summary(name string, opts ...Option) Summary
|
||||
SummaryExt(name string, window time.Duration, quantiles []float64, opts ...Option) Summary
|
||||
Histogram(name string, labels ...string) Histogram
|
||||
Summary(name string, labels ...string) Summary
|
||||
SummaryExt(name string, window time.Duration, quantiles []float64, labels ...string) Summary
|
||||
Write(w io.Writer, opts ...Option) error
|
||||
Options() Options
|
||||
String() string
|
||||
|
@@ -10,7 +10,7 @@ func TestNoopMeter(t *testing.T) {
|
||||
t.Fatalf("invalid options parsing: %v", m.Options())
|
||||
}
|
||||
|
||||
cnt := m.Counter("counter", Labels("server", "noop"))
|
||||
cnt := m.Counter("counter", "server", "noop")
|
||||
cnt.Inc()
|
||||
}
|
||||
|
||||
|
@@ -28,57 +28,33 @@ func (r *noopMeter) Init(opts ...Option) error {
|
||||
}
|
||||
|
||||
// Counter implements the Meter interface
|
||||
func (r *noopMeter) Counter(name string, opts ...Option) Counter {
|
||||
options := Options{}
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
}
|
||||
return &noopCounter{labels: options.Labels}
|
||||
func (r *noopMeter) Counter(name string, labels ...string) Counter {
|
||||
return &noopCounter{labels: labels}
|
||||
}
|
||||
|
||||
// FloatCounter implements the Meter interface
|
||||
func (r *noopMeter) FloatCounter(name string, opts ...Option) FloatCounter {
|
||||
options := Options{}
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
}
|
||||
return &noopFloatCounter{labels: options.Labels}
|
||||
func (r *noopMeter) FloatCounter(name string, labels ...string) FloatCounter {
|
||||
return &noopFloatCounter{labels: labels}
|
||||
}
|
||||
|
||||
// Gauge implements the Meter interface
|
||||
func (r *noopMeter) Gauge(name string, f func() float64, opts ...Option) Gauge {
|
||||
options := Options{}
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
}
|
||||
return &noopGauge{labels: options.Labels}
|
||||
func (r *noopMeter) Gauge(name string, f func() float64, labels ...string) Gauge {
|
||||
return &noopGauge{labels: labels}
|
||||
}
|
||||
|
||||
// Summary implements the Meter interface
|
||||
func (r *noopMeter) Summary(name string, opts ...Option) Summary {
|
||||
options := Options{}
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
}
|
||||
return &noopSummary{labels: options.Labels}
|
||||
func (r *noopMeter) Summary(name string, labels ...string) Summary {
|
||||
return &noopSummary{labels: labels}
|
||||
}
|
||||
|
||||
// SummaryExt implements the Meter interface
|
||||
func (r *noopMeter) SummaryExt(name string, window time.Duration, quantiles []float64, opts ...Option) Summary {
|
||||
options := Options{}
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
}
|
||||
return &noopSummary{labels: options.Labels}
|
||||
func (r *noopMeter) SummaryExt(name string, window time.Duration, quantiles []float64, labels ...string) Summary {
|
||||
return &noopSummary{labels: labels}
|
||||
}
|
||||
|
||||
// Histogram implements the Meter interface
|
||||
func (r *noopMeter) Histogram(name string, opts ...Option) Histogram {
|
||||
options := Options{}
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
}
|
||||
return &noopHistogram{labels: options.Labels}
|
||||
func (r *noopMeter) Histogram(name string, labels ...string) Histogram {
|
||||
return &noopHistogram{labels: labels}
|
||||
}
|
||||
|
||||
// Set implements the Meter interface
|
||||
@@ -111,11 +87,9 @@ type noopCounter struct {
|
||||
}
|
||||
|
||||
func (r *noopCounter) Add(int) {
|
||||
|
||||
}
|
||||
|
||||
func (r *noopCounter) Dec() {
|
||||
|
||||
}
|
||||
|
||||
func (r *noopCounter) Get() uint64 {
|
||||
@@ -123,11 +97,9 @@ func (r *noopCounter) Get() uint64 {
|
||||
}
|
||||
|
||||
func (r *noopCounter) Inc() {
|
||||
|
||||
}
|
||||
|
||||
func (r *noopCounter) Set(uint64) {
|
||||
|
||||
}
|
||||
|
||||
type noopFloatCounter struct {
|
||||
@@ -135,7 +107,6 @@ type noopFloatCounter struct {
|
||||
}
|
||||
|
||||
func (r *noopFloatCounter) Add(float64) {
|
||||
|
||||
}
|
||||
|
||||
func (r *noopFloatCounter) Get() float64 {
|
||||
@@ -143,11 +114,9 @@ func (r *noopFloatCounter) Get() float64 {
|
||||
}
|
||||
|
||||
func (r *noopFloatCounter) Set(float64) {
|
||||
|
||||
}
|
||||
|
||||
func (r *noopFloatCounter) Sub(float64) {
|
||||
|
||||
}
|
||||
|
||||
type noopGauge struct {
|
||||
@@ -163,11 +132,9 @@ type noopSummary struct {
|
||||
}
|
||||
|
||||
func (r *noopSummary) Update(float64) {
|
||||
|
||||
}
|
||||
|
||||
func (r *noopSummary) UpdateDuration(time.Time) {
|
||||
|
||||
}
|
||||
|
||||
type noopHistogram struct {
|
||||
@@ -175,15 +142,12 @@ type noopHistogram struct {
|
||||
}
|
||||
|
||||
func (r *noopHistogram) Reset() {
|
||||
|
||||
}
|
||||
|
||||
func (r *noopHistogram) Update(float64) {
|
||||
|
||||
}
|
||||
|
||||
func (r *noopHistogram) UpdateDuration(time.Time) {
|
||||
|
||||
}
|
||||
|
||||
//func (r *noopHistogram) VisitNonZeroBuckets(f func(vmrange string, count uint64)) {}
|
||||
// func (r *noopHistogram) VisitNonZeroBuckets(f func(vmrange string, count uint64)) {}
|
||||
|
@@ -90,7 +90,7 @@ func Logger(l logger.Logger) Option {
|
||||
|
||||
func Labels(ls ...string) Option {
|
||||
return func(o *Options) {
|
||||
o.Labels = ls
|
||||
o.Labels = append(o.Labels, ls...)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -11,36 +11,48 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
ClientRequestDurationSeconds = "client_request_duration_seconds"
|
||||
ClientRequestLatencyMicroseconds = "client_request_latency_microseconds"
|
||||
ClientRequestTotal = "client_request_total"
|
||||
ServerRequestDurationSeconds = "server_request_duration_seconds"
|
||||
ServerRequestLatencyMicroseconds = "server_request_latency_microseconds"
|
||||
ServerRequestTotal = "server_request_total"
|
||||
PublishMessageDurationSeconds = "publish_message_duration_seconds"
|
||||
PublishMessageLatencyMicroseconds = "publish_message_latency_microseconds"
|
||||
PublishMessageTotal = "publish_message_total"
|
||||
ClientRequestDurationSeconds = "client_request_duration_seconds"
|
||||
ClientRequestLatencyMicroseconds = "client_request_latency_microseconds"
|
||||
ClientRequestTotal = "client_request_total"
|
||||
ClientRequestInflight = "client_request_inflight"
|
||||
|
||||
ServerRequestDurationSeconds = "server_request_duration_seconds"
|
||||
ServerRequestLatencyMicroseconds = "server_request_latency_microseconds"
|
||||
ServerRequestTotal = "server_request_total"
|
||||
ServerRequestInflight = "server_request_inflight"
|
||||
|
||||
PublishMessageDurationSeconds = "publish_message_duration_seconds"
|
||||
PublishMessageLatencyMicroseconds = "publish_message_latency_microseconds"
|
||||
PublishMessageTotal = "publish_message_total"
|
||||
PublishMessageInflight = "publish_message_inflight"
|
||||
|
||||
SubscribeMessageDurationSeconds = "subscribe_message_duration_seconds"
|
||||
SubscribeMessageLatencyMicroseconds = "subscribe_message_latency_microseconds"
|
||||
SubscribeMessageTotal = "subscribe_message_total"
|
||||
SubscribeMessageInflight = "subscribe_message_inflight"
|
||||
|
||||
labelSuccess = "success"
|
||||
labelFailure = "failure"
|
||||
labelStatus = "status"
|
||||
labelEndpoint = "endpoint"
|
||||
|
||||
// DefaultSkipEndpoints contains list of endpoints that not evaluted by wrapper
|
||||
DefaultSkipEndpoints = []string{"Meter.Metrics"}
|
||||
)
|
||||
|
||||
type Options struct {
|
||||
Meter meter.Meter
|
||||
lopts []meter.Option
|
||||
Meter meter.Meter
|
||||
lopts []meter.Option
|
||||
SkipEndpoints []string
|
||||
}
|
||||
|
||||
type Option func(*Options)
|
||||
|
||||
func NewOptions(opts ...Option) Options {
|
||||
options := Options{
|
||||
Meter: meter.DefaultMeter,
|
||||
lopts: make([]meter.Option, 0, 5),
|
||||
Meter: meter.DefaultMeter,
|
||||
lopts: make([]meter.Option, 0, 5),
|
||||
SkipEndpoints: DefaultSkipEndpoints,
|
||||
}
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
@@ -72,6 +84,12 @@ func Meter(m meter.Meter) Option {
|
||||
}
|
||||
}
|
||||
|
||||
func SkipEndoints(eps ...string) Option {
|
||||
return func(o *Options) {
|
||||
o.SkipEndpoints = append(o.SkipEndpoints, eps...)
|
||||
}
|
||||
}
|
||||
|
||||
type wrapper struct {
|
||||
client.Client
|
||||
callFunc client.CallFunc
|
||||
@@ -100,69 +118,90 @@ func NewCallWrapper(opts ...Option) client.CallWrapper {
|
||||
|
||||
func (w *wrapper) CallFunc(ctx context.Context, addr string, req client.Request, rsp interface{}, opts client.CallOptions) error {
|
||||
endpoint := fmt.Sprintf("%s.%s", req.Service(), req.Endpoint())
|
||||
for _, ep := range w.opts.SkipEndpoints {
|
||||
if ep == endpoint {
|
||||
return w.callFunc(ctx, addr, req, rsp, opts)
|
||||
}
|
||||
}
|
||||
|
||||
labels := make([]string, 0, 4)
|
||||
labels = append(labels, labelEndpoint, endpoint)
|
||||
|
||||
w.opts.Meter.Counter(ClientRequestInflight, labels...).Inc()
|
||||
ts := time.Now()
|
||||
err := w.callFunc(ctx, addr, req, rsp, opts)
|
||||
te := time.Since(ts)
|
||||
w.opts.Meter.Counter(ClientRequestInflight, labels...).Dec()
|
||||
|
||||
lopts := w.opts.lopts
|
||||
lopts = append(lopts, meter.Labels(labelEndpoint, endpoint))
|
||||
|
||||
w.opts.Meter.Summary(ClientRequestLatencyMicroseconds, lopts...).Update(float64(te.Seconds()))
|
||||
w.opts.Meter.Histogram(ClientRequestDurationSeconds, lopts...).Update(float64(te.Seconds()))
|
||||
w.opts.Meter.Summary(ClientRequestLatencyMicroseconds, labels...).Update(te.Seconds())
|
||||
w.opts.Meter.Histogram(ClientRequestDurationSeconds, labels...).Update(te.Seconds())
|
||||
|
||||
if err == nil {
|
||||
lopts = append(lopts, meter.Labels(labelStatus, labelSuccess))
|
||||
labels = append(labels, labelStatus, labelSuccess)
|
||||
} else {
|
||||
lopts = append(lopts, meter.Labels(labelStatus, labelFailure))
|
||||
labels = append(labels, labelStatus, labelFailure)
|
||||
}
|
||||
w.opts.Meter.Counter(ClientRequestTotal, lopts...).Inc()
|
||||
w.opts.Meter.Counter(ClientRequestTotal, labels...).Inc()
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (w *wrapper) Call(ctx context.Context, req client.Request, rsp interface{}, opts ...client.CallOption) error {
|
||||
endpoint := fmt.Sprintf("%s.%s", req.Service(), req.Endpoint())
|
||||
for _, ep := range w.opts.SkipEndpoints {
|
||||
if ep == endpoint {
|
||||
return w.Client.Call(ctx, req, rsp, opts...)
|
||||
}
|
||||
}
|
||||
|
||||
labels := make([]string, 0, 4)
|
||||
labels = append(labels, labelEndpoint, endpoint)
|
||||
|
||||
w.opts.Meter.Counter(ClientRequestInflight, labels...).Inc()
|
||||
ts := time.Now()
|
||||
err := w.Client.Call(ctx, req, rsp, opts...)
|
||||
te := time.Since(ts)
|
||||
w.opts.Meter.Counter(ClientRequestInflight, labels...).Dec()
|
||||
|
||||
lopts := w.opts.lopts
|
||||
lopts = append(lopts, meter.Labels(labelEndpoint, endpoint))
|
||||
|
||||
w.opts.Meter.Summary(ClientRequestLatencyMicroseconds, lopts...).Update(float64(te.Seconds()))
|
||||
w.opts.Meter.Histogram(ClientRequestDurationSeconds, lopts...).Update(float64(te.Seconds()))
|
||||
w.opts.Meter.Summary(ClientRequestLatencyMicroseconds, labels...).Update(te.Seconds())
|
||||
w.opts.Meter.Histogram(ClientRequestDurationSeconds, labels...).Update(te.Seconds())
|
||||
|
||||
if err == nil {
|
||||
lopts = append(lopts, meter.Labels(labelStatus, labelSuccess))
|
||||
labels = append(labels, labelStatus, labelSuccess)
|
||||
} else {
|
||||
lopts = append(lopts, meter.Labels(labelStatus, labelFailure))
|
||||
labels = append(labels, labelStatus, labelFailure)
|
||||
}
|
||||
w.opts.Meter.Counter(ClientRequestTotal, lopts...).Inc()
|
||||
w.opts.Meter.Counter(ClientRequestTotal, labels...).Inc()
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (w *wrapper) Stream(ctx context.Context, req client.Request, opts ...client.CallOption) (client.Stream, error) {
|
||||
endpoint := fmt.Sprintf("%s.%s", req.Service(), req.Endpoint())
|
||||
for _, ep := range w.opts.SkipEndpoints {
|
||||
if ep == endpoint {
|
||||
return w.Client.Stream(ctx, req, opts...)
|
||||
}
|
||||
}
|
||||
|
||||
labels := make([]string, 0, 4)
|
||||
labels = append(labels, labelEndpoint, endpoint)
|
||||
|
||||
w.opts.Meter.Counter(ClientRequestInflight, labels...).Inc()
|
||||
ts := time.Now()
|
||||
stream, err := w.Client.Stream(ctx, req, opts...)
|
||||
te := time.Since(ts)
|
||||
w.opts.Meter.Counter(ClientRequestInflight, labels...).Dec()
|
||||
|
||||
lopts := w.opts.lopts
|
||||
lopts = append(lopts, meter.Labels(labelEndpoint, endpoint))
|
||||
|
||||
w.opts.Meter.Summary(ClientRequestLatencyMicroseconds, lopts...).Update(float64(te.Seconds()))
|
||||
w.opts.Meter.Histogram(ClientRequestDurationSeconds, lopts...).Update(float64(te.Seconds()))
|
||||
w.opts.Meter.Summary(ClientRequestLatencyMicroseconds, labels...).Update(te.Seconds())
|
||||
w.opts.Meter.Histogram(ClientRequestDurationSeconds, labels...).Update(te.Seconds())
|
||||
|
||||
if err == nil {
|
||||
lopts = append(lopts, meter.Labels(labelStatus, labelSuccess))
|
||||
labels = append(labels, labelStatus, labelSuccess)
|
||||
} else {
|
||||
lopts = append(lopts, meter.Labels(labelStatus, labelFailure))
|
||||
labels = append(labels, labelStatus, labelFailure)
|
||||
}
|
||||
w.opts.Meter.Counter(ClientRequestTotal, lopts...).Inc()
|
||||
w.opts.Meter.Counter(ClientRequestTotal, labels...).Inc()
|
||||
|
||||
return stream, err
|
||||
}
|
||||
@@ -170,22 +209,24 @@ func (w *wrapper) Stream(ctx context.Context, req client.Request, opts ...client
|
||||
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()
|
||||
|
||||
lopts := w.opts.lopts
|
||||
lopts = append(lopts, meter.Labels(labelEndpoint, endpoint))
|
||||
|
||||
w.opts.Meter.Summary(PublishMessageLatencyMicroseconds, lopts...).Update(float64(te.Seconds()))
|
||||
w.opts.Meter.Histogram(PublishMessageDurationSeconds, lopts...).Update(float64(te.Seconds()))
|
||||
w.opts.Meter.Summary(PublishMessageLatencyMicroseconds, labels...).Update(te.Seconds())
|
||||
w.opts.Meter.Histogram(PublishMessageDurationSeconds, labels...).Update(te.Seconds())
|
||||
|
||||
if err == nil {
|
||||
lopts = append(lopts, meter.Labels(labelStatus, labelSuccess))
|
||||
labels = append(labels, labelStatus, labelSuccess)
|
||||
} else {
|
||||
lopts = append(lopts, meter.Labels(labelStatus, labelFailure))
|
||||
labels = append(labels, labelStatus, labelFailure)
|
||||
}
|
||||
w.opts.Meter.Counter(PublishMessageTotal, lopts...).Inc()
|
||||
w.opts.Meter.Counter(PublishMessageTotal, labels...).Inc()
|
||||
|
||||
return err
|
||||
}
|
||||
@@ -200,23 +241,30 @@ func NewHandlerWrapper(opts ...Option) server.HandlerWrapper {
|
||||
func (w *wrapper) HandlerFunc(fn server.HandlerFunc) server.HandlerFunc {
|
||||
return func(ctx context.Context, req server.Request, rsp interface{}) error {
|
||||
endpoint := req.Endpoint()
|
||||
for _, ep := range w.opts.SkipEndpoints {
|
||||
if ep == endpoint {
|
||||
return fn(ctx, req, rsp)
|
||||
}
|
||||
}
|
||||
|
||||
labels := make([]string, 0, 4)
|
||||
labels = append(labels, labelEndpoint, endpoint)
|
||||
|
||||
w.opts.Meter.Counter(ServerRequestInflight, labels...).Inc()
|
||||
ts := time.Now()
|
||||
err := fn(ctx, req, rsp)
|
||||
te := time.Since(ts)
|
||||
w.opts.Meter.Counter(ServerRequestInflight, labels...).Dec()
|
||||
|
||||
lopts := w.opts.lopts
|
||||
lopts = append(lopts, meter.Labels(labelEndpoint, endpoint))
|
||||
|
||||
w.opts.Meter.Summary(ServerRequestLatencyMicroseconds, lopts...).Update(float64(te.Seconds()))
|
||||
w.opts.Meter.Histogram(ServerRequestDurationSeconds, lopts...).Update(float64(te.Seconds()))
|
||||
w.opts.Meter.Summary(ServerRequestLatencyMicroseconds, labels...).Update(te.Seconds())
|
||||
w.opts.Meter.Histogram(ServerRequestDurationSeconds, labels...).Update(te.Seconds())
|
||||
|
||||
if err == nil {
|
||||
lopts = append(lopts, meter.Labels(labelStatus, labelSuccess))
|
||||
labels = append(labels, labelStatus, labelSuccess)
|
||||
} else {
|
||||
lopts = append(lopts, meter.Labels(labelStatus, labelFailure))
|
||||
labels = append(labels, labelStatus, labelFailure)
|
||||
}
|
||||
w.opts.Meter.Counter(ServerRequestTotal, lopts...).Inc()
|
||||
w.opts.Meter.Counter(ServerRequestTotal, labels...).Inc()
|
||||
|
||||
return err
|
||||
}
|
||||
@@ -233,22 +281,24 @@ 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()
|
||||
|
||||
lopts := w.opts.lopts
|
||||
lopts = append(lopts, meter.Labels(labelEndpoint, endpoint))
|
||||
|
||||
w.opts.Meter.Summary(SubscribeMessageLatencyMicroseconds, lopts...).Update(float64(te.Seconds()))
|
||||
w.opts.Meter.Histogram(SubscribeMessageDurationSeconds, lopts...).Update(float64(te.Seconds()))
|
||||
w.opts.Meter.Summary(SubscribeMessageLatencyMicroseconds, labels...).Update(te.Seconds())
|
||||
w.opts.Meter.Histogram(SubscribeMessageDurationSeconds, labels...).Update(te.Seconds())
|
||||
|
||||
if err == nil {
|
||||
lopts = append(lopts, meter.Labels(labelStatus, labelSuccess))
|
||||
labels = append(labels, labelStatus, labelSuccess)
|
||||
} else {
|
||||
lopts = append(lopts, meter.Labels(labelStatus, labelFailure))
|
||||
labels = append(labels, labelStatus, labelFailure)
|
||||
}
|
||||
w.opts.Meter.Counter(SubscribeMessageTotal, lopts...).Inc()
|
||||
w.opts.Meter.Counter(SubscribeMessageTotal, labels...).Inc()
|
||||
|
||||
return err
|
||||
}
|
||||
|
@@ -31,18 +31,18 @@ type memoryClient struct {
|
||||
}
|
||||
|
||||
type memoryListener struct {
|
||||
topts Options
|
||||
ctx context.Context
|
||||
lopts ListenOptions
|
||||
ctx context.Context
|
||||
exit chan bool
|
||||
conn chan *memorySocket
|
||||
addr string
|
||||
topts Options
|
||||
sync.RWMutex
|
||||
}
|
||||
|
||||
type memoryTransport struct {
|
||||
opts Options
|
||||
listeners map[string]*memoryListener
|
||||
opts Options
|
||||
sync.RWMutex
|
||||
}
|
||||
|
||||
|
@@ -27,9 +27,9 @@ func TestMemoryTransport(t *testing.T) {
|
||||
if len(os.Getenv("INTEGRATION_TESTS")) == 0 {
|
||||
t.Logf("Server Received %s", string(m.Body))
|
||||
}
|
||||
if err := sock.Send(&Message{
|
||||
if cerr := sock.Send(&Message{
|
||||
Body: []byte(`pong`),
|
||||
}); err != nil {
|
||||
}); cerr != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -60,7 +60,6 @@ func TestMemoryTransport(t *testing.T) {
|
||||
t.Logf("Client Received %s", string(m.Body))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestListener(t *testing.T) {
|
||||
|
@@ -12,16 +12,16 @@ import (
|
||||
)
|
||||
|
||||
type tunBroker struct {
|
||||
opts broker.Options
|
||||
tunnel tunnel.Tunnel
|
||||
opts broker.Options
|
||||
}
|
||||
|
||||
type tunSubscriber struct {
|
||||
opts broker.SubscribeOptions
|
||||
listener tunnel.Listener
|
||||
handler broker.Handler
|
||||
closed chan bool
|
||||
topic string
|
||||
opts broker.SubscribeOptions
|
||||
}
|
||||
|
||||
type tunEvent struct {
|
||||
@@ -30,8 +30,10 @@ type tunEvent struct {
|
||||
}
|
||||
|
||||
// used to access tunnel from options context
|
||||
type tunnelKey struct{}
|
||||
type tunnelAddr struct{}
|
||||
type (
|
||||
tunnelKey struct{}
|
||||
tunnelAddr struct{}
|
||||
)
|
||||
|
||||
func (t *tunBroker) Init(opts ...broker.Option) error {
|
||||
for _, o := range opts {
|
||||
|
@@ -34,8 +34,8 @@ type Options struct {
|
||||
Token string
|
||||
// Name holds the tunnel name
|
||||
Name string
|
||||
// Id holds the tunnel id
|
||||
Id string
|
||||
// ID holds the tunnel id
|
||||
ID string
|
||||
// Address holds the tunnel address
|
||||
Address string
|
||||
// Nodes holds the tunnel nodes
|
||||
@@ -68,10 +68,10 @@ type ListenOptions struct {
|
||||
Timeout time.Duration
|
||||
}
|
||||
|
||||
// Id sets the tunnel id
|
||||
func Id(id string) Option {
|
||||
// ID sets the tunnel id
|
||||
func ID(id string) Option {
|
||||
return func(o *Options) {
|
||||
o.Id = id
|
||||
o.ID = id
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,7 +164,7 @@ func DialWait(b bool) DialOption {
|
||||
// NewOptions returns router default options with filled values
|
||||
func NewOptions(opts ...Option) Options {
|
||||
options := Options{
|
||||
Id: uuid.New().String(),
|
||||
ID: uuid.New().String(),
|
||||
Address: DefaultAddress,
|
||||
Token: DefaultToken,
|
||||
Logger: logger.DefaultLogger,
|
||||
|
@@ -10,9 +10,8 @@ import (
|
||||
)
|
||||
|
||||
type tunTransport struct {
|
||||
tunnel tunnel.Tunnel
|
||||
options transport.Options
|
||||
|
||||
tunnel tunnel.Tunnel
|
||||
}
|
||||
|
||||
type tunnelKey struct{}
|
||||
@@ -88,7 +87,7 @@ func NewTransport(opts ...transport.Option) transport.Transport {
|
||||
}
|
||||
|
||||
// initialise
|
||||
//t.Init(opts...)
|
||||
// t.Init(opts...)
|
||||
|
||||
return t
|
||||
}
|
||||
|
@@ -9,10 +9,8 @@ import (
|
||||
"github.com/unistack-org/micro/v3/network/transport"
|
||||
)
|
||||
|
||||
var (
|
||||
// DefaultTunnel contains default tunnel implementation
|
||||
DefaultTunnel Tunnel
|
||||
)
|
||||
// DefaultTunnel contains default tunnel implementation
|
||||
var DefaultTunnel Tunnel
|
||||
|
||||
const (
|
||||
// Unicast send over one link
|
||||
|
@@ -17,8 +17,6 @@ import (
|
||||
"github.com/unistack-org/micro/v3/server"
|
||||
"github.com/unistack-org/micro/v3/store"
|
||||
"github.com/unistack-org/micro/v3/tracer"
|
||||
// "github.com/unistack-org/micro/v3/profiler"
|
||||
// "github.com/unistack-org/micro/v3/runtime"
|
||||
)
|
||||
|
||||
// Options for micro service
|
||||
@@ -78,8 +76,8 @@ func NewOptions(opts ...Option) Options {
|
||||
Meters: []meter.Meter{meter.DefaultMeter},
|
||||
Configs: []config.Config{config.DefaultConfig},
|
||||
Stores: []store.Store{store.DefaultStore},
|
||||
//Runtime runtime.Runtime
|
||||
//Profile profile.Profile
|
||||
// Runtime runtime.Runtime
|
||||
// Profile profile.Profile
|
||||
}
|
||||
|
||||
for _, o := range opts {
|
||||
|
@@ -16,10 +16,8 @@ type httpProfile struct {
|
||||
running bool
|
||||
}
|
||||
|
||||
var (
|
||||
// DefaultAddress for http profiler
|
||||
DefaultAddress = ":6060"
|
||||
)
|
||||
// DefaultAddress for http profiler
|
||||
var DefaultAddress = ":6060"
|
||||
|
||||
// Start the profiler
|
||||
func (h *httpProfile) Start() error {
|
||||
|
@@ -11,10 +11,8 @@ type Profiler interface {
|
||||
String() string
|
||||
}
|
||||
|
||||
var (
|
||||
// DefaultProfiler holds the default profiler
|
||||
DefaultProfiler Profiler = NewProfiler()
|
||||
)
|
||||
// DefaultProfiler holds the default profiler
|
||||
var DefaultProfiler Profiler = NewProfiler()
|
||||
|
||||
// Options holds the options for profiler
|
||||
type Options struct {
|
||||
|
@@ -7,10 +7,8 @@ import (
|
||||
"github.com/unistack-org/micro/v3/server"
|
||||
)
|
||||
|
||||
var (
|
||||
// DefaultEndpoint holds default proxy address
|
||||
DefaultEndpoint = "localhost:9090"
|
||||
)
|
||||
// DefaultEndpoint holds default proxy address
|
||||
var DefaultEndpoint = "localhost:9090"
|
||||
|
||||
// Proxy can be used as a proxy server for micro services
|
||||
type Proxy interface {
|
||||
|
@@ -3,7 +3,6 @@ package register
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
|
||||
@@ -11,12 +10,12 @@ import (
|
||||
)
|
||||
|
||||
// ExtractValue from reflect.Type from specified depth
|
||||
func ExtractValue(v reflect.Type, d int) *Value {
|
||||
func ExtractValue(v reflect.Type, d int) string {
|
||||
if d == 3 {
|
||||
return nil
|
||||
return ""
|
||||
}
|
||||
if v == nil {
|
||||
return nil
|
||||
return ""
|
||||
}
|
||||
|
||||
if v.Kind() == reflect.Ptr {
|
||||
@@ -25,7 +24,7 @@ func ExtractValue(v reflect.Type, d int) *Value {
|
||||
|
||||
// slices and maps don't have a defined name
|
||||
if (v.Kind() == reflect.Slice || v.Kind() == reflect.Map) || len(v.Name()) == 0 {
|
||||
return nil
|
||||
return ""
|
||||
}
|
||||
|
||||
// get the rune character
|
||||
@@ -33,58 +32,10 @@ func ExtractValue(v reflect.Type, d int) *Value {
|
||||
|
||||
// crude check for is unexported field
|
||||
if unicode.IsLower(a) {
|
||||
return nil
|
||||
return ""
|
||||
}
|
||||
|
||||
arg := &Value{
|
||||
Name: v.Name(),
|
||||
Type: v.Name(),
|
||||
}
|
||||
|
||||
switch v.Kind() {
|
||||
case reflect.Struct:
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
f := v.Field(i)
|
||||
val := ExtractValue(f.Type, d+1)
|
||||
if val == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// if we can find a json tag use it
|
||||
if tags := f.Tag.Get("json"); len(tags) > 0 {
|
||||
parts := strings.Split(tags, ",")
|
||||
if parts[0] == "-" || parts[0] == "omitempty" {
|
||||
continue
|
||||
}
|
||||
val.Name = parts[0]
|
||||
}
|
||||
|
||||
// if there's no name default it
|
||||
if len(val.Name) == 0 {
|
||||
val.Name = v.Field(i).Name
|
||||
}
|
||||
|
||||
arg.Values = append(arg.Values, val)
|
||||
}
|
||||
case reflect.Slice:
|
||||
p := v.Elem()
|
||||
if p.Kind() == reflect.Ptr {
|
||||
p = p.Elem()
|
||||
}
|
||||
arg.Type = "[]" + p.Name()
|
||||
case reflect.Map:
|
||||
p := v.Elem()
|
||||
if p.Kind() == reflect.Ptr {
|
||||
p = p.Elem()
|
||||
}
|
||||
key := v.Key()
|
||||
if key.Kind() == reflect.Ptr {
|
||||
key = key.Elem()
|
||||
}
|
||||
arg.Type = fmt.Sprintf("map[%s]%s", key.Name(), p.Name())
|
||||
}
|
||||
|
||||
return arg
|
||||
return v.Name()
|
||||
}
|
||||
|
||||
// ExtractEndpoint extract *Endpoint from reflect.Method
|
||||
@@ -116,7 +67,7 @@ func ExtractEndpoint(method reflect.Method) *Endpoint {
|
||||
|
||||
request := ExtractValue(reqType, 0)
|
||||
response := ExtractValue(rspType, 0)
|
||||
if request == nil || response == nil {
|
||||
if request == "" || response == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -135,7 +86,7 @@ func ExtractEndpoint(method reflect.Method) *Endpoint {
|
||||
}
|
||||
|
||||
// ExtractSubValue exctact *Value from reflect.Type
|
||||
func ExtractSubValue(typ reflect.Type) *Value {
|
||||
func ExtractSubValue(typ reflect.Type) string {
|
||||
var reqType reflect.Type
|
||||
switch typ.NumIn() {
|
||||
case 1:
|
||||
@@ -145,7 +96,7 @@ func ExtractSubValue(typ reflect.Type) *Value {
|
||||
case 3:
|
||||
reqType = typ.In(2)
|
||||
default:
|
||||
return nil
|
||||
return ""
|
||||
}
|
||||
return ExtractValue(reqType, 0)
|
||||
}
|
||||
|
@@ -36,28 +36,21 @@ func TestExtractEndpoint(t *testing.T) {
|
||||
t.Fatalf("Expected handler Test, got %s", endpoints[0].Name)
|
||||
}
|
||||
|
||||
if endpoints[0].Request == nil {
|
||||
if endpoints[0].Request == "" {
|
||||
t.Fatal("Expected non nil Request")
|
||||
}
|
||||
|
||||
if endpoints[0].Response == nil {
|
||||
if endpoints[0].Response == "" {
|
||||
t.Fatal("Expected non nil Request")
|
||||
}
|
||||
|
||||
if endpoints[0].Request.Name != "TestRequest" {
|
||||
t.Fatalf("Expected TestRequest got %s", endpoints[0].Request.Name)
|
||||
if endpoints[0].Request != "TestRequest" {
|
||||
t.Fatalf("Expected TestRequest got %s", endpoints[0].Request)
|
||||
}
|
||||
|
||||
if endpoints[0].Response.Name != "TestResponse" {
|
||||
t.Fatalf("Expected TestResponse got %s", endpoints[0].Response.Name)
|
||||
}
|
||||
|
||||
if endpoints[0].Request.Type != "TestRequest" {
|
||||
t.Fatalf("Expected TestRequest type got %s", endpoints[0].Request.Type)
|
||||
}
|
||||
|
||||
if endpoints[0].Response.Type != "TestResponse" {
|
||||
t.Fatalf("Expected TestResponse type got %s", endpoints[0].Response.Type)
|
||||
if endpoints[0].Response != "TestResponse" {
|
||||
t.Fatalf("Expected TestResponse got %s", endpoints[0].Response)
|
||||
}
|
||||
|
||||
t.Logf("XXX %#+v\n", endpoints[0])
|
||||
}
|
||||
|
@@ -30,10 +30,9 @@ type record struct {
|
||||
}
|
||||
|
||||
type memory struct {
|
||||
opts Options
|
||||
// records is a KV map with domain name as the key and a services map as the value
|
||||
records map[string]services
|
||||
watchers map[string]*watcher
|
||||
opts Options
|
||||
sync.RWMutex
|
||||
}
|
||||
|
||||
@@ -65,7 +64,7 @@ func (m *memory) ttlPrune() {
|
||||
for id, n := range record.Nodes {
|
||||
if n.TTL != 0 && time.Since(n.LastSeen) > n.TTL {
|
||||
if m.opts.Logger.V(logger.DebugLevel) {
|
||||
m.opts.Logger.Debugf(m.opts.Context, "Register TTL expired for node %s of service %s", n.Id, service)
|
||||
m.opts.Logger.Debugf(m.opts.Context, "Register TTL expired for node %s of service %s", n.ID, service)
|
||||
}
|
||||
delete(m.records[domain][service][version].Nodes, id)
|
||||
}
|
||||
@@ -162,7 +161,7 @@ func (m *memory) Register(ctx context.Context, s *Service, opts ...RegisterOptio
|
||||
|
||||
for _, n := range s.Nodes {
|
||||
// check if already exists
|
||||
if _, ok := srvs[s.Name][s.Version].Nodes[n.Id]; ok {
|
||||
if _, ok := srvs[s.Name][s.Version].Nodes[n.ID]; ok {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -177,9 +176,9 @@ func (m *memory) Register(ctx context.Context, s *Service, opts ...RegisterOptio
|
||||
metadata["domain"] = options.Domain
|
||||
|
||||
// add the node
|
||||
srvs[s.Name][s.Version].Nodes[n.Id] = &node{
|
||||
srvs[s.Name][s.Version].Nodes[n.ID] = &node{
|
||||
Node: &Node{
|
||||
Id: n.Id,
|
||||
ID: n.ID,
|
||||
Address: n.Address,
|
||||
Metadata: metadata,
|
||||
},
|
||||
@@ -201,8 +200,8 @@ func (m *memory) Register(ctx context.Context, s *Service, opts ...RegisterOptio
|
||||
if m.opts.Logger.V(logger.DebugLevel) {
|
||||
m.opts.Logger.Debugf(m.opts.Context, "Updated registration for service: %s, version: %s", s.Name, s.Version)
|
||||
}
|
||||
srvs[s.Name][s.Version].Nodes[n.Id].TTL = options.TTL
|
||||
srvs[s.Name][s.Version].Nodes[n.Id].LastSeen = time.Now()
|
||||
srvs[s.Name][s.Version].Nodes[n.ID].TTL = options.TTL
|
||||
srvs[s.Name][s.Version].Nodes[n.ID].LastSeen = time.Now()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,11 +241,11 @@ func (m *memory) Deregister(ctx context.Context, s *Service, opts ...DeregisterO
|
||||
|
||||
// deregister all of the service nodes from this version
|
||||
for _, n := range s.Nodes {
|
||||
if _, ok := version.Nodes[n.Id]; ok {
|
||||
if _, ok := version.Nodes[n.ID]; ok {
|
||||
if m.opts.Logger.V(logger.DebugLevel) {
|
||||
m.opts.Logger.Debugf(m.opts.Context, "Register removed node from service: %s, version: %s", s.Name, s.Version)
|
||||
}
|
||||
delete(version.Nodes, n.Id)
|
||||
delete(version.Nodes, n.ID)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -458,7 +457,7 @@ func serviceToRecord(s *Service, ttl time.Duration) *record {
|
||||
|
||||
nodes := make(map[string]*node, len(s.Nodes))
|
||||
for _, n := range s.Nodes {
|
||||
nodes[n.Id] = &node{
|
||||
nodes[n.ID] = &node{
|
||||
Node: n,
|
||||
TTL: ttl,
|
||||
LastSeen: time.Now(),
|
||||
@@ -490,40 +489,31 @@ func recordToService(r *record, domain string) *Service {
|
||||
|
||||
endpoints := make([]*Endpoint, len(r.Endpoints))
|
||||
for i, e := range r.Endpoints {
|
||||
request := new(Value)
|
||||
if e.Request != nil {
|
||||
*request = *e.Request
|
||||
}
|
||||
response := new(Value)
|
||||
if e.Response != nil {
|
||||
*response = *e.Response
|
||||
}
|
||||
|
||||
metadata := make(map[string]string, len(e.Metadata))
|
||||
md := make(map[string]string, len(e.Metadata))
|
||||
for k, v := range e.Metadata {
|
||||
metadata[k] = v
|
||||
md[k] = v
|
||||
}
|
||||
|
||||
endpoints[i] = &Endpoint{
|
||||
Name: e.Name,
|
||||
Request: request,
|
||||
Response: response,
|
||||
Metadata: metadata,
|
||||
Request: e.Request,
|
||||
Response: e.Response,
|
||||
Metadata: md,
|
||||
}
|
||||
}
|
||||
|
||||
nodes := make([]*Node, len(r.Nodes))
|
||||
i := 0
|
||||
for _, n := range r.Nodes {
|
||||
metadata := make(map[string]string, len(n.Metadata))
|
||||
md := make(map[string]string, len(n.Metadata))
|
||||
for k, v := range n.Metadata {
|
||||
metadata[k] = v
|
||||
md[k] = v
|
||||
}
|
||||
|
||||
nodes[i] = &Node{
|
||||
Id: n.Id,
|
||||
ID: n.ID,
|
||||
Address: n.Address,
|
||||
Metadata: metadata,
|
||||
Metadata: md,
|
||||
}
|
||||
i++
|
||||
}
|
||||
|
@@ -8,72 +8,70 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
testData = map[string][]*Service{
|
||||
"foo": {
|
||||
{
|
||||
Name: "foo",
|
||||
Version: "1.0.0",
|
||||
Nodes: []*Node{
|
||||
{
|
||||
Id: "foo-1.0.0-123",
|
||||
Address: "localhost:9999",
|
||||
},
|
||||
{
|
||||
Id: "foo-1.0.0-321",
|
||||
Address: "localhost:9999",
|
||||
},
|
||||
var testData = map[string][]*Service{
|
||||
"foo": {
|
||||
{
|
||||
Name: "foo",
|
||||
Version: "1.0.0",
|
||||
Nodes: []*Node{
|
||||
{
|
||||
ID: "foo-1.0.0-123",
|
||||
Address: "localhost:9999",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "foo",
|
||||
Version: "1.0.1",
|
||||
Nodes: []*Node{
|
||||
{
|
||||
Id: "foo-1.0.1-321",
|
||||
Address: "localhost:6666",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "foo",
|
||||
Version: "1.0.3",
|
||||
Nodes: []*Node{
|
||||
{
|
||||
Id: "foo-1.0.3-345",
|
||||
Address: "localhost:8888",
|
||||
},
|
||||
{
|
||||
ID: "foo-1.0.0-321",
|
||||
Address: "localhost:9999",
|
||||
},
|
||||
},
|
||||
},
|
||||
"bar": {
|
||||
{
|
||||
Name: "bar",
|
||||
Version: "default",
|
||||
Nodes: []*Node{
|
||||
{
|
||||
Id: "bar-1.0.0-123",
|
||||
Address: "localhost:9999",
|
||||
},
|
||||
{
|
||||
Id: "bar-1.0.0-321",
|
||||
Address: "localhost:9999",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "bar",
|
||||
Version: "latest",
|
||||
Nodes: []*Node{
|
||||
{
|
||||
Id: "bar-1.0.1-321",
|
||||
Address: "localhost:6666",
|
||||
},
|
||||
{
|
||||
Name: "foo",
|
||||
Version: "1.0.1",
|
||||
Nodes: []*Node{
|
||||
{
|
||||
ID: "foo-1.0.1-321",
|
||||
Address: "localhost:6666",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
{
|
||||
Name: "foo",
|
||||
Version: "1.0.3",
|
||||
Nodes: []*Node{
|
||||
{
|
||||
ID: "foo-1.0.3-345",
|
||||
Address: "localhost:8888",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"bar": {
|
||||
{
|
||||
Name: "bar",
|
||||
Version: "default",
|
||||
Nodes: []*Node{
|
||||
{
|
||||
ID: "bar-1.0.0-123",
|
||||
Address: "localhost:9999",
|
||||
},
|
||||
{
|
||||
ID: "bar-1.0.0-321",
|
||||
Address: "localhost:9999",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "bar",
|
||||
Version: "latest",
|
||||
Nodes: []*Node{
|
||||
{
|
||||
ID: "bar-1.0.1-321",
|
||||
Address: "localhost:6666",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
//nolint:gocyclo
|
||||
func TestMemoryRegistry(t *testing.T) {
|
||||
|
@@ -44,6 +44,7 @@ func NewOptions(opts ...Option) Options {
|
||||
return options
|
||||
}
|
||||
|
||||
// nolint: golint
|
||||
// RegisterOptions holds options for register method
|
||||
type RegisterOptions struct {
|
||||
Context context.Context
|
||||
@@ -196,6 +197,7 @@ func TLSConfig(t *tls.Config) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// nolint: golint
|
||||
// RegisterAttempts specifies register atempts count
|
||||
func RegisterAttempts(t int) RegisterOption {
|
||||
return func(o *RegisterOptions) {
|
||||
@@ -203,6 +205,7 @@ func RegisterAttempts(t int) RegisterOption {
|
||||
}
|
||||
}
|
||||
|
||||
// nolint: golint
|
||||
// RegisterTTL specifies register ttl
|
||||
func RegisterTTL(t time.Duration) RegisterOption {
|
||||
return func(o *RegisterOptions) {
|
||||
@@ -210,6 +213,7 @@ func RegisterTTL(t time.Duration) RegisterOption {
|
||||
}
|
||||
}
|
||||
|
||||
// nolint: golint
|
||||
// RegisterContext sets the register context
|
||||
func RegisterContext(ctx context.Context) RegisterOption {
|
||||
return func(o *RegisterOptions) {
|
||||
@@ -217,6 +221,7 @@ func RegisterContext(ctx context.Context) RegisterOption {
|
||||
}
|
||||
}
|
||||
|
||||
// nolint: golint
|
||||
// RegisterDomain secifies register domain
|
||||
func RegisterDomain(d string) RegisterOption {
|
||||
return func(o *RegisterOptions) {
|
||||
|
@@ -53,29 +53,23 @@ type Service struct {
|
||||
// Node holds node register info
|
||||
type Node struct {
|
||||
Metadata metadata.Metadata `json:"metadata"`
|
||||
Id string `json:"id"`
|
||||
ID string `json:"id"`
|
||||
Address string `json:"address"`
|
||||
}
|
||||
|
||||
// Endpoint holds endpoint register info
|
||||
type Endpoint struct {
|
||||
Request *Value `json:"request"`
|
||||
Response *Value `json:"response"`
|
||||
Request string `json:"request"`
|
||||
Response string `json:"response"`
|
||||
Metadata metadata.Metadata `json:"metadata"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// Value holds additional kv stuff
|
||||
type Value struct {
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
Values []*Value `json:"values"`
|
||||
}
|
||||
|
||||
// Option func signature
|
||||
type Option func(*Options)
|
||||
|
||||
// RegisterOption option is used to register service
|
||||
// nolint: golint
|
||||
type RegisterOption func(*RegisterOptions)
|
||||
|
||||
// WatchOption option is used to watch service changes
|
||||
|
@@ -52,8 +52,8 @@ type Event struct {
|
||||
Timestamp time.Time
|
||||
// Service is register service
|
||||
Service *Service
|
||||
// Id is register id
|
||||
Id string
|
||||
// ID is register id
|
||||
ID string
|
||||
// Type defines type of event
|
||||
Type EventType
|
||||
}
|
||||
|
91
router/dns.go
Normal file
91
router/dns.go
Normal file
@@ -0,0 +1,91 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// NewRouter returns an initialized dns router
|
||||
func NewRouter(opts ...Option) Router {
|
||||
options := NewOptions(opts...)
|
||||
return &dns{options}
|
||||
}
|
||||
|
||||
type dns struct {
|
||||
options Options
|
||||
}
|
||||
|
||||
func (d *dns) Init(opts ...Option) error {
|
||||
for _, o := range opts {
|
||||
o(&d.options)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *dns) Options() Options {
|
||||
return d.options
|
||||
}
|
||||
|
||||
func (d *dns) Table() Table {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *dns) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *dns) Lookup(opts ...QueryOption) ([]Route, error) {
|
||||
options := NewQuery(opts...)
|
||||
// check to see if we have the port provided in the service, e.g. go-micro-srv-foo:8000
|
||||
host, port, err := net.SplitHostPort(options.Service)
|
||||
if err == nil {
|
||||
// lookup the service using A records
|
||||
ips, err := net.LookupHost(host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
p, _ := strconv.Atoi(port)
|
||||
|
||||
// convert the ip addresses to routes
|
||||
result := make([]Route, len(ips))
|
||||
for i, ip := range ips {
|
||||
result[i] = Route{
|
||||
Service: options.Service,
|
||||
Address: fmt.Sprintf("%s:%d", ip, uint16(p)),
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// we didn't get the port so we'll lookup the service using SRV records. If we can't lookup the
|
||||
// service using the SRV record, we return the error.
|
||||
_, nodes, err := net.LookupSRV(options.Service, "tcp", d.options.Network)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// convert the nodes (net services) to routes
|
||||
result := make([]Route, len(nodes))
|
||||
for i, n := range nodes {
|
||||
result[i] = Route{
|
||||
Service: options.Service,
|
||||
Address: fmt.Sprintf("%s:%d", n.Target, n.Port),
|
||||
Network: d.options.Network,
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (d *dns) Watch(opts ...WatchOption) (Watcher, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (d *dns) Name() string {
|
||||
return d.options.Name
|
||||
}
|
||||
|
||||
func (d *dns) String() string {
|
||||
return "dns"
|
||||
}
|
@@ -7,7 +7,7 @@ import (
|
||||
|
||||
var (
|
||||
// DefaultRouter is the global default router
|
||||
DefaultRouter Router
|
||||
DefaultRouter Router = NewRouter()
|
||||
// DefaultNetwork is default micro network
|
||||
DefaultNetwork = "micro"
|
||||
// ErrRouteNotFound is returned when no route was found in the routing table
|
||||
|
@@ -5,10 +5,8 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrWatcherStopped is returned when routing table watcher has been stopped
|
||||
ErrWatcherStopped = errors.New("watcher stopped")
|
||||
)
|
||||
// ErrWatcherStopped is returned when routing table watcher has been stopped
|
||||
var ErrWatcherStopped = errors.New("watcher stopped")
|
||||
|
||||
// EventType defines routing table event
|
||||
type EventType int
|
||||
@@ -38,12 +36,12 @@ func (t EventType) String() string {
|
||||
|
||||
// Event is returned by a call to Next on the watcher.
|
||||
type Event struct {
|
||||
// Route is table route
|
||||
Route Route
|
||||
// Timestamp is event timestamp
|
||||
Timestamp time.Time
|
||||
// Id of the event
|
||||
Id string
|
||||
// Route is table route
|
||||
Route Route
|
||||
// Type defines type of event
|
||||
Type EventType
|
||||
}
|
||||
|
@@ -8,10 +8,8 @@ import (
|
||||
"github.com/unistack-org/micro/v3/metadata"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrAlreadyExists error
|
||||
ErrAlreadyExists = errors.New("already exists")
|
||||
)
|
||||
// ErrAlreadyExists error
|
||||
var ErrAlreadyExists = errors.New("already exists")
|
||||
|
||||
// Runtime is a service runtime manager
|
||||
type Runtime interface {
|
||||
|
@@ -5,10 +5,8 @@ import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrNoneAvailable is returned by select when no routes were provided to select from
|
||||
ErrNoneAvailable = errors.New("none available")
|
||||
)
|
||||
// ErrNoneAvailable is returned by select when no routes were provided to select from
|
||||
var ErrNoneAvailable = errors.New("none available")
|
||||
|
||||
// Selector selects a route from a pool
|
||||
type Selector interface {
|
||||
|
3
server/generate.go
Normal file
3
server/generate.go
Normal file
@@ -0,0 +1,3 @@
|
||||
package server
|
||||
|
||||
//go:generate protoc -I./health -I../ -I/home/vtolstov/.cache/go-path/pkg/mod/github.com/unistack-org/micro-proto@v0.0.1 --micro_out=components=micro|http|server,standalone=false,debug=true,paths=source_relative:./health health/health.proto
|
@@ -13,7 +13,7 @@ type rpcHandler struct {
|
||||
endpoints []*register.Endpoint
|
||||
}
|
||||
|
||||
func newRpcHandler(handler interface{}, opts ...HandlerOption) Handler {
|
||||
func newRPCHandler(handler interface{}, opts ...HandlerOption) Handler {
|
||||
options := NewHandlerOptions(opts...)
|
||||
|
||||
typ := reflect.TypeOf(handler)
|
||||
|
82
server/health/health.go
Normal file
82
server/health/health.go
Normal file
@@ -0,0 +1,82 @@
|
||||
package health
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/unistack-org/micro/v3/codec"
|
||||
"github.com/unistack-org/micro/v3/errors"
|
||||
)
|
||||
|
||||
var _ HealthServer = &Handler{}
|
||||
|
||||
type Handler struct {
|
||||
opts Options
|
||||
}
|
||||
|
||||
type CheckFunc func(context.Context) error
|
||||
|
||||
type Option func(*Options)
|
||||
|
||||
type Options struct {
|
||||
Version string
|
||||
Name string
|
||||
LiveChecks []CheckFunc
|
||||
ReadyChecks []CheckFunc
|
||||
}
|
||||
|
||||
func LiveChecks(fns ...CheckFunc) Option {
|
||||
return func(o *Options) {
|
||||
o.LiveChecks = append(o.LiveChecks, fns...)
|
||||
}
|
||||
}
|
||||
|
||||
func ReadyChecks(fns ...CheckFunc) Option {
|
||||
return func(o *Options) {
|
||||
o.ReadyChecks = append(o.ReadyChecks, fns...)
|
||||
}
|
||||
}
|
||||
|
||||
func Name(name string) Option {
|
||||
return func(o *Options) {
|
||||
o.Name = name
|
||||
}
|
||||
}
|
||||
|
||||
func Version(version string) Option {
|
||||
return func(o *Options) {
|
||||
o.Version = version
|
||||
}
|
||||
}
|
||||
|
||||
func NewHandler(opts ...Option) *Handler {
|
||||
options := Options{}
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
}
|
||||
return &Handler{opts: options}
|
||||
}
|
||||
|
||||
func (h *Handler) Live(ctx context.Context, req *codec.Frame, rsp *codec.Frame) error {
|
||||
var err error
|
||||
for _, fn := range h.opts.LiveChecks {
|
||||
if err = fn(ctx); err != nil {
|
||||
return errors.ServiceUnavailable(h.opts.Name, "%v", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *Handler) Ready(ctx context.Context, req *codec.Frame, rsp *codec.Frame) error {
|
||||
var err error
|
||||
for _, fn := range h.opts.ReadyChecks {
|
||||
if err = fn(ctx); err != nil {
|
||||
return errors.ServiceUnavailable(h.opts.Name, "%v", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *Handler) Version(ctx context.Context, req *codec.Frame, rsp *codec.Frame) error {
|
||||
rsp.Data = []byte(h.opts.Version)
|
||||
return nil
|
||||
}
|
62
server/health/health.proto
Normal file
62
server/health/health.proto
Normal file
@@ -0,0 +1,62 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package micro.server.health;
|
||||
option go_package = "github.com/unistack-org/micro/v3/server/health;health";
|
||||
|
||||
import "api/annotations.proto";
|
||||
import "openapiv2/annotations.proto";
|
||||
import "codec/frame.proto";
|
||||
|
||||
service Health {
|
||||
rpc Live(micro.codec.Frame) returns (micro.codec.Frame) {
|
||||
option (micro.openapiv2.openapiv2_operation) = {
|
||||
operation_id: "Live";
|
||||
responses: {
|
||||
key: "default";
|
||||
value: {
|
||||
description: "Error response";
|
||||
schema: {
|
||||
json_schema: {
|
||||
ref: "micro.codec.Frame";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
option (micro.api.http) = { get: "/live"; };
|
||||
};
|
||||
rpc Ready(micro.codec.Frame) returns (micro.codec.Frame) {
|
||||
option (micro.openapiv2.openapiv2_operation) = {
|
||||
operation_id: "Ready";
|
||||
responses: {
|
||||
key: "default";
|
||||
value: {
|
||||
description: "Error response";
|
||||
schema: {
|
||||
json_schema: {
|
||||
ref: "micro.codec.Frame";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
option (micro.api.http) = { get: "/ready"; };
|
||||
};
|
||||
rpc Version(micro.codec.Frame) returns (micro.codec.Frame) {
|
||||
option (micro.openapiv2.openapiv2_operation) = {
|
||||
operation_id: "Version";
|
||||
responses: {
|
||||
key: "default";
|
||||
value: {
|
||||
description: "Error response";
|
||||
schema: {
|
||||
json_schema: {
|
||||
ref: "micro.codec.Frame";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
option (micro.api.http) = { get: "/version"; };
|
||||
};
|
||||
};
|
38
server/health/health_micro.pb.go
Normal file
38
server/health/health_micro.pb.go
Normal file
@@ -0,0 +1,38 @@
|
||||
// Code generated by protoc-gen-micro
|
||||
// source: health.proto
|
||||
package health
|
||||
|
||||
import (
|
||||
context "context"
|
||||
api "github.com/unistack-org/micro/v3/api"
|
||||
codec "github.com/unistack-org/micro/v3/codec"
|
||||
)
|
||||
|
||||
func NewHealthEndpoints() []*api.Endpoint {
|
||||
return []*api.Endpoint{
|
||||
&api.Endpoint{
|
||||
Name: "Health.Live",
|
||||
Path: []string{"/live"},
|
||||
Method: []string{"GET"},
|
||||
Handler: "rpc",
|
||||
},
|
||||
&api.Endpoint{
|
||||
Name: "Health.Ready",
|
||||
Path: []string{"/ready"},
|
||||
Method: []string{"GET"},
|
||||
Handler: "rpc",
|
||||
},
|
||||
&api.Endpoint{
|
||||
Name: "Health.Version",
|
||||
Path: []string{"/version"},
|
||||
Method: []string{"GET"},
|
||||
Handler: "rpc",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type HealthServer interface {
|
||||
Live(ctx context.Context, req *codec.Frame, rsp *codec.Frame) error
|
||||
Ready(ctx context.Context, req *codec.Frame, rsp *codec.Frame) error
|
||||
Version(ctx context.Context, req *codec.Frame, rsp *codec.Frame) error
|
||||
}
|
43
server/health/health_micro_http.pb.go
Normal file
43
server/health/health_micro_http.pb.go
Normal file
@@ -0,0 +1,43 @@
|
||||
// Code generated by protoc-gen-micro
|
||||
// source: health.proto
|
||||
package health
|
||||
|
||||
import (
|
||||
context "context"
|
||||
api "github.com/unistack-org/micro/v3/api"
|
||||
codec "github.com/unistack-org/micro/v3/codec"
|
||||
server "github.com/unistack-org/micro/v3/server"
|
||||
)
|
||||
|
||||
type healthServer struct {
|
||||
HealthServer
|
||||
}
|
||||
|
||||
func (h *healthServer) Live(ctx context.Context, req *codec.Frame, rsp *codec.Frame) error {
|
||||
return h.HealthServer.Live(ctx, req, rsp)
|
||||
}
|
||||
|
||||
func (h *healthServer) Ready(ctx context.Context, req *codec.Frame, rsp *codec.Frame) error {
|
||||
return h.HealthServer.Ready(ctx, req, rsp)
|
||||
}
|
||||
|
||||
func (h *healthServer) Version(ctx context.Context, req *codec.Frame, rsp *codec.Frame) error {
|
||||
return h.HealthServer.Version(ctx, req, rsp)
|
||||
}
|
||||
|
||||
func RegisterHealthServer(s server.Server, sh HealthServer, opts ...server.HandlerOption) error {
|
||||
type health interface {
|
||||
Live(ctx context.Context, req *codec.Frame, rsp *codec.Frame) error
|
||||
Ready(ctx context.Context, req *codec.Frame, rsp *codec.Frame) error
|
||||
Version(ctx context.Context, req *codec.Frame, rsp *codec.Frame) error
|
||||
}
|
||||
type Health struct {
|
||||
health
|
||||
}
|
||||
h := &healthServer{sh}
|
||||
var nopts []server.HandlerOption
|
||||
for _, endpoint := range NewHealthEndpoints() {
|
||||
nopts = append(nopts, api.WithEndpoint(endpoint))
|
||||
}
|
||||
return s.Handle(s.NewHandler(&Health{h}, append(nopts, opts...)...))
|
||||
}
|
@@ -6,9 +6,6 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
// cjson "github.com/unistack-org/micro-codec-json"
|
||||
// cjsonrpc "github.com/unistack-org/micro-codec-jsonrpc"
|
||||
// cproto "github.com/unistack-org/micro-codec-proto"
|
||||
// cprotorpc "github.com/unistack-org/micro-codec-protorpc"
|
||||
"github.com/unistack-org/micro/v3/broker"
|
||||
"github.com/unistack-org/micro/v3/codec"
|
||||
@@ -16,29 +13,23 @@ import (
|
||||
"github.com/unistack-org/micro/v3/register"
|
||||
)
|
||||
|
||||
var (
|
||||
// DefaultCodecs will be used to encode/decode
|
||||
DefaultCodecs = map[string]codec.Codec{
|
||||
//"application/json": cjson.NewCodec,
|
||||
//"application/json-rpc": cjsonrpc.NewCodec,
|
||||
//"application/protobuf": cproto.NewCodec,
|
||||
//"application/proto-rpc": cprotorpc.NewCodec,
|
||||
"application/octet-stream": codec.NewCodec(),
|
||||
}
|
||||
)
|
||||
// DefaultCodecs will be used to encode/decode
|
||||
var DefaultCodecs = map[string]codec.Codec{
|
||||
"application/octet-stream": codec.NewCodec(),
|
||||
}
|
||||
|
||||
const (
|
||||
defaultContentType = "application/json"
|
||||
)
|
||||
|
||||
type noopServer struct {
|
||||
opts Options
|
||||
h Handler
|
||||
wg *sync.WaitGroup
|
||||
rsvc *register.Service
|
||||
handlers map[string]Handler
|
||||
subscribers map[*subscriber][]broker.Subscriber
|
||||
exit chan chan error
|
||||
wg *sync.WaitGroup
|
||||
opts Options
|
||||
sync.RWMutex
|
||||
registered bool
|
||||
started bool
|
||||
@@ -103,7 +94,7 @@ func (n *noopServer) Subscribe(sb Subscriber) error {
|
||||
}
|
||||
|
||||
func (n *noopServer) NewHandler(h interface{}, opts ...HandlerOption) Handler {
|
||||
return newRpcHandler(h, opts...)
|
||||
return newRPCHandler(h, opts...)
|
||||
}
|
||||
|
||||
func (n *noopServer) NewSubscriber(topic string, sb interface{}, opts ...SubscriberOption) Subscriber {
|
||||
@@ -158,23 +149,16 @@ func (n *noopServer) Register() error {
|
||||
}
|
||||
|
||||
n.RLock()
|
||||
// Maps are ordered randomly, sort the keys for consistency
|
||||
var handlerList []string
|
||||
for n, e := range n.handlers {
|
||||
// Only advertise non internal handlers
|
||||
if !e.Options().Internal {
|
||||
handlerList = append(handlerList, n)
|
||||
}
|
||||
handlerList := make([]string, 0, len(n.handlers))
|
||||
for n := range n.handlers {
|
||||
handlerList = append(handlerList, n)
|
||||
}
|
||||
|
||||
sort.Strings(handlerList)
|
||||
|
||||
var subscriberList []*subscriber
|
||||
subscriberList := make([]*subscriber, 0, len(n.subscribers))
|
||||
for e := range n.subscribers {
|
||||
// Only advertise non internal subscribers
|
||||
if !e.Options().Internal {
|
||||
subscriberList = append(subscriberList, e)
|
||||
}
|
||||
subscriberList = append(subscriberList, e)
|
||||
}
|
||||
sort.Slice(subscriberList, func(i, j int) bool {
|
||||
return subscriberList[i].topic > subscriberList[j].topic
|
||||
@@ -190,7 +174,7 @@ func (n *noopServer) Register() error {
|
||||
n.RUnlock()
|
||||
|
||||
service.Nodes[0].Metadata["protocol"] = "noop"
|
||||
service.Nodes[0].Metadata["transport"] = "noop"
|
||||
service.Nodes[0].Metadata["transport"] = service.Nodes[0].Metadata["protocol"]
|
||||
service.Endpoints = endpoints
|
||||
|
||||
n.RLock()
|
||||
@@ -199,7 +183,7 @@ func (n *noopServer) Register() error {
|
||||
|
||||
if !registered {
|
||||
if config.Logger.V(logger.InfoLevel) {
|
||||
config.Logger.Infof(n.opts.Context, "register [%s] Registering node: %s", config.Register.String(), service.Nodes[0].Id)
|
||||
config.Logger.Infof(n.opts.Context, "register [%s] Registering node: %s", config.Register.String(), service.Nodes[0].ID)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,7 +246,7 @@ func (n *noopServer) Deregister() error {
|
||||
}
|
||||
|
||||
if config.Logger.V(logger.InfoLevel) {
|
||||
config.Logger.Infof(n.opts.Context, "deregistering node: %s", service.Nodes[0].Id)
|
||||
config.Logger.Infof(n.opts.Context, "deregistering node: %s", service.Nodes[0].ID)
|
||||
}
|
||||
|
||||
if err := DefaultDeregisterFunc(service, config); err != nil {
|
||||
@@ -344,9 +328,10 @@ func (n *noopServer) Start() error {
|
||||
}
|
||||
|
||||
// use RegisterCheck func before register
|
||||
// nolint: nestif
|
||||
if err := config.RegisterCheck(config.Context); err != nil {
|
||||
if config.Logger.V(logger.ErrorLevel) {
|
||||
config.Logger.Errorf(n.opts.Context, "server %s-%s register check error: %s", config.Name, config.Id, err)
|
||||
config.Logger.Errorf(n.opts.Context, "server %s-%s register check error: %s", config.Name, config.ID, err)
|
||||
}
|
||||
} else {
|
||||
// announce self to the world
|
||||
@@ -378,25 +363,26 @@ func (n *noopServer) Start() error {
|
||||
registered := n.registered
|
||||
n.RUnlock()
|
||||
rerr := config.RegisterCheck(config.Context)
|
||||
// nolint: nestif
|
||||
if rerr != nil && registered {
|
||||
if config.Logger.V(logger.ErrorLevel) {
|
||||
config.Logger.Errorf(n.opts.Context, "server %s-%s register check error: %s, deregister it", config.Name, config.Id, rerr)
|
||||
config.Logger.Errorf(n.opts.Context, "server %s-%s register check error: %s, deregister it", config.Name, config.ID, rerr)
|
||||
}
|
||||
// deregister self in case of error
|
||||
if err := n.Deregister(); err != nil {
|
||||
if config.Logger.V(logger.ErrorLevel) {
|
||||
config.Logger.Errorf(n.opts.Context, "server %s-%s deregister error: %s", config.Name, config.Id, err)
|
||||
config.Logger.Errorf(n.opts.Context, "server %s-%s deregister error: %s", config.Name, config.ID, err)
|
||||
}
|
||||
}
|
||||
} else if rerr != nil && !registered {
|
||||
if config.Logger.V(logger.ErrorLevel) {
|
||||
config.Logger.Errorf(n.opts.Context, "server %s-%s register check error: %s", config.Name, config.Id, rerr)
|
||||
config.Logger.Errorf(n.opts.Context, "server %s-%s register check error: %s", config.Name, config.ID, rerr)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if err := n.Register(); err != nil {
|
||||
if config.Logger.V(logger.ErrorLevel) {
|
||||
config.Logger.Errorf(n.opts.Context, "server %s-%s register error: %s", config.Name, config.Id, err)
|
||||
config.Logger.Errorf(n.opts.Context, "server %s-%s register error: %s", config.Name, config.ID, err)
|
||||
}
|
||||
}
|
||||
// wait for exit
|
||||
|
@@ -39,8 +39,12 @@ type Options struct {
|
||||
Meter meter.Meter
|
||||
// Transport holds the transport
|
||||
Transport transport.Transport
|
||||
// Router for requests
|
||||
Router Router
|
||||
|
||||
/*
|
||||
// Router for requests
|
||||
Router Router
|
||||
*/
|
||||
|
||||
// Listener may be passed if already created
|
||||
Listener net.Listener
|
||||
// Wait group
|
||||
@@ -53,8 +57,8 @@ type Options struct {
|
||||
RegisterCheck func(context.Context) error
|
||||
// Codecs map to handle content-type
|
||||
Codecs map[string]codec.Codec
|
||||
// Id holds the id of the server
|
||||
Id string
|
||||
// ID holds the id of the server
|
||||
ID string
|
||||
// Namespace for te server
|
||||
Namespace string
|
||||
// Name holds the server name
|
||||
@@ -100,7 +104,7 @@ func NewOptions(opts ...Option) Options {
|
||||
Address: DefaultAddress,
|
||||
Name: DefaultName,
|
||||
Version: DefaultVersion,
|
||||
Id: DefaultId,
|
||||
ID: DefaultID,
|
||||
Namespace: DefaultNamespace,
|
||||
}
|
||||
|
||||
@@ -139,10 +143,10 @@ func Meter(m meter.Meter) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// Id unique server id
|
||||
func Id(id string) Option {
|
||||
// ID unique server id
|
||||
func ID(id string) Option {
|
||||
return func(o *Options) {
|
||||
o.Id = id
|
||||
o.ID = id
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,12 +266,14 @@ func TLSConfig(t *tls.Config) Option {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// WithRouter sets the request router
|
||||
func WithRouter(r Router) Option {
|
||||
return func(o *Options) {
|
||||
o.Router = r
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// Wait tells the server to wait for requests to finish before exiting
|
||||
// If `wg` is nil, server only wait for completion of rpc handler.
|
||||
@@ -319,8 +325,6 @@ type HandlerOptions struct {
|
||||
Context context.Context
|
||||
// Metadata for hondler
|
||||
Metadata map[string]metadata.Metadata
|
||||
// Internal flag limits exporting to other nodes via register
|
||||
Internal bool
|
||||
}
|
||||
|
||||
// NewHandlerOptions creates new HandlerOptions
|
||||
@@ -348,8 +352,6 @@ type SubscriberOptions struct {
|
||||
Queue string
|
||||
// AutoAck flag for auto ack messages after processing
|
||||
AutoAck bool
|
||||
// Internal flag limit exporting info via register
|
||||
Internal bool
|
||||
// BodyOnly flag specifies that message without headers
|
||||
BodyOnly bool
|
||||
}
|
||||
@@ -376,23 +378,6 @@ func EndpointMetadata(name string, md metadata.Metadata) HandlerOption {
|
||||
}
|
||||
}
|
||||
|
||||
// InternalHandler options specifies that a handler is not advertised
|
||||
// to the discovery system. In the future this may also limit request
|
||||
// to the internal network or authorised user.
|
||||
func InternalHandler(b bool) HandlerOption {
|
||||
return func(o *HandlerOptions) {
|
||||
o.Internal = b
|
||||
}
|
||||
}
|
||||
|
||||
// InternalSubscriber options specifies that a subscriber is not advertised
|
||||
// to the discovery system.
|
||||
func InternalSubscriber(b bool) SubscriberOption {
|
||||
return func(o *SubscriberOptions) {
|
||||
o.Internal = b
|
||||
}
|
||||
}
|
||||
|
||||
// DisableAutoAck will disable auto acking of messages
|
||||
// after they have been handled.
|
||||
func DisableAutoAck() SubscriberOption {
|
||||
|
@@ -72,7 +72,7 @@ func NewRegisterService(s Server) (*register.Service, error) {
|
||||
}
|
||||
|
||||
node := ®ister.Node{
|
||||
Id: opts.Name + "-" + opts.Id,
|
||||
ID: opts.Name + "-" + opts.ID,
|
||||
Address: net.JoinHostPort(addr, port),
|
||||
}
|
||||
node.Metadata = metadata.Copy(opts.Metadata)
|
||||
|
@@ -11,10 +11,8 @@ import (
|
||||
"github.com/unistack-org/micro/v3/register"
|
||||
)
|
||||
|
||||
var (
|
||||
// DefaultServer default server
|
||||
DefaultServer Server = NewServer()
|
||||
)
|
||||
// DefaultServer default server
|
||||
var DefaultServer Server = NewServer()
|
||||
|
||||
var (
|
||||
// DefaultAddress will be used if no address passed
|
||||
@@ -23,8 +21,8 @@ var (
|
||||
DefaultName = "server"
|
||||
// DefaultVersion will be used if no version passed
|
||||
DefaultVersion = "latest"
|
||||
// DefaultId will be used if no id passed
|
||||
DefaultId = uuid.New().String()
|
||||
// DefaultID will be used if no id passed
|
||||
DefaultID = uuid.New().String()
|
||||
// DefaultRegisterCheck holds func that run before register server
|
||||
DefaultRegisterCheck = func(context.Context) error { return nil }
|
||||
// DefaultRegisterInterval holds interval for register
|
||||
@@ -65,6 +63,7 @@ type Server interface {
|
||||
String() string
|
||||
}
|
||||
|
||||
/*
|
||||
// Router handle serving messages
|
||||
type Router interface {
|
||||
// ProcessMessage processes a message
|
||||
@@ -72,6 +71,7 @@ type Router interface {
|
||||
// ServeRequest processes a request to completion
|
||||
ServeRequest(ctx context.Context, req Request, rsp Response) error
|
||||
}
|
||||
*/
|
||||
|
||||
// Message is an async message interface
|
||||
type Message interface {
|
||||
|
@@ -21,11 +21,9 @@ const (
|
||||
subSig = "func(context.Context, interface{}) error"
|
||||
)
|
||||
|
||||
var (
|
||||
// Precompute the reflect type for error. Can't use error directly
|
||||
// because Typeof takes an empty interface value. This is annoying.
|
||||
typeOfError = reflect.TypeOf((*error)(nil)).Elem()
|
||||
)
|
||||
// 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()
|
||||
|
||||
type handler struct {
|
||||
reqType reflect.Type
|
||||
@@ -64,7 +62,8 @@ func ValidateSubscriber(sub Subscriber) error {
|
||||
typ := reflect.TypeOf(sub.Subscriber())
|
||||
var argType reflect.Type
|
||||
|
||||
if typ.Kind() == reflect.Func {
|
||||
switch typ.Kind() {
|
||||
case reflect.Func:
|
||||
name := "Func"
|
||||
switch typ.NumIn() {
|
||||
case 2:
|
||||
@@ -82,7 +81,7 @@ func ValidateSubscriber(sub Subscriber) error {
|
||||
if returnType := typ.Out(0); returnType != typeOfError {
|
||||
return fmt.Errorf("subscriber %v returns %v not error", name, returnType.String())
|
||||
}
|
||||
} else {
|
||||
default:
|
||||
hdlr := reflect.ValueOf(sub.Subscriber())
|
||||
name := reflect.Indirect(hdlr).Type().Name()
|
||||
|
||||
@@ -276,14 +275,14 @@ func (n *noopServer) createSubHandler(sb *subscriber, opts Options) broker.Handl
|
||||
if n.wg != nil {
|
||||
defer n.wg.Done()
|
||||
}
|
||||
err := fn(ctx, &rpcMessage{
|
||||
cerr := fn(ctx, &rpcMessage{
|
||||
topic: sb.topic,
|
||||
contentType: ct,
|
||||
payload: req.Interface(),
|
||||
header: msg.Header,
|
||||
body: msg.Body,
|
||||
})
|
||||
results <- err
|
||||
results <- cerr
|
||||
}()
|
||||
}
|
||||
var errors []string
|
||||
|
17
service.go
17
service.go
@@ -103,48 +103,48 @@ func (s *service) Init(opts ...Option) error {
|
||||
// skip config as the struct not passed
|
||||
continue
|
||||
}
|
||||
if err = cfg.Init(config.Context(s.opts.Context)); err != nil {
|
||||
if err = cfg.Init(config.Context(cfg.Options().Context)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = cfg.Load(s.opts.Context); err != nil {
|
||||
if err = cfg.Load(cfg.Options().Context); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for _, log := range s.opts.Loggers {
|
||||
if err = log.Init(logger.WithContext(s.opts.Context)); err != nil {
|
||||
if err = log.Init(logger.WithContext(log.Options().Context)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
for _, reg := range s.opts.Registers {
|
||||
if err = reg.Init(register.Context(s.opts.Context)); err != nil {
|
||||
if err = reg.Init(register.Context(reg.Options().Context)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
for _, brk := range s.opts.Brokers {
|
||||
if err = brk.Init(broker.Context(s.opts.Context)); err != nil {
|
||||
if err = brk.Init(broker.Context(brk.Options().Context)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
for _, str := range s.opts.Stores {
|
||||
if err = str.Init(store.Context(s.opts.Context)); err != nil {
|
||||
if err = str.Init(store.Context(str.Options().Context)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
for _, srv := range s.opts.Servers {
|
||||
if err = srv.Init(server.Context(s.opts.Context)); err != nil {
|
||||
if err = srv.Init(server.Context(srv.Options().Context)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
for _, cli := range s.opts.Clients {
|
||||
if err = cli.Init(client.Context(s.opts.Context)); err != nil {
|
||||
if err = cli.Init(client.Context(cli.Options().Context)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -162,7 +162,6 @@ func (s *service) Broker(names ...string) broker.Broker {
|
||||
idx = getNameIndex(names[0], s.opts.Brokers)
|
||||
}
|
||||
return s.opts.Brokers[idx]
|
||||
|
||||
}
|
||||
|
||||
func (s *service) Tracer(names ...string) tracer.Tracer {
|
||||
|
@@ -28,8 +28,8 @@ func (m *memoryStore) Disconnect(ctx context.Context) error {
|
||||
}
|
||||
|
||||
type memoryStore struct {
|
||||
opts Options
|
||||
store *cache.Cache
|
||||
opts Options
|
||||
}
|
||||
|
||||
func (m *memoryStore) key(prefix, key string) string {
|
||||
|
@@ -5,8 +5,6 @@ package store
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/unistack-org/micro/v3/metadata"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -42,12 +40,3 @@ type Store interface {
|
||||
// String returns the name of the implementation.
|
||||
String() string
|
||||
}
|
||||
|
||||
// Value is an item stored or retrieved from a Store
|
||||
// may be used in store implementations to provide metadata
|
||||
type Value struct {
|
||||
// Data holds underline struct
|
||||
Data interface{} `json:"data"`
|
||||
// Metadata associated with data for indexing
|
||||
Metadata metadata.Metadata `json:"metadata"`
|
||||
}
|
||||
|
@@ -6,8 +6,8 @@ import (
|
||||
)
|
||||
|
||||
type memorySync struct {
|
||||
options Options
|
||||
locks map[string]*memoryLock
|
||||
options Options
|
||||
mtx gosync.RWMutex
|
||||
}
|
||||
|
||||
|
@@ -5,10 +5,8 @@ import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrLockTimeout error
|
||||
ErrLockTimeout = errors.New("lock timeout")
|
||||
)
|
||||
// ErrLockTimeout error
|
||||
var ErrLockTimeout = errors.New("lock timeout")
|
||||
|
||||
// Sync is an interface for distributed synchronization
|
||||
type Sync interface {
|
||||
|
@@ -38,7 +38,6 @@ type noopSpan struct {
|
||||
}
|
||||
|
||||
func (s *noopSpan) Finish(opts ...SpanOption) {
|
||||
|
||||
}
|
||||
|
||||
func (s *noopSpan) Context() context.Context {
|
||||
@@ -50,7 +49,6 @@ func (s *noopSpan) Tracer() Tracer {
|
||||
}
|
||||
|
||||
func (s *noopSpan) AddEvent(name string, opts ...EventOption) {
|
||||
|
||||
}
|
||||
|
||||
func (s *noopSpan) SetName(name string) {
|
||||
@@ -58,7 +56,6 @@ func (s *noopSpan) SetName(name string) {
|
||||
}
|
||||
|
||||
func (s *noopSpan) SetLabels(labels ...Label) {
|
||||
|
||||
}
|
||||
|
||||
// NewTracer returns new memory tracer
|
||||
|
@@ -2,13 +2,11 @@ package tracer
|
||||
|
||||
import "github.com/unistack-org/micro/v3/logger"
|
||||
|
||||
type SpanOptions struct {
|
||||
}
|
||||
type SpanOptions struct{}
|
||||
|
||||
type SpanOption func(o *SpanOptions)
|
||||
|
||||
type EventOptions struct {
|
||||
}
|
||||
type EventOptions struct{}
|
||||
|
||||
type EventOption func(o *EventOptions)
|
||||
|
||||
|
@@ -5,10 +5,8 @@ import (
|
||||
"context"
|
||||
)
|
||||
|
||||
var (
|
||||
// DefaultTracer is the global default tracer
|
||||
DefaultTracer Tracer = NewTracer()
|
||||
)
|
||||
// DefaultTracer is the global default tracer
|
||||
var DefaultTracer Tracer = NewTracer()
|
||||
|
||||
// Tracer is an interface for distributed tracing
|
||||
type Tracer interface {
|
||||
|
@@ -101,6 +101,8 @@ var (
|
||||
}
|
||||
sp.SetLabels(labels...)
|
||||
}
|
||||
|
||||
DefaultSkipEndpoints = []string{"Meter.Metrics"}
|
||||
)
|
||||
|
||||
type tWrapper struct {
|
||||
@@ -111,12 +113,14 @@ type tWrapper struct {
|
||||
opts Options
|
||||
}
|
||||
|
||||
type ClientCallObserver func(context.Context, client.Request, interface{}, []client.CallOption, tracer.Span, error)
|
||||
type ClientStreamObserver func(context.Context, client.Request, []client.CallOption, client.Stream, tracer.Span, error)
|
||||
type ClientPublishObserver func(context.Context, client.Message, []client.PublishOption, tracer.Span, error)
|
||||
type ClientCallFuncObserver func(context.Context, string, client.Request, interface{}, client.CallOptions, tracer.Span, error)
|
||||
type ServerHandlerObserver func(context.Context, server.Request, interface{}, tracer.Span, error)
|
||||
type ServerSubscriberObserver func(context.Context, server.Message, tracer.Span, error)
|
||||
type (
|
||||
ClientCallObserver func(context.Context, client.Request, interface{}, []client.CallOption, tracer.Span, error)
|
||||
ClientStreamObserver func(context.Context, client.Request, []client.CallOption, client.Stream, tracer.Span, error)
|
||||
ClientPublishObserver func(context.Context, client.Message, []client.PublishOption, tracer.Span, error)
|
||||
ClientCallFuncObserver func(context.Context, string, client.Request, interface{}, client.CallOptions, tracer.Span, error)
|
||||
ServerHandlerObserver func(context.Context, server.Request, interface{}, tracer.Span, error)
|
||||
ServerSubscriberObserver func(context.Context, server.Message, tracer.Span, error)
|
||||
)
|
||||
|
||||
// Options struct
|
||||
type Options struct {
|
||||
@@ -134,6 +138,8 @@ type Options struct {
|
||||
ServerHandlerObservers []ServerHandlerObserver
|
||||
// ServerSubscriberObservers funcs
|
||||
ServerSubscriberObservers []ServerSubscriberObserver
|
||||
// SkipEndpoints
|
||||
SkipEndpoints []string
|
||||
}
|
||||
|
||||
// Option func signature
|
||||
@@ -149,6 +155,7 @@ func NewOptions(opts ...Option) Options {
|
||||
ClientCallFuncObservers: []ClientCallFuncObserver{DefaultClientCallFuncObserver},
|
||||
ServerHandlerObservers: []ServerHandlerObserver{DefaultServerHandlerObserver},
|
||||
ServerSubscriberObservers: []ServerSubscriberObserver{DefaultServerSubscriberObserver},
|
||||
SkipEndpoints: DefaultSkipEndpoints,
|
||||
}
|
||||
|
||||
for _, o := range opts {
|
||||
@@ -165,6 +172,13 @@ func WithTracer(t tracer.Tracer) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// SkipEndponts
|
||||
func SkipEndpoins(eps ...string) Option {
|
||||
return func(o *Options) {
|
||||
o.SkipEndpoints = append(o.SkipEndpoints, eps...)
|
||||
}
|
||||
}
|
||||
|
||||
// WithClientCallObservers funcs
|
||||
func WithClientCallObservers(ob ...ClientCallObserver) Option {
|
||||
return func(o *Options) {
|
||||
@@ -208,6 +222,13 @@ func WithServerSubscriberObservers(ob ...ServerSubscriberObserver) Option {
|
||||
}
|
||||
|
||||
func (ot *tWrapper) Call(ctx context.Context, req client.Request, rsp interface{}, opts ...client.CallOption) error {
|
||||
endpoint := fmt.Sprintf("%s.%s", req.Service(), req.Endpoint())
|
||||
for _, ep := range ot.opts.SkipEndpoints {
|
||||
if ep == endpoint {
|
||||
return ot.Client.Call(ctx, req, rsp, opts...)
|
||||
}
|
||||
}
|
||||
|
||||
sp := tracer.SpanFromContext(ctx)
|
||||
defer sp.Finish()
|
||||
|
||||
@@ -221,6 +242,13 @@ func (ot *tWrapper) Call(ctx context.Context, req client.Request, rsp interface{
|
||||
}
|
||||
|
||||
func (ot *tWrapper) Stream(ctx context.Context, req client.Request, opts ...client.CallOption) (client.Stream, error) {
|
||||
endpoint := fmt.Sprintf("%s.%s", req.Service(), req.Endpoint())
|
||||
for _, ep := range ot.opts.SkipEndpoints {
|
||||
if ep == endpoint {
|
||||
return ot.Client.Stream(ctx, req, opts...)
|
||||
}
|
||||
}
|
||||
|
||||
sp := tracer.SpanFromContext(ctx)
|
||||
defer sp.Finish()
|
||||
|
||||
@@ -247,6 +275,13 @@ func (ot *tWrapper) Publish(ctx context.Context, msg client.Message, opts ...cli
|
||||
}
|
||||
|
||||
func (ot *tWrapper) ServerHandler(ctx context.Context, req server.Request, rsp interface{}) error {
|
||||
endpoint := req.Endpoint()
|
||||
for _, ep := range ot.opts.SkipEndpoints {
|
||||
if ep == endpoint {
|
||||
return ot.serverHandler(ctx, req, rsp)
|
||||
}
|
||||
}
|
||||
|
||||
sp := tracer.SpanFromContext(ctx)
|
||||
defer sp.Finish()
|
||||
|
||||
@@ -297,6 +332,13 @@ func NewClientCallWrapper(opts ...Option) client.CallWrapper {
|
||||
}
|
||||
|
||||
func (ot *tWrapper) ClientCallFunc(ctx context.Context, addr string, req client.Request, rsp interface{}, opts client.CallOptions) error {
|
||||
endpoint := fmt.Sprintf("%s.%s", req.Service(), req.Endpoint())
|
||||
for _, ep := range ot.opts.SkipEndpoints {
|
||||
if ep == endpoint {
|
||||
return ot.ClientCallFunc(ctx, addr, req, rsp, opts)
|
||||
}
|
||||
}
|
||||
|
||||
sp := tracer.SpanFromContext(ctx)
|
||||
defer sp.Finish()
|
||||
|
||||
|
@@ -5,9 +5,7 @@ import (
|
||||
"net"
|
||||
)
|
||||
|
||||
var (
|
||||
privateBlocks []*net.IPNet
|
||||
)
|
||||
var privateBlocks []*net.IPNet
|
||||
|
||||
func init() {
|
||||
for _, b := range []string{"10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16", "100.64.0.0/10", "fd00::/8"} {
|
||||
|
@@ -54,7 +54,6 @@ func TestExtractor(t *testing.T) {
|
||||
t.Errorf("Expected %s got %s", d.expect, addr)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestAppendPrivateBlocks(t *testing.T) {
|
||||
|
@@ -4,20 +4,20 @@ import (
|
||||
"bytes"
|
||||
)
|
||||
|
||||
type buffer struct {
|
||||
type Buffer struct {
|
||||
*bytes.Buffer
|
||||
}
|
||||
|
||||
// Close reset buffer contents
|
||||
func (b *buffer) Close() error {
|
||||
func (b *Buffer) Close() error {
|
||||
b.Buffer.Reset()
|
||||
return nil
|
||||
}
|
||||
|
||||
// New creates new buffer that satisfies Closer interface
|
||||
func New(b *bytes.Buffer) *buffer {
|
||||
func New(b *bytes.Buffer) *Buffer {
|
||||
if b == nil {
|
||||
b = bytes.NewBuffer(nil)
|
||||
}
|
||||
return &buffer{b}
|
||||
return &Buffer{b}
|
||||
}
|
||||
|
@@ -27,7 +27,6 @@ func HostPort(addr string, port interface{}) string {
|
||||
// Listen takes addr:portmin-portmax and binds to the first available port
|
||||
// Example: Listen("localhost:5000-6000", fn)
|
||||
func Listen(addr string, fn func(string) (net.Listener, error)) (net.Listener, error) {
|
||||
|
||||
if strings.Count(addr, ":") == 1 && strings.Count(addr, "-") == 0 {
|
||||
return fn(addr)
|
||||
}
|
||||
|
@@ -22,5 +22,4 @@ func TestListen(t *testing.T) {
|
||||
// TODO nats case test
|
||||
// natsAddr := "_INBOX.bID2CMRvlNp0vt4tgNBHWf"
|
||||
// Expect addr DO NOT has extra ":" at the end!
|
||||
|
||||
}
|
||||
|
@@ -8,9 +8,8 @@ import (
|
||||
"crypto/rand"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// GenerateKey returns an ed25519 key
|
||||
@@ -46,14 +45,14 @@ func CA(opts ...CertOption) ([]byte, []byte, error) {
|
||||
return nil, nil, err
|
||||
}
|
||||
cert, key := &bytes.Buffer{}, &bytes.Buffer{}
|
||||
if err := pem.Encode(cert, &pem.Block{Type: "CERTIFICATE", Bytes: x509Cert}); err != nil {
|
||||
if err = pem.Encode(cert, &pem.Block{Type: "CERTIFICATE", Bytes: x509Cert}); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
x509Key, err := x509.MarshalPKCS8PrivateKey(options.Priv)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := pem.Encode(key, &pem.Block{Type: "PRIVATE KEY", Bytes: x509Key}); err != nil {
|
||||
if err = pem.Encode(key, &pem.Block{Type: "PRIVATE KEY", Bytes: x509Key}); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
|
@@ -63,9 +63,7 @@ func Unmarshal(dst interface{}, query string) error {
|
||||
// possible. Eg the example above would output:
|
||||
// {"bar":{"one":{"two":2,"red":112}}}
|
||||
func ToJSON(query string) ([]byte, error) {
|
||||
var (
|
||||
builder interface{} = make(map[string]interface{})
|
||||
)
|
||||
var builder interface{} = make(map[string]interface{})
|
||||
params := strings.Split(query, "&")
|
||||
for _, part := range params {
|
||||
tempMap, err := queryToMap(part)
|
||||
|
@@ -32,9 +32,10 @@ type unmarshalT struct {
|
||||
A string `json:"a"`
|
||||
B unmarshalB `json:"b"`
|
||||
}
|
||||
|
||||
type unmarshalB struct {
|
||||
C int `json:"c"`
|
||||
D string `json:"D"`
|
||||
C int `json:"c"`
|
||||
}
|
||||
|
||||
func TestUnmarshal(t *testing.T) {
|
||||
|
@@ -11,7 +11,7 @@ type Rand struct {
|
||||
}
|
||||
|
||||
func (r *Rand) Int31() int32 {
|
||||
rand.Read(r.buf[:4])
|
||||
_, _ = rand.Read(r.buf[:4])
|
||||
return int32(binary.BigEndian.Uint32(r.buf[:4]) & ^uint32(1<<31))
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ func (r *Rand) Intn(n int) int {
|
||||
}
|
||||
|
||||
func (r *Rand) Int63() int64 {
|
||||
rand.Read(r.buf[:])
|
||||
_, _ = rand.Read(r.buf[:])
|
||||
return int64(binary.BigEndian.Uint64(r.buf[:]) & ^uint64(1<<63))
|
||||
}
|
||||
|
||||
|
@@ -5,7 +5,6 @@ import (
|
||||
)
|
||||
|
||||
func TestPath(t *testing.T) {
|
||||
|
||||
type Nested2 struct {
|
||||
Name string
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user