# gizfs:raft

A bounded durable Raft range. Network authentication, timeout scheduling and deterministic application of committed entries belong to the service. No local-clock lease is assumed.

```gizlang
import * as Raft from "gizfs:raft";
```

## Types

### `Limits`

```gizlang
type Limits = { entries: i64; bytes: i64; snapshotBytes: i64; }
```

The most entries and bytes that the log keeps before a snapshot, and the most bytes of a snapshot.

- `entries`: `i64`
- `bytes`: `i64`
- `snapshotBytes`: `i64`

### `Entry`

```gizlang
type Entry = { index: i64; term: i64; kind: i64; data: bytes; voters: Vec<i64>; }
```

A log entry: its index and term, its kind (data or configuration), its data, and the voters that a configuration
entry sets.

- `index`: `i64`
- `term`: `i64`
- `kind`: `i64`
- `data`: `bytes`
- `voters`: `Vec<i64>`

### `Vote`

```gizlang
type Vote = { term: i64; candidate: i64; lastIndex: i64; lastTerm: i64; }
```

A request for a vote of a candidate, with the index and term of its last entry.

- `term`: `i64`
- `candidate`: `i64`
- `lastIndex`: `i64`
- `lastTerm`: `i64`

### `VoteReply`

```gizlang
type VoteReply = { term: i64; voter: i64; granted: bool; }
```

The answer of VOTER to a vote request.

- `term`: `i64`
- `voter`: `i64`
- `granted`: `bool`

### `Append`

```gizlang
type Append = { term: i64; leader: i64; serial: i64; previous: i64; previousTerm: i64; entries: Vec<Entry>; commit: i64; round: i64; }
```

A request of the leader to append ENTRIES after the entry PREVIOUS of PREVIOUSTERM; it also carries the commit
index.

- `term`: `i64`
- `leader`: `i64`
- `serial`: `i64`
- `previous`: `i64`
- `previousTerm`: `i64`
- `entries`: `Vec<M40.Entry>`
- `commit`: `i64`
- `round`: `i64`

### `AppendReply`

```gizlang
type AppendReply = { term: i64; follower: i64; serial: i64; accepted: bool; matched: i64; next: i64; round: i64; }
```

The answer of a follower to an append: whether it accepted, the index that it holds, and the next index to send.

- `term`: `i64`
- `follower`: `i64`
- `serial`: `i64`
- `accepted`: `bool`
- `matched`: `i64`
- `next`: `i64`
- `round`: `i64`

### `Read`

```gizlang
type Read = { term: i64; index: i64; round: i64; }
```

A read barrier of the leader: its term, the commit index that the read waits for, and its round.

- `term`: `i64`
- `index`: `i64`
- `round`: `i64`

### `Snapshot`

```gizlang
type Snapshot = { index: i64; term: i64; voters: Vec<i64>; data: bytes; }
```

A snapshot: the index and term of the last entry that it holds, its voters, and the state.

- `index`: `i64`
- `term`: `i64`
- `voters`: `Vec<i64>`
- `data`: `bytes`

### `Install`

```gizlang
type Install = { term: i64; leader: i64; serial: i64; snapshot: Snapshot; }
```

A request of the leader to install SNAPSHOT.

- `term`: `i64`
- `leader`: `i64`
- `serial`: `i64`
- `snapshot`: `M40.Snapshot`

### `InstallReply`

```gizlang
type InstallReply = { term: i64; follower: i64; serial: i64; index: i64; }
```

The answer of a follower to an install, with the index that it now holds.

- `term`: `i64`
- `follower`: `i64`
- `serial`: `i64`
- `index`: `i64`

### `Node`

```gizlang
type Node = { disk: Disk; id: i64; limits: Limits; term: i64; voted: i64; commit: i64; base: Snapshot; entries: Vec<Entry>; voters: Vec<i64>; joint: Vec<i64>; role: i64; stopped: bool; votes: Vec<i64>; peers: Vec<Progress>; serial: i64; round: i64; readCut: i64; readers: Vec<i64>; persistence: Persistence; ordered: () => Result<bool, string>; }
```

A Raft node: its durable log and state on its disk, its role, and the progress of its peers when it leads.

- `disk`: `M37.Disk`
- `id`: `i64`
- `limits`: `M40.Limits`
- `term`: `i64`
- `voted`: `i64`
- `commit`: `i64`
- `base`: `M40.Snapshot`
- `entries`: `Vec<M40.Entry>`
- `voters`: `Vec<i64>`
- `joint`: `Vec<i64>`
- `role`: `i64`
- `stopped`: `bool`
- `votes`: `Vec<i64>`
- `peers`: `Vec<M40.Progress>`
- `serial`: `i64`
- `round`: `i64`
- `readCut`: `i64`
- `readers`: `Vec<i64>`
- `persistence`: `M40.Persistence`
- `ordered`: `() => _gizlang_sdk_core.Result<bool, string>`

