Skip to content

Commit 8e64c77

Browse files
authored
Merge pull request #4353 from tinyspeck/fix-for-consul-master-election
Do not reuse a consul lock
2 parents eccf912 + dc2cbe0 commit 8e64c77

File tree

1 file changed

+17
-18
lines changed

1 file changed

+17
-18
lines changed

go/vt/topo/consultopo/election.go

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,8 @@ import (
2828

2929
// NewMasterParticipation is part of the topo.Server interface
3030
func (s *Server) NewMasterParticipation(name, id string) (topo.MasterParticipation, error) {
31-
// Create the lock here.
32-
electionPath := path.Join(s.root, electionsPath, name)
33-
l, err := s.client.LockOpts(&api.LockOptions{
34-
Key: electionPath,
35-
Value: []byte(id),
36-
})
37-
if err != nil {
38-
return nil, err
39-
}
40-
4131
return &consulMasterParticipation{
4232
s: s,
43-
lock: l,
4433
name: name,
4534
id: id,
4635
stop: make(chan struct{}),
@@ -56,9 +45,6 @@ type consulMasterParticipation struct {
5645
// s is our parent consul topo Server
5746
s *Server
5847

59-
// lock is the *api.Lock structure we're going to use.
60-
lock *api.Lock
61-
6248
// name is the name of this MasterParticipation
6349
name string
6450

@@ -74,6 +60,16 @@ type consulMasterParticipation struct {
7460

7561
// WaitForMastership is part of the topo.MasterParticipation interface.
7662
func (mp *consulMasterParticipation) WaitForMastership() (context.Context, error) {
63+
64+
electionPath := path.Join(mp.s.root, electionsPath, mp.name)
65+
l, err := mp.s.client.LockOpts(&api.LockOptions{
66+
Key: electionPath,
67+
Value: []byte(mp.id),
68+
})
69+
if err != nil {
70+
return nil, err
71+
}
72+
7773
// If Stop was already called, mp.done is closed, so we are interrupted.
7874
select {
7975
case <-mp.done:
@@ -82,7 +78,7 @@ func (mp *consulMasterParticipation) WaitForMastership() (context.Context, error
8278
}
8379

8480
// Try to lock until mp.stop is closed.
85-
lost, err := mp.lock.Lock(mp.stop)
81+
lost, err := l.Lock(mp.stop)
8682
if err != nil {
8783
// We can't lock. See if it was because we got canceled.
8884
select {
@@ -93,19 +89,22 @@ func (mp *consulMasterParticipation) WaitForMastership() (context.Context, error
9389
return nil, err
9490
}
9591

96-
// We have the lock, keep mastership until we loose it.
92+
// We have the lock, keep mastership until we lose it.
9793
lockCtx, lockCancel := context.WithCancel(context.Background())
9894
go func() {
9995
select {
10096
case <-lost:
101-
// We lost the lock, nothing to do but lockCancel().
10297
lockCancel()
98+
// We could have lost the lock. Per consul API, explicitly call Unlock to make sure that session will not be renewed.
99+
if err := l.Unlock(); err != nil {
100+
log.Errorf("master election(%v) Unlock failed: %v", mp.name, err)
101+
}
103102
case <-mp.stop:
104103
// Stop was called. We stop the context first,
105104
// so the running process is not thinking it
106105
// is the master any more, then we unlock.
107106
lockCancel()
108-
if err := mp.lock.Unlock(); err != nil {
107+
if err := l.Unlock(); err != nil {
109108
log.Errorf("master election(%v) Unlock failed: %v", mp.name, err)
110109
}
111110
close(mp.done)

0 commit comments

Comments
 (0)