forked from TrueCloudLab/frostfs-node
77 lines
1.6 KiB
Go
77 lines
1.6 KiB
Go
|
package transport
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"fmt"
|
||
|
"time"
|
||
|
|
||
|
"github.com/multiformats/go-multiaddr"
|
||
|
manet "github.com/multiformats/go-multiaddr-net"
|
||
|
circuit "github.com/rubyist/circuitbreaker"
|
||
|
)
|
||
|
|
||
|
type (
|
||
|
// Transport is an interface of network connection listener.
|
||
|
Transport interface {
|
||
|
Dial(context.Context, multiaddr.Multiaddr, bool) (Connection, error)
|
||
|
Listen(multiaddr.Multiaddr) (manet.Listener, error)
|
||
|
}
|
||
|
|
||
|
transport struct {
|
||
|
threshold int64
|
||
|
timeout time.Duration
|
||
|
panel *circuit.Panel
|
||
|
}
|
||
|
)
|
||
|
|
||
|
const defaultBreakerName = "_NeoFS"
|
||
|
|
||
|
func (t *transport) Dial(ctx context.Context, addr multiaddr.Multiaddr, reset bool) (Connection, error) {
|
||
|
var (
|
||
|
con manet.Conn
|
||
|
breaker = t.breakerLookup(addr)
|
||
|
)
|
||
|
|
||
|
if reset {
|
||
|
breaker.Reset()
|
||
|
}
|
||
|
|
||
|
err := breaker.CallContext(ctx, func() (errCall error) {
|
||
|
var d manet.Dialer
|
||
|
con, errCall = d.DialContext(ctx, addr)
|
||
|
return errCall
|
||
|
}, t.timeout)
|
||
|
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
return newConnection(con), nil
|
||
|
}
|
||
|
|
||
|
func (t *transport) Listen(addr multiaddr.Multiaddr) (manet.Listener, error) {
|
||
|
return manet.Listen(addr)
|
||
|
}
|
||
|
|
||
|
func (t *transport) breakerLookup(addr fmt.Stringer) *circuit.Breaker {
|
||
|
panel := defaultBreakerName + addr.String()
|
||
|
|
||
|
cb, ok := t.panel.Get(panel)
|
||
|
if !ok {
|
||
|
cb = circuit.NewConsecutiveBreaker(t.threshold)
|
||
|
t.panel.Add(panel, cb)
|
||
|
}
|
||
|
|
||
|
return cb
|
||
|
}
|
||
|
|
||
|
// New is a transport component's constructor.
|
||
|
func New(threshold int64, timeout time.Duration) Transport {
|
||
|
breaker := circuit.NewConsecutiveBreaker(threshold)
|
||
|
|
||
|
panel := circuit.NewPanel()
|
||
|
panel.Add(defaultBreakerName, breaker)
|
||
|
|
||
|
return &transport{panel: panel, threshold: threshold, timeout: timeout}
|
||
|
}
|