frostfs-node/lib/transport/transport.go

77 lines
1.6 KiB
Go
Raw Normal View History

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}
}