# raft

> Run a Raft consensus node in Langoost — bootstrap a cluster, replicate a log through an applyLog callback, and query leadership and state.

# raft

The `raft` module (built on hashicorp/raft with BoltDB storage) runs a Raft
consensus node. You provide an `applyLog` callback; the replicated-state-machine
`Apply` step dispatches each committed entry to it. Nodes are referenced by an
integer **handle**. Import it with `import raft`.

## Functions

| Function | Signature | Description |
| --- | --- | --- |
| `start` | `raft.start(opts) → int` | Start a node; returns a handle |
| `apply` | `raft.apply(h: int, command: string) → bool` | Replicate one log entry through the cluster |
| `isLeader` | `raft.isLeader(h: int) → bool` | Whether this node is the leader |
| `leader` | `raft.leader(h: int) → string` | Address of the current leader |
| `state` | `raft.state(h: int) → string` | Node state (e.g. `"Leader"`, `"Follower"`, `"Candidate"`) |
| `addPeer` | `raft.addPeer(h: int, id: string, addr: string) → bool` | Add a voter to the cluster |
| `shutdown` | `raft.shutdown(h: int) → bool` | Stop the node |

`opts` for `start`:

| Key | Description |
| --- | --- |
| `nodeId` | Unique node identifier |
| `addr` | Bind address for Raft transport |
| `storePath` | Directory for the BoltDB log store |
| `bootstrap` | `true` to bootstrap a new single-node cluster |
| `peers` | Initial peer set |
| `applyLog` | Callback `fn(command)` run for each committed entry |

## Example

```goost
import raft

let node = raft.start({
    nodeId: "n1",
    addr: "127.0.0.1:7000",
    storePath: "./raft-data",
    bootstrap: true,
    applyLog: fn(command) {
        println("applied: " + command)
    },
})

if raft.isLeader(node) {
    raft.apply(node, "set x = 1")
}
```