## Functions

### `vote`

```gizlang
function vote(request: Vote): bytes
```

The encoding of REQUEST.

Effects: fail.

### `readVote`

```gizlang
function readVote(data: bytes): Result<Vote, string>
```

The vote request of DATA. It fails when the encoding is not valid.

Effects: fail, read, write, console, io.

### `voteReply`

```gizlang
function voteReply(reply: VoteReply): bytes
```

The encoding of REPLY.

Effects: fail.

### `readVoteReply`

```gizlang
function readVoteReply(data: bytes): Result<VoteReply, string>
```

The vote answer of DATA. It fails when the encoding is not valid.

Effects: fail, read, write, console, io.

### `append`

```gizlang
function append(request: Append): bytes
```

The encoding of REQUEST.

Effects: fail.

### `readAppend`

```gizlang
function readAppend(data: bytes): Result<Append, string>
```

The append request of DATA. It fails when the encoding is not valid.

Effects: fail, read, write, console, io.

### `appendReply`

```gizlang
function appendReply(reply: AppendReply): bytes
```

The encoding of REPLY.

Effects: fail.

### `readAppendReply`

```gizlang
function readAppendReply(data: bytes): Result<AppendReply, string>
```

The append answer of DATA. It fails when the encoding is not valid.

Effects: fail, read, write, console, io.

### `installReply`

```gizlang
function installReply(reply: InstallReply): bytes
```

The encoding of REPLY.

Effects: fail.

### `readInstallReply`

```gizlang
function readInstallReply(data: bytes): Result<InstallReply, string>
```

The install answer of DATA. It fails when the encoding is not valid.

Effects: fail, read, write, console, io.

### `formats`

```gizlang
function formats(): Vec<Codec.Format>
```

The on-disk formats of this module. A test opens a committed store sample of every version.

Effects: fail.

### `open`

```gizlang
function open(disk: Disk, id: i64, voters: Vec<i64>, limits: Limits): Result<Node, string>
```

Hard state references a log generation and an immutable semantic snapshot; the log is read to its last whole frame.
Unpublished append tails are ignored and truncated before reuse.

Effects: fail, read, write, console, io.

## Methods

### `Node.lastIndex`

```gizlang
function Node.lastIndex(self: Node): i64
```

The index of the last entry of the log.

Effects: fail.

### `Node.initializeRestore`

```gizlang
function Node.initializeRestore(self: mut Node, data: bytes, sourceTerm: i64): Result<bool, string>
```

Offline restore creates a fresh, empty authenticated range. Import bytes and
validate its semantic snapshot first; never merge into existing history.

Effects: fail, read, write, console, io.

### `Node.termAt`

```gizlang
function Node.termAt(self: Node, index: i64): i64
```

The term of the entry at INDEX.

Effects: fail.

### `Node.member`

```gizlang
function Node.member(self: Node, id: i64): bool
```

Whether ID is a voter, in the current or the joint configuration.

Effects: fail.

### `Node.yieldLeadership`

```gizlang
function Node.yieldLeadership(self: mut Node): Result<bool, string>
```

The leader gives up its role in its term (a leadership transfer): it proposes nothing more, and a voter whose log
holds all of it can win the next term.

Effects: fail, read, write, console, io.

### `Node.caughtUp`

```gizlang
function Node.caughtUp(self: Node, id: i64): bool
```

True when the leader knows that voter ID holds its whole log.

Effects: fail.

### `Node.campaign`

```gizlang
function Node.campaign(self: mut Node): Result<Vote, string>
```

Starts an election for the next term and votes for itself; the vote request to send to the peers.

Effects: fail, read, write, console, io.

### `Node.vote`

```gizlang
function Node.vote(self: mut Node, request: Vote): Result<VoteReply, string>
```

The answer to the vote request REQUEST; a vote is durable before it is given.

Effects: fail, read, write, console, io.

### `Node.recordVote`

```gizlang
function Node.recordVote(self: mut Node, reply: VoteReply): Result<bool, string>
```

Counts the answer REPLY; true when the node became the leader.

Effects: fail, read, write, console, io.

### `Node.propose`

```gizlang
function Node.propose(self: mut Node, data: bytes): Result<i64, string>
```

