github.com/juju/juju@v0.0.0-20240327075706-a90865de2538/core/leadership/interface.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package leadership
     5  
     6  import (
     7  	"fmt"
     8  	"time"
     9  
    10  	"github.com/juju/errors"
    11  	"github.com/juju/worker/v3"
    12  )
    13  
    14  // TODO (manadart 2018-10-05) Add interfaces to the end of this line,
    15  // separated by commas, as they become required for mocking in tests.
    16  //go:generate go run go.uber.org/mock/mockgen -package mocks -destination mocks/leadership_mock.go github.com/juju/juju/core/leadership Pinner
    17  
    18  const (
    19  	// ErrClaimDenied is the error which will be returned when a
    20  	// leadership claim has been denied.
    21  	ErrClaimDenied = errors.ConstError("leadership claim denied")
    22  
    23  	// ErrClaimNotHeld is the error which will be returned when a
    24  	// leadership lease is not held.
    25  	ErrClaimNotHeld = errors.ConstError("leadership lease not held")
    26  
    27  	// ErrBlockCancelled is returned from BlockUntilLeadershipReleased
    28  	// if the client cancels the request by closing the cancel channel.
    29  	ErrBlockCancelled = errors.ConstError("waiting for leadership cancelled by client")
    30  )
    31  
    32  // NewNotLeaderError returns an error indicating that this unit is not
    33  // the leader of that application.
    34  func NewNotLeaderError(unit, application string) error {
    35  	return &notLeaderError{unit: unit, application: application}
    36  }
    37  
    38  type notLeaderError struct {
    39  	unit        string
    40  	application string
    41  }
    42  
    43  // Error is part of error.
    44  func (e notLeaderError) Error() string {
    45  	return fmt.Sprintf("%q is not leader of %q", e.unit, e.application)
    46  }
    47  
    48  // IsNotLeaderError returns whether this error represents a token
    49  // check that failed because the unit in question wasn't the leader.
    50  func IsNotLeaderError(err error) bool {
    51  	if err == nil {
    52  		return false
    53  	}
    54  	_, ok := errors.Cause(err).(*notLeaderError)
    55  	return ok
    56  }
    57  
    58  // Claimer exposes leadership acquisition capabilities.
    59  type Claimer interface {
    60  
    61  	// ClaimLeadership claims leadership of the named application on behalf of the
    62  	// named unit. If no error is returned, leadership will be guaranteed for
    63  	// at least the supplied duration from the point when the call was made.
    64  	ClaimLeadership(applicationId, unitId string, duration time.Duration) error
    65  
    66  	// BlockUntilLeadershipReleased blocks until the named application is known
    67  	// to have no leader, in which case it returns no error; or until the
    68  	// manager is stopped, in which case it will fail.
    69  	BlockUntilLeadershipReleased(applicationId string, cancel <-chan struct{}) (err error)
    70  }
    71  
    72  // Revoker exposes leadership revocation capabilities.
    73  type Revoker interface {
    74  	// RevokeLeadership revokes leadership of the named application
    75  	// on behalf of the named unit.
    76  	RevokeLeadership(applicationId, unitId string) error
    77  }
    78  
    79  // Pinner describes methods used to manage suspension of application leadership
    80  // expiry. All methods should be idempotent.
    81  type Pinner interface {
    82  
    83  	// PinLeadership ensures that the leadership of the input application will
    84  	// not expire. The input entity records the party responsible for the
    85  	// pinning operation.
    86  	PinLeadership(applicationId string, entity string) error
    87  
    88  	// UnpinLeadership reverses a PinLeadership operation for the same
    89  	// application and entity. Normal expiry behaviour is restored when no
    90  	// entities remain with pins for the application.
    91  	UnpinLeadership(applicationId string, entity string) error
    92  
    93  	// PinnedLeadership returns a map keyed on pinned application names,
    94  	// with entities that require the application's pinned behaviour.
    95  	PinnedLeadership() (map[string][]string, error)
    96  }
    97  
    98  // Token represents a unit's leadership of its application.
    99  type Token interface {
   100  	// Check returns an error if the condition it embodies no longer holds.
   101  	Check() error
   102  }
   103  
   104  // Checker exposes leadership testing capabilities.
   105  type Checker interface {
   106  
   107  	// LeadershipCheck returns a Token representing the supplied unit's
   108  	// application leadership. The existence of the token does not imply
   109  	// its accuracy; you need to Check() it.
   110  	//
   111  	// This method returns a token that accepts a *[]txn.Op, into which
   112  	// it will (on success) copy mgo/txn operations that can be used to
   113  	// verify the unit's continued leadership as part of another txn.
   114  	LeadershipCheck(applicationId, unitId string) Token
   115  }
   116  
   117  // Ticket is used to communicate leadership status to Tracker clients.
   118  type Ticket interface {
   119  
   120  	// Wait returns true if its Tracker is prepared to guarantee leadership
   121  	// for some period from the ticket request. The guaranteed duration depends
   122  	// upon the Tracker.
   123  	Wait() bool
   124  
   125  	// Ready returns a channel that will be closed when a result is available
   126  	// to Wait(), and is helpful for clients that want to select rather than
   127  	// block on long-waiting tickets.
   128  	Ready() <-chan struct{}
   129  }
   130  
   131  // Tracker allows clients to discover current leadership status by attempting to
   132  // claim it for themselves.
   133  type Tracker interface {
   134  
   135  	// ApplicationName returns the name of the application for which leadership claims
   136  	// are made.
   137  	ApplicationName() string
   138  
   139  	// ClaimDuration returns the duration for which a Ticket's true Wait result
   140  	// is guaranteed valid.
   141  	ClaimDuration() time.Duration
   142  
   143  	// ClaimLeader will return a Ticket which, when Wait()ed for, will return
   144  	// true if leadership is guaranteed for at least the tracker's duration from
   145  	// the time the ticket was issued. Leadership claims should be resolved
   146  	// relatively quickly.
   147  	ClaimLeader() Ticket
   148  
   149  	// WaitLeader will return a Ticket which, when Wait()ed for, will block
   150  	// until the tracker attains leadership.
   151  	WaitLeader() Ticket
   152  
   153  	// WaitMinion will return a Ticket which, when Wait()ed for, will block
   154  	// until the tracker's future leadership can no longer be guaranteed.
   155  	WaitMinion() Ticket
   156  }
   157  
   158  // TrackerWorker represents a leadership tracker worker.
   159  type TrackerWorker interface {
   160  	worker.Worker
   161  	Tracker
   162  }
   163  
   164  // Reader describes the capability to read the current state of leadership.
   165  type Reader interface {
   166  
   167  	// Leaders returns all application leaders in the current model.
   168  	// TODO (manadart 2019-02-27): The return in this signature includes error
   169  	// in order to support state.ApplicationLeaders for legacy leases.
   170  	// When legacy leases are removed, so can the error return.
   171  	Leaders() (map[string]string, error)
   172  }