Trait openraft::storage::RaftStateMachine

source ·
pub trait RaftStateMachine<C>: Sealed + OptionalSend + OptionalSync + 'static + Send
where C: RaftTypeConfig,
{ type SnapshotBuilder: RaftSnapshotBuilder<C>; // Required methods fn applied_state( &mut self ) -> impl Future<Output = Result<(Option<LogId<C::NodeId>>, StoredMembership<C::NodeId, C::Node>), StorageError<C::NodeId>>> + Send; fn apply<I>( &mut self, entries: I ) -> impl Future<Output = Result<Vec<C::R>, StorageError<C::NodeId>>> + Send where I: IntoIterator<Item = C::Entry> + OptionalSend, I::IntoIter: OptionalSend; fn get_snapshot_builder( &mut self ) -> impl Future<Output = Self::SnapshotBuilder> + Send; fn begin_receiving_snapshot( &mut self ) -> impl Future<Output = Result<Box<C::SnapshotData>, StorageError<C::NodeId>>> + Send; fn install_snapshot( &mut self, meta: &SnapshotMeta<C::NodeId, C::Node>, snapshot: Box<C::SnapshotData> ) -> impl Future<Output = Result<(), StorageError<C::NodeId>>> + Send; fn get_current_snapshot( &mut self ) -> impl Future<Output = Result<Option<Snapshot<C>>, StorageError<C::NodeId>>> + Send; }
Expand description

API for state machine and snapshot.

Snapshot is part of the state machine, because usually a snapshot is the persisted state of the state machine.

Required Associated Types§

source

type SnapshotBuilder: RaftSnapshotBuilder<C>

Snapshot builder type.

Required Methods§

source

fn applied_state( &mut self ) -> impl Future<Output = Result<(Option<LogId<C::NodeId>>, StoredMembership<C::NodeId, C::Node>), StorageError<C::NodeId>>> + Send

Returns the last applied log id which is recorded in state machine, and the last applied membership config.

§Correctness requirements

It is all right to return a membership with greater log id than the last-applied-log-id.

source

fn apply<I>( &mut self, entries: I ) -> impl Future<Output = Result<Vec<C::R>, StorageError<C::NodeId>>> + Send

Apply the given payload of entries to the state machine.

The Raft protocol guarantees that only logs which have been committed, that is, logs which have been replicated to a quorum of the cluster, will be applied to the state machine.

This is where the business logic of interacting with your application’s state machine should live. This is 100% application specific. Perhaps this is where an application specific transaction is being started, or perhaps committed. This may be where a key/value is being stored.

For every entry to apply, an implementation should:

  • Store the log id as last applied log id.
  • Deal with the business logic log.
  • Store membership config if RaftEntry::get_membership() returns Some.

Note that for a membership log, the implementation need to do nothing about it, except storing it.

An implementation may choose to persist either the state machine or the snapshot:

  • An implementation with persistent state machine: persists the state on disk before returning from apply_to_state_machine(). So that a snapshot does not need to be persistent.

  • An implementation with persistent snapshot: apply_to_state_machine() does not have to persist state on disk. But every snapshot has to be persistent. And when starting up the application, the state machine should be rebuilt from the last snapshot.

source

fn get_snapshot_builder( &mut self ) -> impl Future<Output = Self::SnapshotBuilder> + Send

Get the snapshot builder for the state machine.

Usually it returns a snapshot view of the state machine(i.e., subsequent changes to the state machine won’t affect the return snapshot view), or just a copy of the entire state machine.

The method is intentionally async to give the implementation a chance to use asynchronous sync primitives to serialize access to the common internal object, if needed.

source

fn begin_receiving_snapshot( &mut self ) -> impl Future<Output = Result<Box<C::SnapshotData>, StorageError<C::NodeId>>> + Send

Create a new blank snapshot, returning a writable handle to the snapshot object.

Openraft will use this handle to receive snapshot data.

See the storage chapter of the guide for details on log compaction / snapshotting.

source

fn install_snapshot( &mut self, meta: &SnapshotMeta<C::NodeId, C::Node>, snapshot: Box<C::SnapshotData> ) -> impl Future<Output = Result<(), StorageError<C::NodeId>>> + Send

Install a snapshot which has finished streaming from the leader.

Before this method returns:

  • The state machine should be replaced with the new contents of the snapshot,
  • the input snapshot should be saved, i.e., Self::get_current_snapshot should return it.
  • and all other snapshots should be deleted at this point.
§snapshot

A snapshot created from an earlier call to begin_receiving_snapshot which provided the snapshot.

source

fn get_current_snapshot( &mut self ) -> impl Future<Output = Result<Option<Snapshot<C>>, StorageError<C::NodeId>>> + Send

Get a readable handle to the current snapshot.

§implementation algorithm

Implementing this method should be straightforward. Check the configured snapshot directory for any snapshot files. A proper implementation will only ever have one active snapshot, though another may exist while it is being created. As such, it is recommended to use a file naming pattern which will allow for easily distinguishing between the current live snapshot, and any new snapshot which is being created.

A proper snapshot implementation will store last-applied-log-id and the last-applied-membership config as part of the snapshot, which should be decoded for creating this method’s response data.

Object Safety§

This trait is not object safe.

Implementors§