-
Notifications
You must be signed in to change notification settings - Fork 269
/
storage.go
99 lines (91 loc) · 3.28 KB
/
storage.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// Copyright 2022 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
package election
import (
"context"
"time"
)
// Storage describes the requirements of a storage that can be used for leader election.
type Storage interface {
// Get gets the current record from the storage. It returns the current record stored
// in the storage and any error encountered. Note that if the record has not created yet,
// it should return an empty record and a nil error.
Get(ctx context.Context) (*Record, error)
// Update updates the record in the storage if the stored record version matches the given
// record version. It returns ErrRecordConflict if the stored record version does not match
// or any other error encountered.
Update(ctx context.Context, record *Record, isLeaderChanged bool) error
}
// Record holds the information of a leader election.
type Record struct {
// LeaderID is the ID of the leader. If it is empty, it means
// there is no leader and all members may try to become leader.
LeaderID string `json:"leader_id"`
// Members is the members that are eligible to become leader,
// which includes the leader itself.
Members []*Member `json:"members"`
// Version is the internal version of the record. It can be used by
// specific storage implementation to determine whether the record has
// been changed by another writer. The caller of the storage interface
// should treat this value as opaque.
//
// Skip serializing this field, because it is not part of the record content.
Version int64 `json:"-"`
}
// Member is a member in a leader election.
type Member struct {
// ID is the ID of the member.
ID string `json:"id"`
// Name is the human-readable name of the member.
// It is used for logging and diagnostics.
Name string `json:"name"`
// Address is the address of the member.
Address string `json:"address"`
// LeaseDuration is the duration that a client will wait before
// it can remove this member when the client hasn't observed
// any renewals from the member.
LeaseDuration time.Duration `json:"lease_duration"`
// RenewTime is the last time when the member renewed its lease.
RenewTime time.Time `json:"renew_time"`
}
// Clone returns a deep copy of the member.
func (m *Member) Clone() *Member {
return &Member{
ID: m.ID,
Name: m.Name,
Address: m.Address,
LeaseDuration: m.LeaseDuration,
RenewTime: m.RenewTime,
}
}
// Clone returns a deep copy of the record.
func (r *Record) Clone() *Record {
members := make([]*Member, len(r.Members))
for i, m := range r.Members {
members[i] = m.Clone()
}
return &Record{
LeaderID: r.LeaderID,
Members: members,
Version: r.Version,
}
}
// FindMember finds the member with the given ID in the record.
func (r *Record) FindMember(id string) (*Member, bool) {
for _, m := range r.Members {
if m.ID == id {
return m, true
}
}
return nil, false
}