103 lines
1.9 KiB
Go
103 lines
1.9 KiB
Go
package peer
|
|
|
|
import (
|
|
"context"
|
|
"github.com/anyproto/any-sync/app/ocache"
|
|
"github.com/anyproto/any-sync/net/transport"
|
|
"storj.io/drpc"
|
|
"storj.io/drpc/drpcconn"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/anyproto/any-sync/app/logger"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
var log = logger.NewNamed("common.net.peer")
|
|
|
|
func NewPeer(mc transport.MultiConn) (p Peer, err error) {
|
|
ctx := mc.Context()
|
|
pr := &peer{
|
|
active: map[drpc.Conn]struct{}{},
|
|
MultiConn: mc,
|
|
}
|
|
if pr.id, err = CtxPeerId(ctx); err != nil {
|
|
return
|
|
}
|
|
return pr, nil
|
|
}
|
|
|
|
type Peer interface {
|
|
Id() string
|
|
|
|
AcquireDrpcConn(ctx context.Context) (drpc.Conn, error)
|
|
ReleaseDrpcConn(conn drpc.Conn)
|
|
|
|
IsClosed() bool
|
|
|
|
TryClose(objectTTL time.Duration) (res bool, err error)
|
|
|
|
ocache.Object
|
|
}
|
|
|
|
type peer struct {
|
|
id string
|
|
|
|
// drpc conn pool
|
|
inactive []drpc.Conn
|
|
active map[drpc.Conn]struct{}
|
|
mu sync.Mutex
|
|
|
|
transport.MultiConn
|
|
}
|
|
|
|
func (p *peer) Id() string {
|
|
return p.id
|
|
}
|
|
|
|
func (p *peer) AcquireDrpcConn(ctx context.Context) (drpc.Conn, error) {
|
|
p.mu.Lock()
|
|
defer p.mu.Unlock()
|
|
if len(p.inactive) == 0 {
|
|
conn, err := p.Open(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
dconn := drpcconn.New(conn)
|
|
p.inactive = append(p.inactive, dconn)
|
|
}
|
|
idx := len(p.inactive) - 1
|
|
res := p.inactive[idx]
|
|
p.inactive = p.inactive[:idx]
|
|
p.active[res] = struct{}{}
|
|
return res, nil
|
|
}
|
|
|
|
func (p *peer) ReleaseDrpcConn(conn drpc.Conn) {
|
|
p.mu.Lock()
|
|
defer p.mu.Unlock()
|
|
if _, ok := p.active[conn]; ok {
|
|
delete(p.active, conn)
|
|
}
|
|
p.inactive = append(p.inactive, conn)
|
|
return
|
|
}
|
|
|
|
func (p *peer) TryClose(objectTTL time.Duration) (res bool, err error) {
|
|
if time.Now().Sub(p.LastUsage()) < objectTTL {
|
|
return false, nil
|
|
}
|
|
p.mu.Lock()
|
|
if len(p.active) > 0 {
|
|
p.mu.Unlock()
|
|
return false, nil
|
|
}
|
|
p.mu.Unlock()
|
|
return true, p.Close()
|
|
}
|
|
|
|
func (p *peer) Close() (err error) {
|
|
log.Debug("peer close", zap.String("peerId", p.id))
|
|
return p.MultiConn.Close()
|
|
}
|