mirror of
https://github.com/netbirdio/netbird.git
synced 2026-08-25 09:01:29 +02:00
On network changes the client restarted the whole engine. That is heavy-handed and slow: it tears down working state to recover from a transition the engine could handle itself. This replaces the restart with proper network event handling. Suspend the retry loops while no network is available. Instead of burning through backoff intervals against an unreachable network, the reconnection loops park until the OS reports a usable network again. Reconnect immediately on a network switch. When the OS hands us a new network, connections bound to the old one are swept and re-dialed right away, rather than waiting for a timeout to notice they are dead.
59 lines
1.8 KiB
Go
59 lines
1.8 KiB
Go
package netsweep
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/cenkalti/backoff/v4"
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestQuickRetryAfterRecentMark(t *testing.T) {
|
|
sweeper := New()
|
|
sweeper.MarkNetworkChange()
|
|
|
|
slow := backoff.NewConstantBackOff(5 * time.Second)
|
|
bo := sweeper.QuickRetryBackoff(context.Background(), slow, nil)
|
|
|
|
assert.Equal(t, quickRetryDelay, bo.NextBackOff(), "first retry after a mark must be quick")
|
|
assert.Equal(t, 5*time.Second, bo.NextBackOff(), "second retry must fall back to the wrapped backoff")
|
|
|
|
bo.Reset()
|
|
assert.Equal(t, quickRetryDelay, bo.NextBackOff(), "reset must re-arm the quick retry")
|
|
}
|
|
|
|
func TestQuickRetryWithoutMarkKeepsSpread(t *testing.T) {
|
|
sweeper := New()
|
|
|
|
slow := backoff.NewConstantBackOff(5 * time.Second)
|
|
bo := sweeper.QuickRetryBackoff(context.Background(), slow, nil)
|
|
|
|
assert.Equal(t, 5*time.Second, bo.NextBackOff(), "without a mark the wrapped backoff decides")
|
|
|
|
sweeper.mu.Lock()
|
|
sweeper.lastMark = time.Now().Add(-recentMarkWindow)
|
|
sweeper.mu.Unlock()
|
|
assert.Equal(t, 5*time.Second, bo.NextBackOff(), "a stale mark must not trigger the quick retry")
|
|
}
|
|
|
|
func TestQuickRetryNilSweeperPassthrough(t *testing.T) {
|
|
var sweeper *Sweeper
|
|
|
|
slow := backoff.NewConstantBackOff(5 * time.Second)
|
|
bo := sweeper.QuickRetryBackoff(context.Background(), slow, nil)
|
|
|
|
assert.Equal(t, backoff.BackOff(slow), bo, "nil sweeper must return the backoff unchanged")
|
|
}
|
|
|
|
func TestQuickRetryHonorsContext(t *testing.T) {
|
|
sweeper := New()
|
|
sweeper.MarkNetworkChange()
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
cancel()
|
|
bo := sweeper.QuickRetryBackoff(ctx, backoff.NewConstantBackOff(time.Millisecond), nil)
|
|
|
|
assert.Equal(t, backoff.Stop, bo.NextBackOff(), "cancelled context must stop the retry loop")
|
|
}
|