Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions p2p/discover/lookup.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ type lookupIterator struct {
cancel func()
lookup *lookup
tabRefreshing <-chan struct{}
lastLookup time.Time
}

type lookupFunc func(ctx context.Context) *lookup
Expand Down Expand Up @@ -185,6 +186,9 @@ func (it *lookupIterator) Next() bool {
return false
}
if it.lookup == nil {
// Ensure enough time has passed between lookup creations.
it.slowdown()

it.lookup = it.nextLookup(it.ctx)
if it.lookup.empty() {
// If the lookup is empty right after creation, it means the local table
Expand Down Expand Up @@ -235,6 +239,25 @@ func (it *lookupIterator) lookupFailed(tab *Table, timeout time.Duration) {
tab.waitForNodes(tout, 1)
}

// slowdown applies a delay between creating lookups. This exists to prevent hot-spinning
// in some test environments where lookups don't yield any results.
func (it *lookupIterator) slowdown() {
const minInterval = 1 * time.Second

now := time.Now()
diff := now.Sub(it.lastLookup)
it.lastLookup = now
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just nitpicking, but something like the following would be more precise:
defer func() { it.lastLookup = time.Now() }()

Anyway, the current one works as well for the scope here.

if diff > minInterval {
return
}
wait := time.NewTimer(diff)
defer wait.Stop()
select {
case <-wait.C:
case <-it.ctx.Done():
}
}

// Close ends the iterator.
func (it *lookupIterator) Close() {
it.cancel()
Expand Down