Skip to content
This repository has been archived by the owner on May 26, 2022. It is now read-only.

Commit

Permalink
fix and tests for backoff connector
Browse files Browse the repository at this point in the history
  • Loading branch information
aschmahmann committed Oct 13, 2019
1 parent 09f4d64 commit f88f93e
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 5 deletions.
15 changes: 10 additions & 5 deletions backoffconnector.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,34 @@ package discovery

import (
"context"
lru "github.com/hashicorp/golang-lru"
"sync"
"time"

"github.com/libp2p/go-libp2p-core/host"
"github.com/libp2p/go-libp2p-core/peer"

"github.com/hashicorp/golang-lru/simplelru"
)

type BackoffConnector struct {
cache simplelru.LRUCache
cache *lru.TwoQueueCache
host host.Host
connTryDur time.Duration
backoff BackoffFactory
mux sync.Mutex
}

func NewBackoffConnector(h host.Host, cache simplelru.LRUCache, connectionTryDuration time.Duration, backoff BackoffFactory) *BackoffConnector {
func NewBackoffConnector(h host.Host, cacheSize int, connectionTryDuration time.Duration, backoff BackoffFactory) (*BackoffConnector, error) {
cache, err := lru.New2Q(cacheSize)
if err != nil {
return nil, err
}

return &BackoffConnector{
cache: cache,
host: h,
connTryDur: connectionTryDuration,
backoff: backoff,
}
}, nil
}

type connCacheData struct {
Expand Down Expand Up @@ -62,6 +66,7 @@ func (c *BackoffConnector) Connect(ctx context.Context, peerCh <-chan peer.AddrI
cachedPeer.nextTry = time.Now().Add(cachedPeer.strat.Delay())
c.cache.Add(pi.ID, cachedPeer)
}
c.mux.Unlock()

go func(pi peer.AddrInfo) {
ctx, cancel := context.WithTimeout(ctx, c.connTryDur)
Expand Down
108 changes: 108 additions & 0 deletions backoffconnector_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package discovery

import (
"context"
"fmt"
"sync"
"testing"
"time"

bhost "github.com/libp2p/go-libp2p-blankhost"
"github.com/libp2p/go-libp2p-core/host"
"github.com/libp2p/go-libp2p-core/peer"
swarmt "github.com/libp2p/go-libp2p-swarm/testing"
)

type maxDialHost struct {
host.Host

mux sync.Mutex
timesDialed map[peer.ID]int
maxTimesToDial map[peer.ID]int
}

func (h *maxDialHost) Connect(ctx context.Context, ai peer.AddrInfo) error {
pid := ai.ID

h.mux.Lock()
defer h.mux.Unlock()
numDials := h.timesDialed[pid]
numDials += 1
h.timesDialed[pid] = numDials

if maxDials, ok := h.maxTimesToDial[pid]; ok && numDials > maxDials {
return fmt.Errorf("should not be dialing peer %s", pid.String())
}

return h.Host.Connect(ctx, ai)
}

func getNetHosts(t *testing.T, ctx context.Context, n int) []host.Host {
var out []host.Host

for i := 0; i < n; i++ {
netw := swarmt.GenSwarm(t, ctx)
h := bhost.NewBlankHost(netw)
out = append(out, h)
}

return out
}

func loadCh(peers []host.Host) <-chan peer.AddrInfo {
ch := make(chan peer.AddrInfo, len(peers))
for _, p := range peers {
ch <- p.Peerstore().PeerInfo(p.ID())
}
close(ch)
return ch
}

func TestBackoffConnector(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

hosts := getNetHosts(t, ctx, 5)
primary := &maxDialHost{
Host: hosts[0],
mux: sync.Mutex{},
timesDialed: make(map[peer.ID]int),
maxTimesToDial: map[peer.ID]int{
hosts[1].ID(): 1,
hosts[2].ID(): 2,
},
}

bc, err := NewBackoffConnector(primary, 10, time.Minute, NewFixedBackoff(time.Millisecond*1500))
if err != nil {
t.Fatal(err)
}

bc.Connect(ctx, loadCh(hosts))

time.Sleep(time.Millisecond * 100)
if expected, actual := len(hosts) - 1, len(primary.Network().Conns()); actual != expected {
t.Fatalf("wrong number of connections. expected %d, actual %d", expected, actual)
}

for _, c := range primary.Network().Conns() {
c.Close()
}

for len(primary.Network().Conns()) > 0 {
time.Sleep(time.Millisecond * 100)
}

bc.Connect(ctx, loadCh(hosts))
if numConns := len(primary.Network().Conns()); numConns != 0 {
t.Fatal("shouldn't be connected to any peers")
}

time.Sleep(time.Millisecond * 1600)
bc.Connect(ctx, loadCh(hosts))

time.Sleep(time.Millisecond * 100)
if expected, actual := len(hosts) - 2, len(primary.Network().Conns()); actual != expected {
t.Fatalf("wrong number of connections. expected %d, actual %d", expected, actual)
}
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module github.com/libp2p/go-libp2p-discovery

require (
github.com/hashicorp/golang-lru v0.5.1
github.com/ipfs/go-cid v0.0.2
github.com/ipfs/go-log v0.0.1
github.com/libp2p/go-libp2p-blankhost v0.1.1
Expand Down
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ github.com/gxed/hashland/keccakpg v0.0.1 h1:wrk3uMNaMxbXiHibbPO4S0ymqJMm41WiudyF
github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU=
github.com/gxed/hashland/murmur3 v0.0.1 h1:SheiaIt0sda5K+8FLz952/1iWS9zrnKsEJaOJu4ZbSc=
github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48=
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
Expand Down

0 comments on commit f88f93e

Please sign in to comment.