Compare commits
11 Commits
0144f175f0
...
v4.1.16
Author | SHA1 | Date | |
---|---|---|---|
9ee31fb5a6 | |||
ed5d30a58e | |||
|
b4b67a8b41 | ||
13f90ff716 | |||
0f8f12aee0 | |||
8b406cf963 | |||
029a434a2b | |||
|
847259bc39 | ||
a1ee8728ad | |||
88a5875cfb | |||
03ee33040c |
@@ -22,8 +22,8 @@ type Broker struct {
|
|||||||
subscribers map[string][]*Subscriber
|
subscribers map[string][]*Subscriber
|
||||||
addr string
|
addr string
|
||||||
opts broker.Options
|
opts broker.Options
|
||||||
sync.RWMutex
|
mu sync.RWMutex
|
||||||
connected bool
|
connected bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type memoryMessage struct {
|
type memoryMessage struct {
|
||||||
@@ -72,9 +72,9 @@ func (b *Broker) newCodec(ct string) (codec.Codec, error) {
|
|||||||
if idx := strings.IndexRune(ct, ';'); idx >= 0 {
|
if idx := strings.IndexRune(ct, ';'); idx >= 0 {
|
||||||
ct = ct[:idx]
|
ct = ct[:idx]
|
||||||
}
|
}
|
||||||
b.RLock()
|
b.mu.RLock()
|
||||||
c, ok := b.opts.Codecs[ct]
|
c, ok := b.opts.Codecs[ct]
|
||||||
b.RUnlock()
|
b.mu.RUnlock()
|
||||||
if ok {
|
if ok {
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
@@ -96,8 +96,8 @@ func (b *Broker) Connect(ctx context.Context) error {
|
|||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
b.Lock()
|
b.mu.Lock()
|
||||||
defer b.Unlock()
|
defer b.mu.Unlock()
|
||||||
|
|
||||||
if b.connected {
|
if b.connected {
|
||||||
return nil
|
return nil
|
||||||
@@ -126,8 +126,8 @@ func (b *Broker) Disconnect(ctx context.Context) error {
|
|||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
b.Lock()
|
b.mu.Lock()
|
||||||
defer b.Unlock()
|
defer b.mu.Unlock()
|
||||||
|
|
||||||
if !b.connected {
|
if !b.connected {
|
||||||
return nil
|
return nil
|
||||||
@@ -159,6 +159,9 @@ func (b *Broker) Init(opts ...broker.Option) error {
|
|||||||
|
|
||||||
func (b *Broker) NewMessage(ctx context.Context, hdr metadata.Metadata, body interface{}, opts ...broker.PublishOption) (broker.Message, error) {
|
func (b *Broker) NewMessage(ctx context.Context, hdr metadata.Metadata, body interface{}, opts ...broker.PublishOption) (broker.Message, error) {
|
||||||
options := broker.NewPublishOptions(opts...)
|
options := broker.NewPublishOptions(opts...)
|
||||||
|
if options.ContentType == "" {
|
||||||
|
options.ContentType = b.opts.ContentType
|
||||||
|
}
|
||||||
m := &memoryMessage{ctx: ctx, hdr: hdr, opts: options}
|
m := &memoryMessage{ctx: ctx, hdr: hdr, opts: options}
|
||||||
c, err := b.newCodec(m.opts.ContentType)
|
c, err := b.newCodec(m.opts.ContentType)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@@ -180,12 +183,12 @@ func (b *Broker) fnPublish(ctx context.Context, topic string, messages ...broker
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *Broker) publish(ctx context.Context, topic string, messages ...broker.Message) error {
|
func (b *Broker) publish(ctx context.Context, topic string, messages ...broker.Message) error {
|
||||||
b.RLock()
|
b.mu.RLock()
|
||||||
if !b.connected {
|
if !b.connected {
|
||||||
b.RUnlock()
|
b.mu.RUnlock()
|
||||||
return broker.ErrNotConnected
|
return broker.ErrNotConnected
|
||||||
}
|
}
|
||||||
b.RUnlock()
|
b.mu.RUnlock()
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
@@ -193,9 +196,9 @@ func (b *Broker) publish(ctx context.Context, topic string, messages ...broker.M
|
|||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
b.RLock()
|
b.mu.RLock()
|
||||||
subs, ok := b.subscribers[topic]
|
subs, ok := b.subscribers[topic]
|
||||||
b.RUnlock()
|
b.mu.RUnlock()
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -252,12 +255,12 @@ func (b *Broker) fnSubscribe(ctx context.Context, topic string, handler interfac
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
b.RLock()
|
b.mu.RLock()
|
||||||
if !b.connected {
|
if !b.connected {
|
||||||
b.RUnlock()
|
b.mu.RUnlock()
|
||||||
return nil, broker.ErrNotConnected
|
return nil, broker.ErrNotConnected
|
||||||
}
|
}
|
||||||
b.RUnlock()
|
b.mu.RUnlock()
|
||||||
|
|
||||||
sid, err := id.New()
|
sid, err := id.New()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -275,13 +278,13 @@ func (b *Broker) fnSubscribe(ctx context.Context, topic string, handler interfac
|
|||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
}
|
}
|
||||||
|
|
||||||
b.Lock()
|
b.mu.Lock()
|
||||||
b.subscribers[topic] = append(b.subscribers[topic], sub)
|
b.subscribers[topic] = append(b.subscribers[topic], sub)
|
||||||
b.Unlock()
|
b.mu.Unlock()
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
<-sub.exit
|
<-sub.exit
|
||||||
b.Lock()
|
b.mu.Lock()
|
||||||
newSubscribers := make([]*Subscriber, 0, len(b.subscribers)-1)
|
newSubscribers := make([]*Subscriber, 0, len(b.subscribers)-1)
|
||||||
for _, sb := range b.subscribers[topic] {
|
for _, sb := range b.subscribers[topic] {
|
||||||
if sb.id == sub.id {
|
if sb.id == sub.id {
|
||||||
@@ -290,7 +293,7 @@ func (b *Broker) fnSubscribe(ctx context.Context, topic string, handler interfac
|
|||||||
newSubscribers = append(newSubscribers, sb)
|
newSubscribers = append(newSubscribers, sb)
|
||||||
}
|
}
|
||||||
b.subscribers[topic] = newSubscribers
|
b.subscribers[topic] = newSubscribers
|
||||||
b.Unlock()
|
b.mu.Unlock()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return sub, nil
|
return sub, nil
|
||||||
|
@@ -14,16 +14,16 @@ type NoopBroker struct {
|
|||||||
funcPublish FuncPublish
|
funcPublish FuncPublish
|
||||||
funcSubscribe FuncSubscribe
|
funcSubscribe FuncSubscribe
|
||||||
opts Options
|
opts Options
|
||||||
sync.RWMutex
|
mu sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *NoopBroker) newCodec(ct string) (codec.Codec, error) {
|
func (b *NoopBroker) newCodec(ct string) (codec.Codec, error) {
|
||||||
if idx := strings.IndexRune(ct, ';'); idx >= 0 {
|
if idx := strings.IndexRune(ct, ';'); idx >= 0 {
|
||||||
ct = ct[:idx]
|
ct = ct[:idx]
|
||||||
}
|
}
|
||||||
b.RLock()
|
b.mu.RLock()
|
||||||
c, ok := b.opts.Codecs[ct]
|
c, ok := b.opts.Codecs[ct]
|
||||||
b.RUnlock()
|
b.mu.RUnlock()
|
||||||
if ok {
|
if ok {
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
@@ -128,6 +128,9 @@ func (m *noopMessage) Unmarshal(dst interface{}, opts ...codec.Option) error {
|
|||||||
|
|
||||||
func (b *NoopBroker) NewMessage(ctx context.Context, hdr metadata.Metadata, body interface{}, opts ...PublishOption) (Message, error) {
|
func (b *NoopBroker) NewMessage(ctx context.Context, hdr metadata.Metadata, body interface{}, opts ...PublishOption) (Message, error) {
|
||||||
options := NewPublishOptions(opts...)
|
options := NewPublishOptions(opts...)
|
||||||
|
if options.ContentType == "" {
|
||||||
|
options.ContentType = b.opts.ContentType
|
||||||
|
}
|
||||||
m := &noopMessage{ctx: ctx, hdr: hdr, opts: options}
|
m := &noopMessage{ctx: ctx, hdr: hdr, opts: options}
|
||||||
c, err := b.newCodec(m.opts.ContentType)
|
c, err := b.newCodec(m.opts.ContentType)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
@@ -45,6 +45,9 @@ type Options struct {
|
|||||||
|
|
||||||
// GracefulTimeout contains time to wait to finish in flight requests
|
// GracefulTimeout contains time to wait to finish in flight requests
|
||||||
GracefulTimeout time.Duration
|
GracefulTimeout time.Duration
|
||||||
|
|
||||||
|
// ContentType will be used if no content-type set when creating message
|
||||||
|
ContentType string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewOptions create new Options
|
// NewOptions create new Options
|
||||||
@@ -57,14 +60,19 @@ func NewOptions(opts ...Option) Options {
|
|||||||
Codecs: make(map[string]codec.Codec),
|
Codecs: make(map[string]codec.Codec),
|
||||||
Tracer: tracer.DefaultTracer,
|
Tracer: tracer.DefaultTracer,
|
||||||
GracefulTimeout: DefaultGracefulTimeout,
|
GracefulTimeout: DefaultGracefulTimeout,
|
||||||
|
ContentType: DefaultContentType,
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, o := range opts {
|
for _, o := range opts {
|
||||||
o(&options)
|
o(&options)
|
||||||
}
|
}
|
||||||
|
|
||||||
return options
|
return options
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DefaultContentType is the default content-type if not specified
|
||||||
|
var DefaultContentType = ""
|
||||||
|
|
||||||
// Context sets the context option
|
// Context sets the context option
|
||||||
func Context(ctx context.Context) Option {
|
func Context(ctx context.Context) Option {
|
||||||
return func(o *Options) {
|
return func(o *Options) {
|
||||||
@@ -72,6 +80,13 @@ func Context(ctx context.Context) Option {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ContentType used by default if not specified
|
||||||
|
func ContentType(ct string) Option {
|
||||||
|
return func(o *Options) {
|
||||||
|
o.ContentType = ct
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// PublishOptions struct
|
// PublishOptions struct
|
||||||
type PublishOptions struct {
|
type PublishOptions struct {
|
||||||
// ContentType for message body
|
// ContentType for message body
|
||||||
|
@@ -3,8 +3,6 @@ package codec
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"gopkg.in/yaml.v3"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -68,10 +66,10 @@ func (m *RawMessage) MarshalYAML() ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalYAML sets *m to a copy of data.
|
// UnmarshalYAML sets *m to a copy of data.
|
||||||
func (m *RawMessage) UnmarshalYAML(n *yaml.Node) error {
|
func (m *RawMessage) UnmarshalYAML(data []byte) error {
|
||||||
if m == nil {
|
if m == nil {
|
||||||
return errors.New("RawMessage UnmarshalYAML on nil pointer")
|
return errors.New("RawMessage UnmarshalYAML on nil pointer")
|
||||||
}
|
}
|
||||||
*m = append((*m)[0:0], []byte(n.Value)...)
|
*m = append((*m)[0:0], data...)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,5 @@
|
|||||||
package codec
|
package codec
|
||||||
|
|
||||||
import "gopkg.in/yaml.v3"
|
|
||||||
|
|
||||||
// Frame gives us the ability to define raw data to send over the pipes
|
// Frame gives us the ability to define raw data to send over the pipes
|
||||||
type Frame struct {
|
type Frame struct {
|
||||||
Data []byte
|
Data []byte
|
||||||
@@ -28,8 +26,8 @@ func (m *Frame) MarshalYAML() ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalYAML set frame data
|
// UnmarshalYAML set frame data
|
||||||
func (m *Frame) UnmarshalYAML(n *yaml.Node) error {
|
func (m *Frame) UnmarshalYAML(data []byte) error {
|
||||||
m.Data = []byte(n.Value)
|
m.Data = append((m.Data)[0:0], data...)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
4
go.mod
4
go.mod
@@ -6,7 +6,7 @@ require (
|
|||||||
dario.cat/mergo v1.0.1
|
dario.cat/mergo v1.0.1
|
||||||
github.com/DATA-DOG/go-sqlmock v1.5.2
|
github.com/DATA-DOG/go-sqlmock v1.5.2
|
||||||
github.com/KimMachineGun/automemlimit v0.7.0
|
github.com/KimMachineGun/automemlimit v0.7.0
|
||||||
github.com/ash3in/uuidv8 v1.2.0
|
github.com/goccy/go-yaml v1.17.1
|
||||||
github.com/google/uuid v1.6.0
|
github.com/google/uuid v1.6.0
|
||||||
github.com/matoous/go-nanoid v1.5.1
|
github.com/matoous/go-nanoid v1.5.1
|
||||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||||
@@ -19,7 +19,6 @@ require (
|
|||||||
golang.org/x/sync v0.10.0
|
golang.org/x/sync v0.10.0
|
||||||
google.golang.org/grpc v1.69.4
|
google.golang.org/grpc v1.69.4
|
||||||
google.golang.org/protobuf v1.36.3
|
google.golang.org/protobuf v1.36.3
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
@@ -31,4 +30,5 @@ require (
|
|||||||
golang.org/x/sys v0.29.0 // indirect
|
golang.org/x/sys v0.29.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241216192217-9240e9c98484 // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20241216192217-9240e9c98484 // indirect
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
4
go.sum
4
go.sum
@@ -4,12 +4,12 @@ github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7Oputl
|
|||||||
github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
|
github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
|
||||||
github.com/KimMachineGun/automemlimit v0.7.0 h1:7G06p/dMSf7G8E6oq+f2uOPuVncFyIlDI/pBWK49u88=
|
github.com/KimMachineGun/automemlimit v0.7.0 h1:7G06p/dMSf7G8E6oq+f2uOPuVncFyIlDI/pBWK49u88=
|
||||||
github.com/KimMachineGun/automemlimit v0.7.0/go.mod h1:QZxpHaGOQoYvFhv/r4u3U0JTC2ZcOwbSr11UZF46UBM=
|
github.com/KimMachineGun/automemlimit v0.7.0/go.mod h1:QZxpHaGOQoYvFhv/r4u3U0JTC2ZcOwbSr11UZF46UBM=
|
||||||
github.com/ash3in/uuidv8 v1.2.0 h1:2oogGdtCPwaVtyvPPGin4TfZLtOGE5F+W++E880G6SI=
|
|
||||||
github.com/ash3in/uuidv8 v1.2.0/go.mod h1:BnU0wJBxnzdEKmVg4xckBkD+VZuecTFTUP3M0dWgyY4=
|
|
||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||||
|
github.com/goccy/go-yaml v1.17.1 h1:LI34wktB2xEE3ONG/2Ar54+/HJVBriAGJ55PHls4YuY=
|
||||||
|
github.com/goccy/go-yaml v1.17.1/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
|
||||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
|
@@ -11,8 +11,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type httpProfile struct {
|
type httpProfile struct {
|
||||||
server *http.Server
|
server *http.Server
|
||||||
sync.Mutex
|
mu sync.Mutex
|
||||||
running bool
|
running bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -21,8 +21,8 @@ var DefaultAddress = ":6060"
|
|||||||
|
|
||||||
// Start the profiler
|
// Start the profiler
|
||||||
func (h *httpProfile) Start() error {
|
func (h *httpProfile) Start() error {
|
||||||
h.Lock()
|
h.mu.Lock()
|
||||||
defer h.Unlock()
|
defer h.mu.Unlock()
|
||||||
|
|
||||||
if h.running {
|
if h.running {
|
||||||
return nil
|
return nil
|
||||||
@@ -30,9 +30,9 @@ func (h *httpProfile) Start() error {
|
|||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
if err := h.server.ListenAndServe(); err != nil {
|
if err := h.server.ListenAndServe(); err != nil {
|
||||||
h.Lock()
|
h.mu.Lock()
|
||||||
h.running = false
|
h.running = false
|
||||||
h.Unlock()
|
h.mu.Unlock()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@@ -43,8 +43,8 @@ func (h *httpProfile) Start() error {
|
|||||||
|
|
||||||
// Stop the profiler
|
// Stop the profiler
|
||||||
func (h *httpProfile) Stop() error {
|
func (h *httpProfile) Stop() error {
|
||||||
h.Lock()
|
h.mu.Lock()
|
||||||
defer h.Unlock()
|
defer h.mu.Unlock()
|
||||||
|
|
||||||
if !h.running {
|
if !h.running {
|
||||||
return nil
|
return nil
|
||||||
|
@@ -17,7 +17,7 @@ type profiler struct {
|
|||||||
cpuFile *os.File
|
cpuFile *os.File
|
||||||
memFile *os.File
|
memFile *os.File
|
||||||
opts profile.Options
|
opts profile.Options
|
||||||
sync.Mutex
|
mu sync.Mutex
|
||||||
running bool
|
running bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,8 +39,8 @@ func (p *profiler) writeHeap(f *os.File) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *profiler) Start() error {
|
func (p *profiler) Start() error {
|
||||||
p.Lock()
|
p.mu.Lock()
|
||||||
defer p.Unlock()
|
defer p.mu.Unlock()
|
||||||
|
|
||||||
if p.running {
|
if p.running {
|
||||||
return nil
|
return nil
|
||||||
@@ -86,8 +86,8 @@ func (p *profiler) Start() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *profiler) Stop() error {
|
func (p *profiler) Stop() error {
|
||||||
p.Lock()
|
p.mu.Lock()
|
||||||
defer p.Unlock()
|
defer p.mu.Unlock()
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case <-p.exit:
|
case <-p.exit:
|
||||||
|
@@ -33,7 +33,7 @@ type memory struct {
|
|||||||
records map[string]services
|
records map[string]services
|
||||||
watchers map[string]*watcher
|
watchers map[string]*watcher
|
||||||
opts register.Options
|
opts register.Options
|
||||||
sync.RWMutex
|
mu sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// services is a KV map with service name as the key and a map of records as the value
|
// services is a KV map with service name as the key and a map of records as the value
|
||||||
@@ -57,7 +57,7 @@ func (m *memory) ttlPrune() {
|
|||||||
defer prune.Stop()
|
defer prune.Stop()
|
||||||
|
|
||||||
for range prune.C {
|
for range prune.C {
|
||||||
m.Lock()
|
m.mu.Lock()
|
||||||
for namespace, services := range m.records {
|
for namespace, services := range m.records {
|
||||||
for service, versions := range services {
|
for service, versions := range services {
|
||||||
for version, record := range versions {
|
for version, record := range versions {
|
||||||
@@ -72,24 +72,24 @@ func (m *memory) ttlPrune() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m.Unlock()
|
m.mu.Unlock()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *memory) sendEvent(r *register.Result) {
|
func (m *memory) sendEvent(r *register.Result) {
|
||||||
m.RLock()
|
m.mu.RLock()
|
||||||
watchers := make([]*watcher, 0, len(m.watchers))
|
watchers := make([]*watcher, 0, len(m.watchers))
|
||||||
for _, w := range m.watchers {
|
for _, w := range m.watchers {
|
||||||
watchers = append(watchers, w)
|
watchers = append(watchers, w)
|
||||||
}
|
}
|
||||||
m.RUnlock()
|
m.mu.RUnlock()
|
||||||
|
|
||||||
for _, w := range watchers {
|
for _, w := range watchers {
|
||||||
select {
|
select {
|
||||||
case <-w.exit:
|
case <-w.exit:
|
||||||
m.Lock()
|
m.mu.Lock()
|
||||||
delete(m.watchers, w.id)
|
delete(m.watchers, w.id)
|
||||||
m.Unlock()
|
m.mu.Unlock()
|
||||||
default:
|
default:
|
||||||
select {
|
select {
|
||||||
case w.res <- r:
|
case w.res <- r:
|
||||||
@@ -113,8 +113,8 @@ func (m *memory) Init(opts ...register.Option) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add services
|
// add services
|
||||||
m.Lock()
|
m.mu.Lock()
|
||||||
defer m.Unlock()
|
defer m.mu.Unlock()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -124,8 +124,8 @@ func (m *memory) Options() register.Options {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *memory) Register(_ context.Context, s *register.Service, opts ...register.RegisterOption) error {
|
func (m *memory) Register(_ context.Context, s *register.Service, opts ...register.RegisterOption) error {
|
||||||
m.Lock()
|
m.mu.Lock()
|
||||||
defer m.Unlock()
|
defer m.mu.Unlock()
|
||||||
|
|
||||||
options := register.NewRegisterOptions(opts...)
|
options := register.NewRegisterOptions(opts...)
|
||||||
|
|
||||||
@@ -197,8 +197,8 @@ func (m *memory) Register(_ context.Context, s *register.Service, opts ...regist
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *memory) Deregister(ctx context.Context, s *register.Service, opts ...register.DeregisterOption) error {
|
func (m *memory) Deregister(ctx context.Context, s *register.Service, opts ...register.DeregisterOption) error {
|
||||||
m.Lock()
|
m.mu.Lock()
|
||||||
defer m.Unlock()
|
defer m.mu.Unlock()
|
||||||
|
|
||||||
options := register.NewDeregisterOptions(opts...)
|
options := register.NewDeregisterOptions(opts...)
|
||||||
|
|
||||||
@@ -264,9 +264,9 @@ func (m *memory) LookupService(ctx context.Context, name string, opts ...registe
|
|||||||
|
|
||||||
// if it's a wildcard domain, return from all domains
|
// if it's a wildcard domain, return from all domains
|
||||||
if options.Namespace == register.WildcardNamespace {
|
if options.Namespace == register.WildcardNamespace {
|
||||||
m.RLock()
|
m.mu.RLock()
|
||||||
recs := m.records
|
recs := m.records
|
||||||
m.RUnlock()
|
m.mu.RUnlock()
|
||||||
|
|
||||||
var services []*register.Service
|
var services []*register.Service
|
||||||
|
|
||||||
@@ -286,8 +286,8 @@ func (m *memory) LookupService(ctx context.Context, name string, opts ...registe
|
|||||||
return services, nil
|
return services, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
m.RLock()
|
m.mu.RLock()
|
||||||
defer m.RUnlock()
|
defer m.mu.RUnlock()
|
||||||
|
|
||||||
// check the domain exists
|
// check the domain exists
|
||||||
services, ok := m.records[options.Namespace]
|
services, ok := m.records[options.Namespace]
|
||||||
@@ -319,9 +319,9 @@ func (m *memory) ListServices(ctx context.Context, opts ...register.ListOption)
|
|||||||
|
|
||||||
// if it's a wildcard domain, list from all domains
|
// if it's a wildcard domain, list from all domains
|
||||||
if options.Namespace == register.WildcardNamespace {
|
if options.Namespace == register.WildcardNamespace {
|
||||||
m.RLock()
|
m.mu.RLock()
|
||||||
recs := m.records
|
recs := m.records
|
||||||
m.RUnlock()
|
m.mu.RUnlock()
|
||||||
|
|
||||||
var services []*register.Service
|
var services []*register.Service
|
||||||
|
|
||||||
@@ -336,8 +336,8 @@ func (m *memory) ListServices(ctx context.Context, opts ...register.ListOption)
|
|||||||
return services, nil
|
return services, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
m.RLock()
|
m.mu.RLock()
|
||||||
defer m.RUnlock()
|
defer m.mu.RUnlock()
|
||||||
|
|
||||||
// ensure the domain exists
|
// ensure the domain exists
|
||||||
services, ok := m.records[options.Namespace]
|
services, ok := m.records[options.Namespace]
|
||||||
@@ -371,9 +371,9 @@ func (m *memory) Watch(ctx context.Context, opts ...register.WatchOption) (regis
|
|||||||
wo: wo,
|
wo: wo,
|
||||||
}
|
}
|
||||||
|
|
||||||
m.Lock()
|
m.mu.Lock()
|
||||||
m.watchers[w.id] = w
|
m.watchers[w.id] = w
|
||||||
m.Unlock()
|
m.mu.Unlock()
|
||||||
|
|
||||||
return w, nil
|
return w, nil
|
||||||
}
|
}
|
||||||
|
@@ -51,13 +51,13 @@ func (r *rpcHandler) Options() HandlerOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type noopServer struct {
|
type noopServer struct {
|
||||||
h Handler
|
h Handler
|
||||||
wg *sync.WaitGroup
|
wg *sync.WaitGroup
|
||||||
rsvc *register.Service
|
rsvc *register.Service
|
||||||
handlers map[string]Handler
|
handlers map[string]Handler
|
||||||
exit chan chan error
|
exit chan chan error
|
||||||
opts Options
|
opts Options
|
||||||
sync.RWMutex
|
mu sync.RWMutex
|
||||||
registered bool
|
registered bool
|
||||||
started bool
|
started bool
|
||||||
}
|
}
|
||||||
@@ -125,10 +125,10 @@ func (n *noopServer) String() string {
|
|||||||
|
|
||||||
//nolint:gocyclo
|
//nolint:gocyclo
|
||||||
func (n *noopServer) Register() error {
|
func (n *noopServer) Register() error {
|
||||||
n.RLock()
|
n.mu.RLock()
|
||||||
rsvc := n.rsvc
|
rsvc := n.rsvc
|
||||||
config := n.opts
|
config := n.opts
|
||||||
n.RUnlock()
|
n.mu.RUnlock()
|
||||||
|
|
||||||
// if service already filled, reuse it and return early
|
// if service already filled, reuse it and return early
|
||||||
if rsvc != nil {
|
if rsvc != nil {
|
||||||
@@ -144,9 +144,9 @@ func (n *noopServer) Register() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
n.RLock()
|
n.mu.RLock()
|
||||||
registered := n.registered
|
registered := n.registered
|
||||||
n.RUnlock()
|
n.mu.RUnlock()
|
||||||
|
|
||||||
if !registered {
|
if !registered {
|
||||||
if config.Logger.V(logger.InfoLevel) {
|
if config.Logger.V(logger.InfoLevel) {
|
||||||
@@ -164,8 +164,8 @@ func (n *noopServer) Register() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
n.Lock()
|
n.mu.Lock()
|
||||||
defer n.Unlock()
|
defer n.mu.Unlock()
|
||||||
|
|
||||||
n.registered = true
|
n.registered = true
|
||||||
if cacheService {
|
if cacheService {
|
||||||
@@ -178,9 +178,9 @@ func (n *noopServer) Register() error {
|
|||||||
func (n *noopServer) Deregister() error {
|
func (n *noopServer) Deregister() error {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
n.RLock()
|
n.mu.RLock()
|
||||||
config := n.opts
|
config := n.opts
|
||||||
n.RUnlock()
|
n.mu.RUnlock()
|
||||||
|
|
||||||
service, err := NewRegisterService(n)
|
service, err := NewRegisterService(n)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -195,29 +195,29 @@ func (n *noopServer) Deregister() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
n.Lock()
|
n.mu.Lock()
|
||||||
n.rsvc = nil
|
n.rsvc = nil
|
||||||
|
|
||||||
if !n.registered {
|
if !n.registered {
|
||||||
n.Unlock()
|
n.mu.Unlock()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
n.registered = false
|
n.registered = false
|
||||||
|
|
||||||
n.Unlock()
|
n.mu.Unlock()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//nolint:gocyclo
|
//nolint:gocyclo
|
||||||
func (n *noopServer) Start() error {
|
func (n *noopServer) Start() error {
|
||||||
n.RLock()
|
n.mu.RLock()
|
||||||
if n.started {
|
if n.started {
|
||||||
n.RUnlock()
|
n.mu.RUnlock()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
config := n.Options()
|
config := n.Options()
|
||||||
n.RUnlock()
|
n.mu.RUnlock()
|
||||||
|
|
||||||
// use 127.0.0.1 to avoid scan of all network interfaces
|
// use 127.0.0.1 to avoid scan of all network interfaces
|
||||||
addr, err := maddr.Extract("127.0.0.1")
|
addr, err := maddr.Extract("127.0.0.1")
|
||||||
@@ -235,11 +235,11 @@ func (n *noopServer) Start() error {
|
|||||||
config.Logger.Info(n.opts.Context, "server [noop] Listening on "+config.Address)
|
config.Logger.Info(n.opts.Context, "server [noop] Listening on "+config.Address)
|
||||||
}
|
}
|
||||||
|
|
||||||
n.Lock()
|
n.mu.Lock()
|
||||||
if len(config.Advertise) == 0 {
|
if len(config.Advertise) == 0 {
|
||||||
config.Advertise = config.Address
|
config.Advertise = config.Address
|
||||||
}
|
}
|
||||||
n.Unlock()
|
n.mu.Unlock()
|
||||||
|
|
||||||
// use RegisterCheck func before register
|
// use RegisterCheck func before register
|
||||||
// nolint: nestif
|
// nolint: nestif
|
||||||
@@ -273,9 +273,9 @@ func (n *noopServer) Start() error {
|
|||||||
select {
|
select {
|
||||||
// register self on interval
|
// register self on interval
|
||||||
case <-t.C:
|
case <-t.C:
|
||||||
n.RLock()
|
n.mu.RLock()
|
||||||
registered := n.registered
|
registered := n.registered
|
||||||
n.RUnlock()
|
n.mu.RUnlock()
|
||||||
rerr := config.RegisterCheck(config.Context)
|
rerr := config.RegisterCheck(config.Context)
|
||||||
// nolint: nestif
|
// nolint: nestif
|
||||||
if rerr != nil && registered {
|
if rerr != nil && registered {
|
||||||
@@ -332,29 +332,29 @@ func (n *noopServer) Start() error {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
// mark the server as started
|
// mark the server as started
|
||||||
n.Lock()
|
n.mu.Lock()
|
||||||
n.started = true
|
n.started = true
|
||||||
n.Unlock()
|
n.mu.Unlock()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *noopServer) Stop() error {
|
func (n *noopServer) Stop() error {
|
||||||
n.RLock()
|
n.mu.RLock()
|
||||||
if !n.started {
|
if !n.started {
|
||||||
n.RUnlock()
|
n.mu.RUnlock()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
n.RUnlock()
|
n.mu.RUnlock()
|
||||||
|
|
||||||
ch := make(chan error)
|
ch := make(chan error)
|
||||||
n.exit <- ch
|
n.exit <- ch
|
||||||
|
|
||||||
err := <-ch
|
err := <-ch
|
||||||
n.Lock()
|
n.mu.Lock()
|
||||||
n.rsvc = nil
|
n.rsvc = nil
|
||||||
n.started = false
|
n.started = false
|
||||||
n.Unlock()
|
n.mu.Unlock()
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
20
service.go
20
service.go
@@ -96,9 +96,9 @@ func RegisterHandler(s server.Server, h interface{}, opts ...server.HandlerOptio
|
|||||||
}
|
}
|
||||||
|
|
||||||
type service struct {
|
type service struct {
|
||||||
done chan struct{}
|
done chan struct{}
|
||||||
opts Options
|
opts Options
|
||||||
sync.RWMutex
|
mu sync.RWMutex
|
||||||
stopped bool
|
stopped bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -321,9 +321,9 @@ func (s *service) Health() bool {
|
|||||||
func (s *service) Start() error {
|
func (s *service) Start() error {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
s.RLock()
|
s.mu.RLock()
|
||||||
config := s.opts
|
config := s.opts
|
||||||
s.RUnlock()
|
s.mu.RUnlock()
|
||||||
|
|
||||||
for _, cfg := range s.opts.Configs {
|
for _, cfg := range s.opts.Configs {
|
||||||
if cfg.Options().Struct == nil {
|
if cfg.Options().Struct == nil {
|
||||||
@@ -380,9 +380,9 @@ func (s *service) Start() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *service) Stop() error {
|
func (s *service) Stop() error {
|
||||||
s.RLock()
|
s.mu.RLock()
|
||||||
config := s.opts
|
config := s.opts
|
||||||
s.RUnlock()
|
s.mu.RUnlock()
|
||||||
|
|
||||||
if config.Loggers[0].V(logger.InfoLevel) {
|
if config.Loggers[0].V(logger.InfoLevel) {
|
||||||
config.Loggers[0].Info(s.opts.Context, fmt.Sprintf("stoppping [service] %s", s.Name()))
|
config.Loggers[0].Info(s.opts.Context, fmt.Sprintf("stoppping [service] %s", s.Name()))
|
||||||
@@ -457,13 +457,13 @@ func (s *service) Run() error {
|
|||||||
// notifyShutdown marks the service as stopped and closes the done channel.
|
// notifyShutdown marks the service as stopped and closes the done channel.
|
||||||
// It ensures the channel is closed only once, preventing multiple closures.
|
// It ensures the channel is closed only once, preventing multiple closures.
|
||||||
func (s *service) notifyShutdown() {
|
func (s *service) notifyShutdown() {
|
||||||
s.Lock()
|
s.mu.Lock()
|
||||||
if s.stopped {
|
if s.stopped {
|
||||||
s.Unlock()
|
s.mu.Unlock()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s.stopped = true
|
s.stopped = true
|
||||||
s.Unlock()
|
s.mu.Unlock()
|
||||||
|
|
||||||
close(s.done)
|
close(s.done)
|
||||||
}
|
}
|
||||||
|
@@ -139,7 +139,7 @@ func (n *noopStore) fnExists(ctx context.Context, _ string, _ ...ExistsOption) e
|
|||||||
return ctx.Err()
|
return ctx.Err()
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
return nil
|
return ErrNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *noopStore) Write(ctx context.Context, key string, val interface{}, opts ...WriteOption) error {
|
func (n *noopStore) Write(ctx context.Context, key string, val interface{}, opts ...WriteOption) error {
|
||||||
|
@@ -9,7 +9,7 @@ type memorySync struct {
|
|||||||
locks map[string]*memoryLock
|
locks map[string]*memoryLock
|
||||||
options Options
|
options Options
|
||||||
|
|
||||||
mtx gosync.RWMutex
|
mu gosync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
type memoryLock struct {
|
type memoryLock struct {
|
||||||
@@ -74,7 +74,7 @@ func (m *memorySync) Options() Options {
|
|||||||
|
|
||||||
func (m *memorySync) Lock(id string, opts ...LockOption) error {
|
func (m *memorySync) Lock(id string, opts ...LockOption) error {
|
||||||
// lock our access
|
// lock our access
|
||||||
m.mtx.Lock()
|
m.mu.Lock()
|
||||||
|
|
||||||
var options LockOptions
|
var options LockOptions
|
||||||
for _, o := range opts {
|
for _, o := range opts {
|
||||||
@@ -90,11 +90,11 @@ func (m *memorySync) Lock(id string, opts ...LockOption) error {
|
|||||||
release: make(chan bool),
|
release: make(chan bool),
|
||||||
}
|
}
|
||||||
// unlock
|
// unlock
|
||||||
m.mtx.Unlock()
|
m.mu.Unlock()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
m.mtx.Unlock()
|
m.mu.Unlock()
|
||||||
|
|
||||||
// set wait time
|
// set wait time
|
||||||
var wait <-chan time.Time
|
var wait <-chan time.Time
|
||||||
@@ -124,12 +124,12 @@ lockLoop:
|
|||||||
// wait for the lock to be released
|
// wait for the lock to be released
|
||||||
select {
|
select {
|
||||||
case <-lk.release:
|
case <-lk.release:
|
||||||
m.mtx.Lock()
|
m.mu.Lock()
|
||||||
|
|
||||||
// someone locked before us
|
// someone locked before us
|
||||||
lk, ok = m.locks[id]
|
lk, ok = m.locks[id]
|
||||||
if ok {
|
if ok {
|
||||||
m.mtx.Unlock()
|
m.mu.Unlock()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,7 +141,7 @@ lockLoop:
|
|||||||
release: make(chan bool),
|
release: make(chan bool),
|
||||||
}
|
}
|
||||||
|
|
||||||
m.mtx.Unlock()
|
m.mu.Unlock()
|
||||||
|
|
||||||
break lockLoop
|
break lockLoop
|
||||||
case <-ttl:
|
case <-ttl:
|
||||||
@@ -160,8 +160,8 @@ lockLoop:
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *memorySync) Unlock(id string) error {
|
func (m *memorySync) Unlock(id string) error {
|
||||||
m.mtx.Lock()
|
m.mu.Lock()
|
||||||
defer m.mtx.Unlock()
|
defer m.mu.Unlock()
|
||||||
|
|
||||||
lk, ok := m.locks[id]
|
lk, ok := m.locks[id]
|
||||||
// no lock exists
|
// no lock exists
|
||||||
|
@@ -46,6 +46,10 @@ func (s memoryStringer) String() string {
|
|||||||
return s.s
|
return s.s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *Tracer) Enabled() bool {
|
||||||
|
return t.opts.Enabled
|
||||||
|
}
|
||||||
|
|
||||||
func (t *Tracer) Flush(_ context.Context) error {
|
func (t *Tracer) Flush(_ context.Context) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@@ -20,6 +20,10 @@ func (t *noopTracer) Spans() []Span {
|
|||||||
|
|
||||||
var uuidNil = uuid.Nil.String()
|
var uuidNil = uuid.Nil.String()
|
||||||
|
|
||||||
|
func (t *noopTracer) Enabled() bool {
|
||||||
|
return t.opts.Enabled
|
||||||
|
}
|
||||||
|
|
||||||
func (t *noopTracer) Start(ctx context.Context, name string, opts ...SpanOption) (context.Context, Span) {
|
func (t *noopTracer) Start(ctx context.Context, name string, opts ...SpanOption) (context.Context, Span) {
|
||||||
options := NewSpanOptions(opts...)
|
options := NewSpanOptions(opts...)
|
||||||
span := &noopSpan{
|
span := &noopSpan{
|
||||||
|
@@ -142,6 +142,8 @@ type Options struct {
|
|||||||
Name string
|
Name string
|
||||||
// ContextAttrFuncs contains funcs that provides tracing
|
// ContextAttrFuncs contains funcs that provides tracing
|
||||||
ContextAttrFuncs []ContextAttrFunc
|
ContextAttrFuncs []ContextAttrFunc
|
||||||
|
// Enabled specify trace status
|
||||||
|
Enabled bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Option func signature
|
// Option func signature
|
||||||
@@ -181,6 +183,7 @@ func NewOptions(opts ...Option) Options {
|
|||||||
Logger: logger.DefaultLogger,
|
Logger: logger.DefaultLogger,
|
||||||
Context: context.Background(),
|
Context: context.Background(),
|
||||||
ContextAttrFuncs: DefaultContextAttrFuncs,
|
ContextAttrFuncs: DefaultContextAttrFuncs,
|
||||||
|
Enabled: true,
|
||||||
}
|
}
|
||||||
for _, o := range opts {
|
for _, o := range opts {
|
||||||
o(&options)
|
o(&options)
|
||||||
@@ -194,3 +197,10 @@ func Name(n string) Option {
|
|||||||
o.Name = n
|
o.Name = n
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Disabled disable tracer
|
||||||
|
func Disabled(b bool) Option {
|
||||||
|
return func(o *Options) {
|
||||||
|
o.Enabled = !b
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -51,6 +51,8 @@ type Tracer interface {
|
|||||||
// Extract(ctx context.Context)
|
// Extract(ctx context.Context)
|
||||||
// Flush flushes spans
|
// Flush flushes spans
|
||||||
Flush(ctx context.Context) error
|
Flush(ctx context.Context) error
|
||||||
|
// Enabled returns tracer status
|
||||||
|
Enabled() bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type Span interface {
|
type Span interface {
|
||||||
|
@@ -67,6 +67,12 @@ func (b *SeekerBuffer) Close() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset clears all the data out of the buffer and sets the read position to 0.
|
||||||
|
func (b *SeekerBuffer) Reset() {
|
||||||
|
b.data = nil
|
||||||
|
b.pos = 0
|
||||||
|
}
|
||||||
|
|
||||||
// Len returns the length of data remaining to be read.
|
// Len returns the length of data remaining to be read.
|
||||||
func (b *SeekerBuffer) Len() int {
|
func (b *SeekerBuffer) Len() int {
|
||||||
return len(b.data[b.pos:])
|
return len(b.data[b.pos:])
|
||||||
|
@@ -137,7 +137,7 @@ type cache struct {
|
|||||||
|
|
||||||
opts Options
|
opts Options
|
||||||
|
|
||||||
sync.RWMutex
|
mu sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
type cacheEntry struct {
|
type cacheEntry struct {
|
||||||
@@ -171,7 +171,7 @@ func (c *cache) put(req string, res string) {
|
|||||||
ttl = c.opts.MaxCacheTTL
|
ttl = c.opts.MaxCacheTTL
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Lock()
|
c.mu.Lock()
|
||||||
if c.entries == nil {
|
if c.entries == nil {
|
||||||
c.entries = make(map[string]cacheEntry)
|
c.entries = make(map[string]cacheEntry)
|
||||||
}
|
}
|
||||||
@@ -207,7 +207,7 @@ func (c *cache) put(req string, res string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
c.opts.Meter.Counter(semconv.CacheItemsTotal, "type", "dns").Inc()
|
c.opts.Meter.Counter(semconv.CacheItemsTotal, "type", "dns").Inc()
|
||||||
c.Unlock()
|
c.mu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cache) get(req string) (res string) {
|
func (c *cache) get(req string) (res string) {
|
||||||
@@ -219,8 +219,8 @@ func (c *cache) get(req string) (res string) {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
c.RLock()
|
c.mu.RLock()
|
||||||
defer c.RUnlock()
|
defer c.mu.RUnlock()
|
||||||
|
|
||||||
if c.entries == nil {
|
if c.entries == nil {
|
||||||
return ""
|
return ""
|
||||||
|
@@ -20,7 +20,7 @@ type dnsConn struct {
|
|||||||
ibuf bytes.Buffer
|
ibuf bytes.Buffer
|
||||||
obuf bytes.Buffer
|
obuf bytes.Buffer
|
||||||
|
|
||||||
sync.Mutex
|
mu sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
type roundTripper func(ctx context.Context, req string) (res string, err error)
|
type roundTripper func(ctx context.Context, req string) (res string, err error)
|
||||||
@@ -42,15 +42,15 @@ func (c *dnsConn) Read(b []byte) (n int, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *dnsConn) Write(b []byte) (n int, err error) {
|
func (c *dnsConn) Write(b []byte) (n int, err error) {
|
||||||
c.Lock()
|
c.mu.Lock()
|
||||||
defer c.Unlock()
|
defer c.mu.Unlock()
|
||||||
return c.ibuf.Write(b)
|
return c.ibuf.Write(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *dnsConn) Close() error {
|
func (c *dnsConn) Close() error {
|
||||||
c.Lock()
|
c.mu.Lock()
|
||||||
cancel := c.cancel
|
cancel := c.cancel
|
||||||
c.Unlock()
|
c.mu.Unlock()
|
||||||
|
|
||||||
if cancel != nil {
|
if cancel != nil {
|
||||||
cancel()
|
cancel()
|
||||||
@@ -78,9 +78,9 @@ func (c *dnsConn) SetDeadline(t time.Time) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *dnsConn) SetReadDeadline(t time.Time) error {
|
func (c *dnsConn) SetReadDeadline(t time.Time) error {
|
||||||
c.Lock()
|
c.mu.Lock()
|
||||||
c.deadline = t
|
c.deadline = t
|
||||||
c.Unlock()
|
c.mu.Unlock()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,8 +90,8 @@ func (c *dnsConn) SetWriteDeadline(_ time.Time) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *dnsConn) drainBuffers(b []byte) (string, int, error) {
|
func (c *dnsConn) drainBuffers(b []byte) (string, int, error) {
|
||||||
c.Lock()
|
c.mu.Lock()
|
||||||
defer c.Unlock()
|
defer c.mu.Unlock()
|
||||||
|
|
||||||
// drain the output buffer
|
// drain the output buffer
|
||||||
if c.obuf.Len() > 0 {
|
if c.obuf.Len() > 0 {
|
||||||
@@ -119,8 +119,8 @@ func (c *dnsConn) drainBuffers(b []byte) (string, int, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *dnsConn) fillBuffer(b []byte, str string) (int, error) {
|
func (c *dnsConn) fillBuffer(b []byte, str string) (int, error) {
|
||||||
c.Lock()
|
c.mu.Lock()
|
||||||
defer c.Unlock()
|
defer c.mu.Unlock()
|
||||||
c.obuf.WriteByte(byte(len(str) >> 8))
|
c.obuf.WriteByte(byte(len(str) >> 8))
|
||||||
c.obuf.WriteByte(byte(len(str)))
|
c.obuf.WriteByte(byte(len(str)))
|
||||||
c.obuf.WriteString(str)
|
c.obuf.WriteString(str)
|
||||||
@@ -128,8 +128,8 @@ func (c *dnsConn) fillBuffer(b []byte, str string) (int, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *dnsConn) childContext() (context.Context, context.CancelFunc) {
|
func (c *dnsConn) childContext() (context.Context, context.CancelFunc) {
|
||||||
c.Lock()
|
c.mu.Lock()
|
||||||
defer c.Unlock()
|
defer c.mu.Unlock()
|
||||||
if c.ctx == nil {
|
if c.ctx == nil {
|
||||||
c.ctx, c.cancel = context.WithCancel(context.Background())
|
c.ctx, c.cancel = context.WithCancel(context.Background())
|
||||||
}
|
}
|
||||||
|
@@ -52,7 +52,7 @@ type clientTracer struct {
|
|||||||
tr tracer.Tracer
|
tr tracer.Tracer
|
||||||
activeHooks map[string]context.Context
|
activeHooks map[string]context.Context
|
||||||
root tracer.Span
|
root tracer.Span
|
||||||
mtx sync.Mutex
|
mu sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewClientTrace(ctx context.Context, tr tracer.Tracer) *httptrace.ClientTrace {
|
func NewClientTrace(ctx context.Context, tr tracer.Tracer) *httptrace.ClientTrace {
|
||||||
@@ -83,8 +83,8 @@ func NewClientTrace(ctx context.Context, tr tracer.Tracer) *httptrace.ClientTrac
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ct *clientTracer) start(hook, spanName string, attrs ...interface{}) {
|
func (ct *clientTracer) start(hook, spanName string, attrs ...interface{}) {
|
||||||
ct.mtx.Lock()
|
ct.mu.Lock()
|
||||||
defer ct.mtx.Unlock()
|
defer ct.mu.Unlock()
|
||||||
|
|
||||||
if hookCtx, found := ct.activeHooks[hook]; !found {
|
if hookCtx, found := ct.activeHooks[hook]; !found {
|
||||||
var sp tracer.Span
|
var sp tracer.Span
|
||||||
@@ -104,8 +104,8 @@ func (ct *clientTracer) start(hook, spanName string, attrs ...interface{}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ct *clientTracer) end(hook string, err error, attrs ...interface{}) {
|
func (ct *clientTracer) end(hook string, err error, attrs ...interface{}) {
|
||||||
ct.mtx.Lock()
|
ct.mu.Lock()
|
||||||
defer ct.mtx.Unlock()
|
defer ct.mu.Unlock()
|
||||||
if ctx, ok := ct.activeHooks[hook]; ok { // nolint:nestif
|
if ctx, ok := ct.activeHooks[hook]; ok { // nolint:nestif
|
||||||
if span, ok := tracer.SpanFromContext(ctx); ok {
|
if span, ok := tracer.SpanFromContext(ctx); ok {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -136,8 +136,8 @@ func (ct *clientTracer) getParentContext(hook string) context.Context {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ct *clientTracer) span(hook string) (tracer.Span, bool) {
|
func (ct *clientTracer) span(hook string) (tracer.Span, bool) {
|
||||||
ct.mtx.Lock()
|
ct.mu.Lock()
|
||||||
defer ct.mtx.Unlock()
|
defer ct.mu.Unlock()
|
||||||
if ctx, ok := ct.activeHooks[hook]; ok {
|
if ctx, ok := ct.activeHooks[hook]; ok {
|
||||||
return tracer.SpanFromContext(ctx)
|
return tracer.SpanFromContext(ctx)
|
||||||
}
|
}
|
||||||
|
@@ -2,12 +2,8 @@ package id
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/binary"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
uuidv8 "github.com/ash3in/uuidv8"
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
nanoid "github.com/matoous/go-nanoid"
|
nanoid "github.com/matoous/go-nanoid"
|
||||||
)
|
)
|
||||||
@@ -25,6 +21,7 @@ type Type int
|
|||||||
const (
|
const (
|
||||||
TypeUnspecified Type = iota
|
TypeUnspecified Type = iota
|
||||||
TypeNanoid
|
TypeNanoid
|
||||||
|
TypeUUIDv7
|
||||||
TypeUUIDv8
|
TypeUUIDv8
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -58,14 +55,14 @@ func (g *Generator) New() (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return nanoid.Generate(g.opts.NanoidAlphabet, g.opts.NanoidSize)
|
return nanoid.Generate(g.opts.NanoidAlphabet, g.opts.NanoidSize)
|
||||||
case TypeUUIDv8:
|
case TypeUUIDv7:
|
||||||
timestamp := uint64(time.Now().UnixNano())
|
uid, err := uuid.NewV7()
|
||||||
clockSeq := make([]byte, 2)
|
if err != nil {
|
||||||
if _, err := rand.Read(clockSeq); err != nil {
|
return "", err
|
||||||
return "", fmt.Errorf("failed to generate random clock sequence: %w", err)
|
|
||||||
}
|
}
|
||||||
clockSeqValue := binary.BigEndian.Uint16(clockSeq) & 0x0FFF // Mask to 12 bits
|
return uid.String(), nil
|
||||||
return uuidv8.NewWithParams(timestamp, clockSeqValue, g.opts.UUIDNode[:], uuidv8.TimestampBits48)
|
case TypeUUIDv8:
|
||||||
|
return "", errors.New("unsupported uuid version v8")
|
||||||
}
|
}
|
||||||
return "", errors.New("invalid option, Type unspecified")
|
return "", errors.New("invalid option, Type unspecified")
|
||||||
}
|
}
|
||||||
@@ -82,16 +79,15 @@ func New(opts ...Option) (string, error) {
|
|||||||
if options.NanoidSize <= 0 {
|
if options.NanoidSize <= 0 {
|
||||||
return "", errors.New("invalid option, NanoidSize must be positive integer")
|
return "", errors.New("invalid option, NanoidSize must be positive integer")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nanoid.Generate(options.NanoidAlphabet, options.NanoidSize)
|
return nanoid.Generate(options.NanoidAlphabet, options.NanoidSize)
|
||||||
case TypeUUIDv8:
|
case TypeUUIDv7:
|
||||||
timestamp := uint64(time.Now().UnixNano())
|
uid, err := uuid.NewV7()
|
||||||
clockSeq := make([]byte, 2)
|
if err != nil {
|
||||||
if _, err := rand.Read(clockSeq); err != nil {
|
return "", err
|
||||||
return "", fmt.Errorf("failed to generate random clock sequence: %w", err)
|
|
||||||
}
|
}
|
||||||
clockSeqValue := binary.BigEndian.Uint16(clockSeq) & 0x0FFF // Mask to 12 bits
|
return uid.String(), nil
|
||||||
return uuidv8.NewWithParams(timestamp, clockSeqValue, options.UUIDNode[:], uuidv8.TimestampBits48)
|
case TypeUUIDv8:
|
||||||
|
return "", errors.New("unsupported uuid version v8")
|
||||||
}
|
}
|
||||||
|
|
||||||
return "", errors.New("invalid option, Type unspecified")
|
return "", errors.New("invalid option, Type unspecified")
|
||||||
@@ -145,7 +141,7 @@ func WithUUIDNode(node [6]byte) Option {
|
|||||||
// NewOptions returns new Options struct filled by opts
|
// NewOptions returns new Options struct filled by opts
|
||||||
func NewOptions(opts ...Option) Options {
|
func NewOptions(opts ...Option) Options {
|
||||||
options := Options{
|
options := Options{
|
||||||
Type: TypeUUIDv8,
|
Type: TypeUUIDv7,
|
||||||
NanoidAlphabet: DefaultNanoidAlphabet,
|
NanoidAlphabet: DefaultNanoidAlphabet,
|
||||||
NanoidSize: DefaultNanoidSize,
|
NanoidSize: DefaultNanoidSize,
|
||||||
UUIDNode: generatedNode,
|
UUIDNode: generatedNode,
|
||||||
|
@@ -14,7 +14,7 @@ type Buffer struct {
|
|||||||
vals []*Entry
|
vals []*Entry
|
||||||
size int
|
size int
|
||||||
|
|
||||||
sync.RWMutex
|
mu sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// Entry is ring buffer data entry
|
// Entry is ring buffer data entry
|
||||||
@@ -35,8 +35,8 @@ type Stream struct {
|
|||||||
|
|
||||||
// Put adds a new value to ring buffer
|
// Put adds a new value to ring buffer
|
||||||
func (b *Buffer) Put(v interface{}) {
|
func (b *Buffer) Put(v interface{}) {
|
||||||
b.Lock()
|
b.mu.Lock()
|
||||||
defer b.Unlock()
|
defer b.mu.Unlock()
|
||||||
|
|
||||||
// append to values
|
// append to values
|
||||||
entry := &Entry{
|
entry := &Entry{
|
||||||
@@ -63,8 +63,8 @@ func (b *Buffer) Put(v interface{}) {
|
|||||||
|
|
||||||
// Get returns the last n entries
|
// Get returns the last n entries
|
||||||
func (b *Buffer) Get(n int) []*Entry {
|
func (b *Buffer) Get(n int) []*Entry {
|
||||||
b.RLock()
|
b.mu.RLock()
|
||||||
defer b.RUnlock()
|
defer b.mu.RUnlock()
|
||||||
|
|
||||||
// reset any invalid values
|
// reset any invalid values
|
||||||
if n > len(b.vals) || n < 0 {
|
if n > len(b.vals) || n < 0 {
|
||||||
@@ -80,8 +80,8 @@ func (b *Buffer) Get(n int) []*Entry {
|
|||||||
|
|
||||||
// Since returns the entries since a specific time
|
// Since returns the entries since a specific time
|
||||||
func (b *Buffer) Since(t time.Time) []*Entry {
|
func (b *Buffer) Since(t time.Time) []*Entry {
|
||||||
b.RLock()
|
b.mu.RLock()
|
||||||
defer b.RUnlock()
|
defer b.mu.RUnlock()
|
||||||
|
|
||||||
// return all the values
|
// return all the values
|
||||||
if t.IsZero() {
|
if t.IsZero() {
|
||||||
@@ -109,8 +109,8 @@ func (b *Buffer) Since(t time.Time) []*Entry {
|
|||||||
// Stream logs from the buffer
|
// Stream logs from the buffer
|
||||||
// Close the channel when you want to stop
|
// Close the channel when you want to stop
|
||||||
func (b *Buffer) Stream() (<-chan *Entry, chan bool) {
|
func (b *Buffer) Stream() (<-chan *Entry, chan bool) {
|
||||||
b.Lock()
|
b.mu.Lock()
|
||||||
defer b.Unlock()
|
defer b.mu.Unlock()
|
||||||
|
|
||||||
entries := make(chan *Entry, 128)
|
entries := make(chan *Entry, 128)
|
||||||
id := id.MustNew()
|
id := id.MustNew()
|
||||||
|
@@ -24,7 +24,7 @@ type stream struct {
|
|||||||
err error
|
err error
|
||||||
request *request
|
request *request
|
||||||
|
|
||||||
sync.RWMutex
|
mu sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
type request struct {
|
type request struct {
|
||||||
@@ -57,9 +57,9 @@ func (s *stream) Request() server.Request {
|
|||||||
func (s *stream) Send(v interface{}) error {
|
func (s *stream) Send(v interface{}) error {
|
||||||
err := s.Stream.SendMsg(v)
|
err := s.Stream.SendMsg(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.Lock()
|
s.mu.Lock()
|
||||||
s.err = err
|
s.err = err
|
||||||
s.Unlock()
|
s.mu.Unlock()
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -68,17 +68,17 @@ func (s *stream) Send(v interface{}) error {
|
|||||||
func (s *stream) Recv(v interface{}) error {
|
func (s *stream) Recv(v interface{}) error {
|
||||||
err := s.Stream.RecvMsg(v)
|
err := s.Stream.RecvMsg(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.Lock()
|
s.mu.Lock()
|
||||||
s.err = err
|
s.err = err
|
||||||
s.Unlock()
|
s.mu.Unlock()
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Error returns error that stream holds
|
// Error returns error that stream holds
|
||||||
func (s *stream) Error() error {
|
func (s *stream) Error() error {
|
||||||
s.RLock()
|
s.mu.RLock()
|
||||||
defer s.RUnlock()
|
defer s.mu.RUnlock()
|
||||||
return s.err
|
return s.err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -6,7 +6,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"gopkg.in/yaml.v3"
|
"github.com/goccy/go-yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Duration int64
|
type Duration int64
|
||||||
@@ -58,9 +58,9 @@ func (d Duration) MarshalYAML() (interface{}, error) {
|
|||||||
return time.Duration(d).String(), nil
|
return time.Duration(d).String(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Duration) UnmarshalYAML(n *yaml.Node) error {
|
func (d *Duration) UnmarshalYAML(data []byte) error {
|
||||||
var v interface{}
|
var v interface{}
|
||||||
if err := yaml.Unmarshal([]byte(n.Value), &v); err != nil {
|
if err := yaml.Unmarshal(data, &v); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
switch value := v.(type) {
|
switch value := v.(type) {
|
||||||
|
@@ -6,7 +6,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"gopkg.in/yaml.v3"
|
"github.com/goccy/go-yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMarshalYAML(t *testing.T) {
|
func TestMarshalYAML(t *testing.T) {
|
||||||
|
Reference in New Issue
Block a user