Documentation ¶
Index ¶
- Constants
- Variables
- func Bootstrap(config Config) error
- func IsNotLeaderError(err error) bool
- func Manifold(config ManifoldConfig) dependency.Manifold
- func NewLogStore(dir string, syncMode SyncMode) (*raftboltdb.BoltStore, error)
- func NewNotLeaderError(serverAddress, serverID string) error
- func NewRaftConfig(config Config) (*raft.Config, error)
- func NewSnapshotStore(dir string, retain int, logger Logger) (raft.SnapshotStore, error)
- func NewTarget(st *state.State, logger raftleasestore.Logger) raftlease.NotifyTarget
- func NewWorker(config Config) (worker.Worker, error)
- func NewWorkerShim(config Config) (worker.Worker, error)
- type Applier
- type ApplierMetrics
- type BootstrapFSM
- type BootstrapLeaseApplier
- type BootstrapNotifyTarget
- type Config
- type LeaseApplier
- type Logger
- type ManifoldConfig
- type NotLeaderError
- type Queue
- type Raft
- type SimpleFSM
- type SimpleSnapshot
- type SyncMode
- type Worker
Constants ¶
const ( // InitialApplyTimeout is the initial timeout for applying a time. When // starting up a raft backend, on some machines it might take more than the // running apply timeout. For that reason, we allow a grace period when // initializing. InitialApplyTimeout time.Duration = time.Second * 5 // ApplyTimeout is the timeout for applying a command in an operation. It // is expected that raft can commit a log with in this timeout. ApplyTimeout time.Duration = time.Second * 2 )
const ( // LoopTimeout is the max time we will wait until the raft object // is constructed and the main loop is started. This is to avoid // hard-to-debug problems where the transport hung and so this // worker wasn't really started even though it seemed like it // was. If it crashes instead the logging will give a path to the // problem. LoopTimeout = 1 * time.Minute )
Variables ¶
var ( // ErrWorkerStopped is returned by Worker.Raft if the // worker has been explicitly stopped. ErrWorkerStopped = errors.New("raft worker stopped") // ErrStartTimeout is returned by NewWorker if the worker loop // didn't start within LoopTimeout. ErrStartTimeout = errors.New("timed out waiting for worker loop") // ErrNoLeaderTimeout is returned by the worker loop if we've gone // too long without contact from the leader. It gives the worker a // chance to see any configuration changes the backstop worker // might have force-appended to the raft log. ErrNoLeaderTimeout = errors.New("timed out waiting for leader contact") )
Functions ¶
func Bootstrap ¶
Bootstrap bootstraps the raft cluster, using the given configuration.
This is only to be called once, at the beginning of the raft cluster's lifetime, by the bootstrap machine agent.
func IsNotLeaderError ¶
IsNotLeaderError returns true if the error is the NotLeaderError.
func Manifold ¶
func Manifold(config ManifoldConfig) dependency.Manifold
Manifold returns a dependency.Manifold that will run a raft worker.
func NewLogStore ¶
func NewLogStore(dir string, syncMode SyncMode) (*raftboltdb.BoltStore, error)
NewLogStore opens a boltDB logstore in the specified directory. If the directory doesn't already exist it'll be created. If the caller passes NonSyncedAfterWrite as the value of the syncMode argument, the underlying store will NOT perform fsync calls between log writes.
func NewNotLeaderError ¶
NewNotLeaderError creates a new NotLeaderError with the server address and/or server ID of the current raft state leader.
func NewRaftConfig ¶
NewRaftConfig makes a raft config struct from the worker config struct passed in.
func NewSnapshotStore ¶
NewSnapshotStore opens a file-based snapshot store in the specified directory. If the directory doesn't exist it'll be created.
func NewTarget ¶
func NewTarget(st *state.State, logger raftleasestore.Logger) raftlease.NotifyTarget
NewTarget creates a new lease notify target using the dependencies in a late fashion.
func NewWorkerShim ¶
NewWorkerShim is suitable for use in ManifoldConfig.NewWorker, and simply calls through to NewWorker.
Types ¶
type Applier ¶
type Applier struct {
// contains filtered or unexported fields
}
Applier applies a new operation against a raft instance.
func (*Applier) ApplyOperation ¶
ApplyOperation applies an lease opeartion against the raft instance. If the raft instance isn't the leader, then an error is returned with the leader information if available. This Raft spec outlines this "The first option, which we recommend ..., is for the server to reject the request and return to the client the address of the leader, if known." (see 6.2.1). If the leader is the current raft instance, then attempt to apply it to the fsm.
type ApplierMetrics ¶
type ApplierMetrics interface { // Record times how long a apply operation took, along with if it failed or // not. This can be used to understand if we're hitting issues with the // underlying raft instance. Record(start time.Time, result string) // RecordLeaderError calls out that there was a leader error, so didn't // follow the usual flow. RecordLeaderError(start time.Time) }
ApplierMetrics defines an interface for recording the application of a log.
type BootstrapFSM ¶
type BootstrapFSM struct{}
BootstrapFSM is a minimal implementation of raft.FSM for use during bootstrap. Its methods should never be invoked.
func (BootstrapFSM) Apply ¶
func (BootstrapFSM) Apply(_ *raft.Log) interface{}
Apply is part of raft.FSM.
func (BootstrapFSM) Restore ¶
func (BootstrapFSM) Restore(io.ReadCloser) error
Restore is part of raft.FSM.
func (BootstrapFSM) Snapshot ¶
func (BootstrapFSM) Snapshot() (raft.FSMSnapshot, error)
Snapshot is part of raft.FSM.
type BootstrapLeaseApplier ¶
type BootstrapLeaseApplier struct{}
func (BootstrapLeaseApplier) ApplyOperation ¶
func (BootstrapLeaseApplier) ApplyOperation([]queue.Operation, time.Duration)
type BootstrapNotifyTarget ¶
type BootstrapNotifyTarget struct{}
type Config ¶
type Config struct { // FSM is the raft.FSM to use for this raft worker. This // must be non-nil for NewWorker, and nil for Bootstrap. FSM raft.FSM // Logger is the logger for this worker. Logger Logger // StorageDir is the directory in which to store raft // artifacts: logs, snapshots, etc. It is expected that // this directory is under the full control of the raft // worker. StorageDir string // NonSyncedWritesToRaftLog allows the operator to disable fsync calls // after each write to the raft log. This option trades performance for // data safety and should be used with caution. NonSyncedWritesToRaftLog bool // LocalID is the raft.ServerID of this worker. LocalID raft.ServerID // Transport is the raft.Transport to use for communication // between raft servers. This must be non-nil for NewWorker, // and nil for Bootstrap. // // The raft worker expects the server address to exactly // match the server ID, which is the stringified agent tag. // The transport internally maps the server address to one // or more network addresses, i.e. by looking up the API // connection information in the state database. Transport raft.Transport // Clock is used for timeouts in the worker (although not inside // raft). Clock clock.Clock // NoLeaderTimeout, if non-zero, will override the default // timeout for leader contact before restarting. NoLeaderTimeout time.Duration // ElectionTimeout, if non-zero, will override the default // raft election timeout. ElectionTimeout time.Duration // HeartbeatTimeout, if non-zero, will override the default // raft heartbeat timeout. HeartbeatTimeout time.Duration // LeaderLeaseTimeout, if non-zero, will override the default // raft leader lease timeout. LeaderLeaseTimeout time.Duration // SnapshotRetention is the non-negative number of snapshots // to retain on disk. If zero, defaults to 2. SnapshotRetention int // PrometheusRegisterer is used to register the raft metrics. PrometheusRegisterer prometheus.Registerer // Queue is a blocking queue to apply raft operations. Queue Queue // NotifyTarget is used to notify the changes from the raft operation // applications. NotifyTarget raftlease.NotifyTarget // NewApplier is used to apply the raft operations on to the raft // instance, before notifying a target of the changes. NewApplier func(Raft, raftlease.NotifyTarget, ApplierMetrics, clock.Clock, Logger) LeaseApplier }
Config is the configuration required for running a raft worker.
type LeaseApplier ¶
type LeaseApplier interface { // ApplyOperation applies a lease opeartion against the raft instance. If // the raft instance isn't the leader, then an error is returned with the // leader information if available. // This Raft spec outlines this "The first option, which we recommend ..., // is for the server to reject the request and return to the client the // address of the leader, if known." (see 6.2.1). // If the leader is the current raft instance, then attempt to apply it to // the fsm. // The time duration is the applying of a command in an operation, not for // the whole operation. ApplyOperation([]queue.Operation, time.Duration) }
LeaseApplier applies operations from the queue onto the underlying raft instance.
func NewApplier ¶
func NewApplier(raft Raft, target raftlease.NotifyTarget, metrics ApplierMetrics, clock clock.Clock, logger Logger) LeaseApplier
NewApplier creates a new Applier.
type Logger ¶
type Logger interface { Criticalf(message string, args ...interface{}) Warningf(message string, args ...interface{}) Errorf(message string, args ...interface{}) Infof(message string, args ...interface{}) Debugf(message string, args ...interface{}) Tracef(message string, args ...interface{}) Logf(level loggo.Level, message string, args ...interface{}) IsTraceEnabled() bool }
Logger represents the logging methods called.
type ManifoldConfig ¶
type ManifoldConfig struct { ClockName string AgentName string TransportName string StateName string FSM raft.FSM Logger Logger PrometheusRegisterer prometheus.Registerer NewWorker func(Config) (worker.Worker, error) NewTarget func(*state.State, raftleasestore.Logger) raftlease.NotifyTarget NewApplier func(Raft, raftlease.NotifyTarget, ApplierMetrics, clock.Clock, Logger) LeaseApplier Queue Queue }
ManifoldConfig holds the information necessary to run a raft worker in a dependency.Engine.
func (ManifoldConfig) Validate ¶
func (config ManifoldConfig) Validate() error
Validate validates the manifold configuration.
type NotLeaderError ¶
type NotLeaderError struct {
// contains filtered or unexported fields
}
NotLeaderError creates a typed error for when a raft operation is applied, but the raft state shows that it's not the leader. The error will help redirect the consumer of the error to workout where they can try and find the leader.
func (*NotLeaderError) AsMap ¶
func (e *NotLeaderError) AsMap() map[string]interface{}
AsMap returns a map of the error. Useful when crossing the facade boundary and wanting information in the client.
func (*NotLeaderError) Error ¶
func (e *NotLeaderError) Error() string
func (*NotLeaderError) ServerAddress ¶
func (e *NotLeaderError) ServerAddress() string
ServerAddress returns the address of the potential current leader. It's not guaranteed to be the leader, as things may of changed when attempting the same request on the new leader.
func (*NotLeaderError) ServerID ¶
func (e *NotLeaderError) ServerID() string
ServerID returns the server ID from the raft state. This should align with the controller machine ID of Juju.
type Queue ¶
type Queue interface { // Queue returns the queue of operations. Removing an item from the channel // will unblock to allow another to take its place. Queue() <-chan []queue.Operation }
Queue is a blocking queue to guard access and to serialize raft applications, allowing for client side backoff.
type Raft ¶
type Raft interface { // State is used to return the current raft state. State() raft.RaftState // Leader is used to return the current leader of the cluster. // It may return empty string if there is no current leader // or the leader is unknown. Leader() raft.ServerAddress // GetConfiguration returns the latest configuration. This may not yet be // committed. The main loop can access this directly. GetConfiguration() raft.ConfigurationFuture // Apply is used to apply a command to the FSM in a highly consistent // manner. This returns a future that can be used to wait on the application. // An optional timeout can be provided to limit the amount of time we wait // for the command to be started. This must be run on the leader or it // will fail. Apply([]byte, time.Duration) raft.ApplyFuture }
Raft defines a local use Raft instance.
type SimpleFSM ¶
type SimpleFSM struct {
// contains filtered or unexported fields
}
SimpleFSM is an implementation of raft.FSM, which simply appends the log data to a slice.
type SimpleSnapshot ¶
type SimpleSnapshot struct {
// contains filtered or unexported fields
}
SimpleSnapshot is an implementation of raft.FSMSnapshot, returned by the SimpleFSM.Snapshot in this package.
func (*SimpleSnapshot) Persist ¶
func (snap *SimpleSnapshot) Persist(sink raft.SnapshotSink) error
Persist is part of the raft.FSMSnapshot interface.
func (*SimpleSnapshot) Release ¶
func (*SimpleSnapshot) Release()
Release is part of the raft.FSMSnapshot interface.
type SyncMode ¶
type SyncMode bool
SyncMode defines the supported sync modes when writing to the raft log store.
type Worker ¶
type Worker struct {
// contains filtered or unexported fields
}
Worker is a worker that manages a raft.Raft instance.
func (*Worker) LogStore ¶
LogStore returns the raft.LogStore managed by this worker, or an error if the worker has stopped.
func (*Worker) Raft ¶
Raft returns the raft.Raft managed by this worker, or an error if the worker has stopped.