Connects this RaftController
to the Raft cluster. Users of this
RaftController
need to wait til the returned promise is resolved before
they can propose inputs with propose(...)
, observe the replicated state
with getState()
and observeState()
, and monitor the cluster
configuration with getClusterConfiguration()
and
observeClusterConfiguration()
.
If this function is called after a crash and this RaftController
was
connected to the Raft cluster before the crash, persisted data will be
used to restore this controller and reconnect to the Raft cluster.
A promise that resolves once this RaftController
has connected
to the Raft cluster.
The RaftController
with
shouldCreateCluster
set to true
will
create a new Raft cluster on initial startup. Trying to connect a
RaftController
with this option set to false
will only resolve after
a Raft cluster has been created and a majority of the existing cluster
has agreed on letting this RaftController
join.
An InvalidControllerOptionsError
if the
RaftControllerOptions
provided when bootstrapping this
controller are invalid or missing.
An OperationNotSupportedInCurrentConnectionStateError
if this controller is currently in the process of disconnecting or
stopping.
Disconnects this RaftController
from the Raft cluster therefore
removing it from the cluster configuration. Users of this
RaftController
need to wait til the returned promise is resolved before
they can shutdown the corresponding Coaty container. Deletes all
persisted state of this controller. The shared state of a Raft cluster is
lost after all RaftControllers
of that cluster have disconnected.
A promise that resolves once this RaftController
has
disconnected.
An OperationNotSupportedInCurrentConnectionStateError
if this controller is currently in the process of connecting or stopping.
Returns a promise resolving to the cluster configuration. The cluster
configuration contains the ids of all RaftController
s in the cluster.
A promise resolving to the cluster configuration. The cluster
configuration contains the ids of all RaftController
s in the cluster.
The returned configuration is guaranteed to be up to date or
newer respective to the point in time when this function was called. In
other words calling getClusterConfiguration()
at time t will return the
cluster configuration from some point in time inside [t, ∞]. This means
that all connects and disconnects that finished before t are guaranteed
to already be applied in this configuration. Newer connects and
disconnects that finished after t might also already be applied.
A DisconnectBeforeOperationCompleteError
if this
controller disconnected before the cluster configuration could be
retrieved.
An OperationNotSupportedInCurrentConnectionStateError
if this controller is not connected to the Raft cluster, this.connect()
needs to be called first.
Returns a promise resolving to the state of the RSM. The state is
retrieved by proposing a NOOP and waiting for its resulting state. The
NOOP is being proposed internally and therefore cannot be observed by
observeState()
.
A promise resolving to the state of the RSM. The state will be
of type RaftData
.
The returned state is guaranteed to be up to date or newer
respective to the point in time when this function was called. In other
words calling getState()
at time t will return the distributed state
from some point in time inside [t, ∞]. This means that all inputs
committed before t are guaranteed to already be applied in this state.
Newer inputs that were committed after t might also already be applied.
A DisconnectBeforeOperationCompleteError
if this
controller is disconnected from the cluster before the state could be
retrieved.
An OperationNotSupportedInCurrentConnectionStateError
if this controller is not connected to the Raft cluster, this.connect()
needs to be called first.
Returns an observable that emits the cluster configuration on every
configuration change as soon as the change becomes known to this
controller. Cluster configuration changes are triggered when a
RaftController
connects to or disconnects from the Raft cluster.
The returned observable completes and its subscriptions are automatically unsubscribed once the controller is disconnected or stopped, in order to release system resources and to avoid memory leaks.
an observable emitting the cluster configuration on every
configuration change. The cluster configuration contains the ids of all
RaftController
s in the cluster.
An OperationNotSupportedInCurrentConnectionStateError
if this controller is not connected to the Raft cluster, this.connect()
needs to be called first.
Returns an observable that emits the state of the RSM on every state update as soon as the update becomes known to this controller. State updates are triggered when a new input is committed.
The returned observable completes and its subscriptions are automatically unsubscribed once the controller is disconnected or stopped, in order to release system resources and to avoid memory leaks.
an observable emitting the state of the RSM on every state
update. The emitted state will be of type RaftData
.
An OperationNotSupportedInCurrentConnectionStateError
if this controller is not connected to the Raft cluster, this.connect()
needs to be called first.
Proposes the given input
to Raft. Raft will try to add the input to a
log shared between all RaftController
s in the Raft cluster. If the
input is accepted into the log it counts as committed and is applied to
the RSM. The returned promise resolves to the resulting state of the RSM
after the proposed input has been applied.
A majority of controllers need to give their consent before the given input is accepted into the log. This might take indefinitely if no majority can be reached, e.g. if too many agents have crashed and cannot recover. In this case the returned promise is never resolved or rejected.
Input that should be committed and applied to the RSM. Has
to be of type RaftData
.
A promise resolving to the resulting state of the RSM after the
proposed input has been applied if it ever gets applied. Is of type
RaftData
. Is rejected if this RaftController
is stopped or
disconnected before it could make sure that the input was committed. The
input might still be committed.
This function implements reproposed inputs as explained inside the Raft thesis. Manual reproposing by the user is not intended. That is why the returned promise never times out.
The object structure of input and resulting state can be chosen
by the user and depends on the implementation of the RSM that is provided
in the RaftControllerOptions
of this controller. Both input
and resulting state have to be of type RaftData
.
A TooManyQueuedUpInputProposalsError
if there are
more than 1000 input proposals queued up that haven't been committed yet.
A DisconnectBeforeOperationCompleteError
if this
controller is disconnected from the cluster before it could make sure
that the proposed input was committed.
An OperationNotSupportedInCurrentConnectionStateError
if this controller is not connected to the Raft cluster, this.connect()
needs to be called first.
Stops this RaftController
WITHOUT disconnecting from the Raft cluster
and WITHOUT deleting the persisted state. Users of this RaftController
need to wait til the returned promise is resolved before they can
shutdown the corresponding Coaty container.
Users can use this function instead of disconnect()
if they want to
shutdown this controller for some time without losing the current shared
state and cluster configuration. This might be useful if e.g. the entire
cluster has to shutdown for a few days but its state and configuration
should be preserved. stop()
can also be seen as a graceful crash.
A promise that resolves once this RaftController
has been
stopped.
If at least half of all RaftControllers
in the Raft cluster are
stopped the cluster can no longer make any progress til enough stopped
controllers reconnect using connect()
.
An OperationNotSupportedInCurrentConnectionStateError
if this controller is currently in the process of connecting or
disconnecting.
Protected
getCan be overwritten to change the RaftCommunication
implementation used by Raft.
Protected
getCan be overwritten to change the RaftPersistency
implementation used by Raft.
The default implementation persists Raft data using Coaty's SQL-based
local storage in the form of a local SQLite database file. This database
must be referenced in Coaty Configuration.databaseOptions
under the key
specified by RaftControllerOptions.databaseKey (or "raftdb" if not
specified) using the adapter named "SqLiteNodeAdapter". Make sure the
path to the database file (i.e. connectionString) exists and is
accessible.
Internal
For internal use in framework only.
Never instantiate Controller objects in your application; they are created automatically by dependency injection.
Gets the container's communication manager.
Gets the container object of this controller.
Gets the controller's options as specified in the configuration options.
Gets the registered name of this controller.
The registered name is either defined by the corresponding key in the
Components.controllers
object in the container configuration, or by
invoking Container.registerController
method with this name.
Gets the container's Runtime object.
Protected
extendWhenever one of the controller's log methods (e.g. logDebug
, logInfo
,
logWarning
, logError
, logFatal
) is called by application code, the
controller creates a Log object with appropriate property values and
passes it to this method before advertising it.
You can override this method to additionally set certain properties (such
as LogHost.hostname
or Log.logLabels
). Ensure that
super.extendLogObject
is called in your override. The base method does
nothing.
log object to be extended before being advertised
Called when the container has completely set up and injected all dependency components, including all its controllers.
Override this method to perform initializations in your custom controller
class instead of defining a constructor. Although the base implementation
does nothing it is good practice to call super.onInit()
in your
override method; especially if your custom controller class does not
extend from the base Controller
class directly.
Generated using TypeDoc
Maintains a replicated state machine (RSM) with other
RaftController
instances in the Coaty network using the Raft protocol. For that eachRaftController
joins a specified Raft cluster. An instance of the RSM in form of aRaftStateMachine
has to be provided in theRaftControllerOptions
when bootstrapping this controller.A new
RaftController
instance needs toconnect()
to the Raft cluster before it can modify/access the replicated state with the following functions:propose(input)
proposes a new input that should be applied to the RSM.getState()
returns the state of the RSM.observeState()
returns an observable emitting on every RSM change.After a
RaftController
has connected to the Raft cluster it can monitor the cluster configuration with the following functions:getClusterConfiguration()
returns the cluster configuration.observeClusterConfiguration()
returns an observable emitting on every cluster configuration change.Before shutting down the Coaty container of this
RaftController
the user has to eitherdisconnect()
from the Raft cluster orstop()
this controller.