github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/pkg/election/storage.go (about)

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