README

Lfan-ke/raft-moonbit/log does not have a README file

#
LogCompacted

pub suberror LogCompacted

The one way a RaftLog read can fail: the requested index predates the snapshot baseline and has been compacted away. slice / entries / must_check_out_of_bounds narrow the storage layer's four-variant StorageError to this single mode at the boundary — a caller such as all_entries then handles exactly the failure that can occur, and no wildcard arm can silently swallow an Unavailable or contract-violating error (etcd documents that raftLog.slice only ever returns ErrCompacted).

#
LogSlice

pub(all) struct LogSlice {
term : UInt64
prev :
EntryId

entries : Array[
Entry
]
}

A contiguous, well-formed slice of a raft log considered under a specific leader term. prev is the entry immediately before entries. Mirrors etcd's logSlice, whose invariants a well-formed append must satisfy: entries are contiguous after prev, entry terms never regress, and no entry carries a term newer than the leader term.

#
LogSlice::last_entry_id

The identity of the last entry, or prev when the slice is empty.

#
LogSlice::last_index

fn LogSlice::last_index(self : LogSlice) -> UInt64

The index of the last entry, or prev.index when the slice is empty.

#
LogSlice::valid

fn LogSlice::valid(self : LogSlice) -> Bool

Whether the slice is well-formed: every entry follows the previous one by exactly one index, entry terms never regress below the preceding entry, and the last entry's term does not exceed the leader term. This is the "gateway" check etcd runs on a slice sourced from a message or from storage.

#
RaftLog

pub struct RaftLog {
storage : &
RaftStorage

unstable : Unstable
committed : UInt64
applying : UInt64
applied : UInt64
max_applying_ents_size : UInt64
applying_ents_size : UInt64
applying_ents_paused : Bool
}