Appends DATA as a new entry of the leader; its index.

Effects: fail, read, write, console, io.

### `Node.proposeMany`

```gizlang
function Node.proposeMany(self: mut Node, data: Vec<bytes>): Result<Vec<i64>, string>
```

Proposes each of DATA in order (Node.extend): a sole voter commits all of them with one log sync.

Effects: fail, read, write, console, io.

### `Node.appendMany`

```gizlang
function Node.appendMany(self: mut Node, data: Vec<bytes>): Result<Vec<i64>, string>
```

As proposeMany, but a sole voter syncs and commits DATA at its next flush (Node.flush), not here: its owner may answer
reads of the state before DATA while the log syncs.

Effects: fail, read, write, console, io.

### `Node.flush`

```gizlang
function Node.flush(self: mut Node): Result<bool, string>
```

Syncs the entries not yet durable. A leader calls it after it sends their appends, so its sync and the followers' run in parallel.

Effects: fail, read, write, console, io.

### `Node.request`

```gizlang
function Node.request(self: mut Node, peer: i64, batch: i64): Result<Append, string>
```

Learner peers can receive entries but never contribute a vote or quorum.

Effects: fail.

### `Node.append`

```gizlang
function Node.append(self: mut Node, request: Append): Result<AppendReply, string>
```

The answer to the append request REQUEST, after the entries are durable.

Effects: fail, read, write, console, io.

### `Node.ack`

```gizlang
function Node.ack(self: mut Node, reply: AppendReply): Result<bool, string>
```

Counts the answer REPLY of a follower and moves the commit index; true when it moved.

Effects: fail, read, write, console, io.

### `Node.beginRead`

```gizlang
function Node.beginRead(self: mut Node): Result<Read, string>
```

Starts a read barrier at the commit index. It fails unless the node leads with a committed entry of its term.

Effects: fail.

### `Node.readIndex`

```gizlang
function Node.readIndex(self: mut Node, token: Read): Result<i64, string>
```

Apply through the returned index before replying; tokens cannot be reused after a new
round or term. Each read round requires fresh matching peer replies, never old matches.

Effects: fail.

### `Node.readReady`

```gizlang
function Node.readReady(self: Node): bool
```

Non-consuming readiness for a transport executor. It grants no cut and does
not replace readIndex's exact term/round/token validation.

Effects: fail.

### `Node.beginJoint`

```gizlang
function Node.beginJoint(self: mut Node, voters: Vec<i64>): Result<i64, string>
```

Starts a change of the voters to VOTERS through a joint configuration; the index of its entry.

Effects: fail, read, write, console, io.

### `Node.finishJoint`

```gizlang
function Node.finishJoint(self: mut Node): Result<i64, string>
```

Ends the joint configuration: the new voters alone; the index of its entry.

Effects: fail, read, write, console, io.

### `Node.compact`

```gizlang
function Node.compact(self: mut Node, index: i64, data: bytes): Result<Snapshot, string>
```

Compact only a committed, stable-configuration cut; snapshots carry semantic state and
its voters atomically. The application must supply the exact state at this cut.

Effects: fail, read, write, console, io.

### `Node.install`

```gizlang
function Node.install(self: mut Node, leader: i64, term: i64, snapshot: Snapshot): Result<bool, string>
```

Snapshot transfer must authenticate the elected leader, verify bytes, and apply this
snapshot before serving. Old snapshots never overwrite a newer committed prefix.

Effects: fail, read, write, console, io.

### `Node.snapshotRequest`

```gizlang
function Node.snapshotRequest(self: mut Node, peer: i64, snapshot: Snapshot): Result<Install, string>
```

The returned snapshot and serial are one authenticated transfer; a receipt never counts
toward a read barrier. Appends after installation establish fresh read authority.

Effects: fail.

### `Node.installed`

```gizlang
function Node.installed(self: mut Node, request: Install): Result<InstallReply, string>
```

Installs the snapshot of REQUEST; the answer to the leader.

Effects: fail, read, write, console, io.

### `Node.matchedOf`

```gizlang
function Node.matchedOf(self: Node, peer: i64): i64
```

The last index the leader knows PEER holds, or 0.

Effects: fail.

### `Node.ackSnapshot`

```gizlang
function Node.ackSnapshot(self: mut Node, reply: InstallReply): Result<bool, string>
```

Counts the answer REPLY to an install.

Effects: fail, read, write, console, io.

### `Node.committed`

```gizlang
function Node.committed(self: Node, after: i64): Result<Vec<Entry>, string>
```

A service may only apply entries at or below commit, in index order.

Effects: fail.

