Skip to content
Open
Show file tree
Hide file tree
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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ The following emojis are used to highlight certain changes:

### Added

- `bootstrap`: `BootstrapConfig.DeferFirstRound` runs the first bootstrap round after one `Period` instead of right away, and `Bootstrap` returns without waiting for it. Callers that bring up connections their own way at startup can then dial bootstrap peers only if that falls short. Off by default. [#1223](https://github.com/ipfs/boxo/pull/1223)

### Changed

- `bootstrap`: `Bootstrap` now always returns after the first bootstrap round has completed, which can take up to `ConnectionTimeout` (10s by default). Previously it waited only when backup peers were configured, and returned right away otherwise. [#1220](https://github.com/ipfs/boxo/pull/1220)
Expand Down
21 changes: 16 additions & 5 deletions bootstrap/bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,13 @@ type BootstrapConfig struct {
// as backup bootstrap peers.
MaxBackupBootstrapSize int

// DeferFirstRound skips the round Bootstrap otherwise runs right away:
// the first round runs after Period, and Bootstrap returns without
// waiting for it. This suits callers that bring up connections their own
// way at startup, and only want bootstrap peers dialed if that falls
// short.
DeferFirstRound bool

saveBackupBootstrapPeers func(context.Context, []peer.AddrInfo)
loadBackupBootstrapPeers func(context.Context) []peer.AddrInfo
}
Expand Down Expand Up @@ -118,7 +125,8 @@ func Bootstrap(id peer.ID, host host.Host, rt routing.Routing, cfg BootstrapConf

ctx, cancel := context.WithCancel(context.Background())

// Closed when the first bootstrap round, started independent of the ticker, is complete.
// Closed when the first bootstrap round, started independent of the ticker,
// is complete, or right away when cfg.DeferFirstRound skips it.
firstRoundDone := make(chan struct{})

go func() {
Expand All @@ -132,8 +140,10 @@ func Bootstrap(id peer.ID, host host.Host, rt routing.Routing, cfg BootstrapConf
ticker := time.NewTicker(cfg.Period)
defer ticker.Stop()

// Run first round independent of ticker.
periodic()
// Run first round independent of ticker, unless it waits for the first tick.
if !cfg.DeferFirstRound {
periodic()
}
close(firstRoundDone)
if ctx.Err() != nil {
return
Expand Down Expand Up @@ -193,8 +203,9 @@ func startSavePeersAsTemporaryBootstrapProc(ctx context.Context, cfg BootstrapCo
ticker := time.NewTicker(cfg.BackupBootstrapInterval)
defer ticker.Stop()

// Run the first round now (after the first bootstrap process has
// finished) as the SavePeersPeriod can be much longer than bootstrap.
// Save right away, as BackupBootstrapInterval can be much longer than
// Period. This follows the first bootstrap round, unless
// cfg.DeferFirstRound skipped it.
periodic()
if ctx.Err() != nil {
return
Expand Down
27 changes: 27 additions & 0 deletions bootstrap/bootstrap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -535,3 +535,30 @@ func TestBootstrapStartsBackupSaving(t *testing.T) {
}
})
}

func TestBootstrapDeferFirstRound(t *testing.T) {
const periods = 5
for _, tt := range backupCases {
t.Run(tt.name, func(t *testing.T) {
synctest.Test(t, func(t *testing.T) {
counter := &roundCounter{}
cfg := newTestConfig(counter, tt.withBackup)
cfg.DeferFirstRound = true
startBootstrap(t, fakeHost{}, cfg)

synctest.Wait()
if got := counter.rounds(); got != 0 {
t.Fatalf("%d rounds ran before the first period, want 0", got)
}

// Sleep off the tick boundary so the count is exact.
time.Sleep(periods*testPeriod + testPeriod/2)
synctest.Wait()

if got := counter.rounds(); got != periods {
t.Fatalf("got %d rounds over %d periods, want one per period", got, periods)
}
})
})
}
}
Loading