The raft log (etcd's raftLog): a MemoryStorage of durable entries with an Unstable in-memory tail layered on top, plus the commit/apply cursors.

committed is the highest index known committed on a quorum; applying and applied track how far the state machine has been told to apply and has finished applying. applying_ents_size / max_applying_ents_size bound the bytes of committed-but-unapplied entries handed out at once, so a burst of commits cannot force an unbounded apply batch (byte-level pagination).

#
RaftLog::accept_applying

fn RaftLog::accept_applying(self : RaftLog, i : UInt64, size : UInt64, allow_unstable : Bool) -> Unit

Record that the application has been handed entries up to i to apply, charging size bytes against the budget and pausing when it is exhausted or when the next entry would overshoot it.

#
RaftLog::accept_unstable

fn RaftLog::accept_unstable(self : RaftLog) -> Unit

Mark the current unstable entries and snapshot as being written.

#
RaftLog::all_entries

Every entry currently in the log.

#
RaftLog::append

fn RaftLog::append(self : RaftLog, ents : Array[
Entry
]) -> UInt64

Append ents to the unstable tail and return the new last index. Appending at or before the commit index is a corruption and aborts.

#
RaftLog::applied_to

fn RaftLog::applied_to(self : RaftLog, i : UInt64, size : UInt64) -> Unit

Record that the state machine has finished applying up to i, releasing size bytes of the outstanding apply budget.

#
RaftLog::async_stabilize

fn RaftLog::async_stabilize(self : RaftLog, index : UInt64, log_term : UInt64) -> Unit

Acknowledge an asynchronous append made durable up to (index, log_term): move the confirmed unstable prefix into storage and truncate the unstable tail. This is a no-op — the ABA guard — unless the unstable log still holds (index, log_term); if a later term rewrote that index, the stale ack must not be mistaken for a confirmation of the new entries.

#
RaftLog::commit_stable

fn RaftLog::commit_stable(self : RaftLog, entries : Array[
Entry
]) -> Unit

Move entries from the unstable tail into stable storage, then mark them stable — the persist half of a driver's Ready/Advance cycle.

#
RaftLog::commit_to

fn RaftLog::commit_to(self : RaftLog, tocommit : UInt64) -> Unit

Advance the commit index (never backwards). Committing past the last index is a corruption and aborts.

#
RaftLog::committed

fn RaftLog::committed(self : RaftLog) -> UInt64

The committed index.

#
RaftLog::entries

fn RaftLog::entries(self : RaftLog, i : UInt64, max_size : UInt64) -> Array[
Entry
] raise LogCompacted

Entries starting at i, size-capped by max_size. Empty if i is past the end; raises Compacted if i has been compacted.

#
RaftLog::find_conflict

fn RaftLog::find_conflict(self : RaftLog, ents : ArrayView[
Entry
]) -> UInt64

The index of the first entry in ents that conflicts with our log (same index, different term), or the first genuinely new index, or 0 if all match.

#
RaftLog::find_conflict_by_term

fn RaftLog::find_conflict_by_term(self : RaftLog, index : UInt64, term : UInt64) -> (UInt64, UInt64)

A best guess at where our log stops matching another whose only known point is (index, term): the greatest i <= index with term(i) <= term, or with an unknown (compacted/unstored) term. Returns (i, term(i)-or-0).

#
RaftLog::first_index

fn RaftLog::first_index(self : RaftLog) -> UInt64

The first index still readable (one past the snapshot).

#
RaftLog::has_next_committed_ents

fn RaftLog::has_next_committed_ents(self : RaftLog, allow_unstable : Bool) -> Bool

Whether any committed-but-unapplied entries are ready (a light check that avoids the slice in next_committed_ents).

#
RaftLog::has_next_or_in_progress_unstable_ents

fn RaftLog::has_next_or_in_progress_unstable_ents(self : RaftLog) -> Bool

Whether there are any unstable entries, whether or not already in progress.

#
RaftLog::has_next_unstable_ents

fn RaftLog::has_next_unstable_ents(self : RaftLog) -> Bool

Whether any unstable entries are ready to be written.

#
RaftLog::has_next_unstable_snapshot

fn RaftLog::has_next_unstable_snapshot(self : RaftLog) -> Bool

Whether an unstable snapshot is ready to be applied.

#
RaftLog::is_up_to_date

fn RaftLog::is_up_to_date(self : RaftLog, their :
EntryId
) -> Bool

Whether the log ending at their is at least as up-to-date as ours (§5.4.1).

#
RaftLog::last_entry_id

The identity of the last entry.

#
RaftLog::last_index

fn RaftLog::last_index(self : RaftLog) -> UInt64

The index of the last entry in the log.

#
RaftLog::match_term

fn RaftLog::match_term(self : RaftLog, id :
EntryId
) -> Bool

Whether the log holds the identified entry with that exact term.

#
RaftLog::maybe_append

fn RaftLog::maybe_append(self : RaftLog, a : LogSlice, committed : UInt64) -> UInt64?

Try to append the slice a after verifying its prev matches our log. On a match, splice in any genuinely new tail (a conflict with a committed entry aborts), advance commit to min(committed, last_new), and return the new last index; otherwise return None.

#
RaftLog::maybe_commit

fn RaftLog::maybe_commit(self : RaftLog, at :
EntryId
) -> Bool

The committed entries whose term matches — advance commit to at.index.

#
RaftLog::must_check_out_of_bounds

fn RaftLog::must_check_out_of_bounds(self : RaftLog, lo : UInt64, hi : UInt64) -> Unit raise LogCompacted

Guard: first_index <= lo <= hi <= last_index + 1. Compacted when lo predates the first index; a high bound past the end aborts (etcd panics).

#
RaftLog::new

Recover a log from storage, positioned at the last compaction: committed, applying and applied all start at first_index - 1, and the unstable tail is empty just past last_index.

#
RaftLog::new_with_size

fn RaftLog::new_with_size(storage : &
RaftStorage
, max_applying_ents_size : UInt64) -> RaftLog

As new, but capping the byte size of entries returned per apply batch.

#
RaftLog::next_committed_ents

fn RaftLog::next_committed_ents(self : RaftLog, allow_unstable : Bool) -> Array[
Entry
]

The committed-but-unapplied entries ready for execution, subject to the apply pause, any pending snapshot, and the byte budget. allow_unstable lets committed entries still in the unstable tail be applied.

#
RaftLog::next_unstable_ents

The unstable entries ready to be written and not already in progress.

#
RaftLog::next_unstable_snapshot

fn RaftLog::next_unstable_snapshot(self : RaftLog) ->
Snapshot
?

The unstable snapshot ready to be applied and not already in progress.

#
RaftLog::pending_snapshot_index

fn RaftLog::pending_snapshot_index(self : RaftLog) -> UInt64?

The index of the snapshot still held in the unstable tail, if any (whether or not its write is in progress). Used to acknowledge a snapshot made durable under async storage writes, where the append response does not name it.

#
RaftLog::restore

Restore the log to a snapshot baseline: commit follows the snapshot forward, and the unstable tail is replaced by it.

#
RaftLog::scan

fn RaftLog::scan(self : RaftLog, lo : UInt64, hi : UInt64, page_size : UInt64, v : (ArrayView[
Entry
]) -> Unit raise) -> Unit raise

Visit [lo, hi) in consecutive byte-bounded pages, passing each page to v. v may raise to stop early. Each page holds at least one entry and at most page_size bytes (unless a single entry exceeds it).

#
RaftLog::seed

fn RaftLog::seed(self : RaftLog, committed : UInt64, applied : UInt64) -> Unit

Seed the commit and applied cursors from a recovered node on construction. Commit only moves forward; applied and applying jump to the recovered point.

#
RaftLog::slice

fn RaftLog::slice(self : RaftLog, lo : UInt64, hi : UInt64, max_size : UInt64) -> Array[
Entry
] raise LogCompacted

Entries with indices in [lo, hi), size-capped by max_size, drawn from the stable storage and the unstable tail and stitched together. Compacted if lo predates the first index.

#
RaftLog::snapshot

The most recent snapshot: the unstable one if present, else storage's.

#
RaftLog::stable_snap_to

fn RaftLog::stable_snap_to(self : RaftLog, i : UInt64) -> Unit

Confirm the unstable snapshot at index i is durably stored.

#
RaftLog::stable_to

fn RaftLog::stable_to(self : RaftLog, id :
EntryId
) -> Unit

Confirm the unstable tail entries up to id are durably stored.

#
RaftLog::term

fn RaftLog::term(self : RaftLog, i : UInt64) -> UInt64 raise
StorageError

The term of entry i. Compacted if it predates the first index, Unavailable if it is past the last. The term at first_index-1 is retained for log-matching even though the entry itself is gone.

#
RaftLog::to_string

fn RaftLog::to_string(self : RaftLog) -> String

A one-line description of the log's cursors for debugging (etcd's raftLog.String()).

