Skip to content

Commit 068c5f9

Browse files
committed
fix(badgerd/gossip): skip stale startup election when leader is already known
Signed-off-by: Adphi <philippe.adrien.nousse@gmail.com>
1 parent 8520f0a commit 068c5f9

File tree

2 files changed

+41
-2
lines changed

2 files changed

+41
-2
lines changed

internal/badgerd/replication/gossip/gossip.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,9 @@ func (r *Gossip) run(ctx context.Context) {
295295
if ctx.Err() != nil {
296296
return
297297
}
298+
if r.HasLeader() {
299+
return
300+
}
298301
r.Elect(ctx)
299302
}()
300303
}

internal/badgerd/replication/gossip/gossip_test.go

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
package gossip
22

33
import (
4+
"context"
45
"testing"
56
"time"
67

8+
"github.com/hashicorp/memberlist"
9+
"github.com/stretchr/testify/assert"
710
pubsub "go.linka.cloud/pubsub/typed"
811
"google.golang.org/grpc"
912

10-
"github.com/stretchr/testify/assert"
11-
1213
"go.linka.cloud/protodb/internal/badgerd/replication"
14+
pb2 "go.linka.cloud/protodb/internal/badgerd/replication/gossip/pb"
1315
)
1416

1517
func TestGossipSimpleMethodsTable(t *testing.T) {
@@ -49,3 +51,37 @@ func TestGossipSimpleMethodsTable(t *testing.T) {
4951
assert.NotNil(t, conn)
5052
assert.Same(t, cc, conn)
5153
}
54+
55+
func TestRunSkipsElectionWhenLeaderAlreadyKnown(t *testing.T) {
56+
ctx, cancel := context.WithCancel(context.Background())
57+
defer cancel()
58+
59+
r := &Gossip{
60+
ctx: ctx,
61+
name: "self",
62+
shuttingDown: NewAtomic(false),
63+
leading: NewAtomic(false),
64+
leaderName: NewAtomic("peer"),
65+
bootNodes: []string{"peer"},
66+
ready: make(chan struct{}),
67+
events: make(chan memberlist.NodeEvent),
68+
converged: make(chan struct{}),
69+
pub: pubsub.NewPublisher[string](time.Second, 2),
70+
}
71+
r.meta.Store(&pb2.Meta{LocalVersion: 1})
72+
close(r.converged)
73+
74+
r.run(ctx)
75+
t.Cleanup(func() { close(r.events) })
76+
77+
time.Sleep(1500 * time.Millisecond)
78+
79+
assert.Equal(t, "peer", r.CurrentLeader())
80+
assert.False(t, r.IsLeader())
81+
assert.False(t, r.HasLeader() && r.CurrentLeader() == "self")
82+
select {
83+
case <-r.ready:
84+
t.Fatal("expected ready to stay open")
85+
default:
86+
}
87+
}

0 commit comments

Comments
 (0)