#
RaftLog::zero_term_on_out_of_bounds

fn RaftLog::zero_term_on_out_of_bounds(self : RaftLog, i : UInt64) -> UInt64

The term at i, or 0 when the index is out of bounds (etcd's zeroTermOnOutOfBounds), used where a missing term is simply "no match".

#
Unstable

pub(all) struct Unstable {
snapshot :
Snapshot
?
entries : Array[
Entry
]
offset : UInt64
offset_in_progress : UInt64
snapshot_in_progress : Bool
}

The in-memory tail of the log that has not yet been written to Storage (etcd's unstable). It holds newly appended entries and, optionally, a snapshot waiting to be applied, until they are handed to a Ready and their writes are confirmed. entries[i] sits at absolute log index i + offset.

offset_in_progress (exclusive, >= offset) marks how far the entries have begun being written; snapshot_in_progress says the snapshot write has begun. Following etcd, the "in progress" cursors are what let the same entries be exposed once for persistence and then withheld until stabilized. The snapshot is an Option rather than a sentinel — its absence is a real type state, not an index-0 magic value.

#
Unstable::accept_in_progress

fn Unstable::accept_in_progress(self : Unstable) -> Unit

Mark every held entry and the snapshot as having begun their write, so they are withheld from later next_entries/next_snapshot until stabilized.

#
Unstable::maybe_first_index

fn Unstable::maybe_first_index(self : Unstable) -> UInt64?

The first index the unstable region can speak to — one past the snapshot — or None when there is no snapshot.

#
Unstable::maybe_last_index

fn Unstable::maybe_last_index(self : Unstable) -> UInt64?

The last index covered, if there is at least one entry or a snapshot.

#
Unstable::maybe_term

fn Unstable::maybe_term(self : Unstable, i : UInt64) -> UInt64?

The term of the entry at i, if the unstable region knows it — either from an entry it holds or from the snapshot baseline.

#
Unstable::new

fn Unstable::new(offset : UInt64) -> Unstable

A fresh unstable tail anchored just past the last stable entry.

#
Unstable::next_entries

The entries not already in the process of being written to storage.

#
Unstable::next_snapshot

The snapshot to write, if one is present and not already being written.

#
Unstable::restore

Replace the unstable tail with a snapshot baseline: the log restarts just past s, with no in-memory entries.

#
Unstable::slice

fn Unstable::slice(self : Unstable, lo : UInt64, hi : UInt64) -> Array[
Entry
]

The held entries with indices in [lo, hi). The whole range must lie within the unstable region, otherwise this aborts (etcd panics).

#
Unstable::stable_snap_to

fn Unstable::stable_snap_to(self : Unstable, i : UInt64) -> Unit

Drop the snapshot once it has been written to storage.

#
Unstable::stable_to

Discard the entries up to and including id now that they are durably stored. Ignored if the entry is missing, matched only the snapshot baseline, or the term no longer matches (the unstable tail was replaced meanwhile).

#
Unstable::truncate_and_append

fn Unstable::truncate_and_append(self : Unstable, ents : Array[
Entry
]) -> Unit

Splice ents onto the tail: append directly when they follow the last held entry, replace the whole tail when they start at or before offset, or truncate the divergent suffix and append otherwise. Only in-progress entries before the truncation point stay in progress.

#
describe_conf_state

fn describe_conf_state(cs :
ConfState
) -> String

A concise description of a ConfState (etcd's DescribeConfState).

#
describe_entries

fn describe_entries(entries : ArrayView[
Entry
], format : (Bytes) -> String?) -> String

Each entry described, one per line (etcd's DescribeEntries).

#
describe_entry

fn describe_entry(e :
Entry
, format : (Bytes) -> String?) -> String

A concise, human-readable description of an entry for debugging: term/index Type payload. format renders the payload; when it is None the default Go %q-style quoting is used. Mirrors etcd's DescribeEntry.

#
describe_hard_state

fn describe_hard_state(hs :
HardState
) -> String

A concise description of a HardState for debugging (etcd's DescribeHardState): Term:N [Vote:v ]Commit:N, the vote shown only when a vote was cast.

#
describe_snapshot

fn describe_snapshot(snap :
Snapshot
) -> String

A concise description of a Snapshot (etcd's DescribeSnapshot).