aarondb/consensus

consensus — leader-gated command and lease reference surface

This module composes committed Raft positions with the deterministic command state machine. It is deliberately transport-free: callers supply quorum evidence and a monotonic clock reading. No wall-clock conversion is trusted.

Types

pub type Lease {
  Lease(
    resource: String,
    holder: String,
    fence: Int,
    expires_at: Int,
  )
}

Constructors

  • Lease(
      resource: String,
      holder: String,
      fence: Int,
      expires_at: Int,
    )
pub type LeaseCommand {
  Acquire(resource: String, holder: String, ttl: Int)
  Renew(resource: String, holder: String, fence: Int, ttl: Int)
  Revoke(resource: String, holder: String, fence: Int)
}

Constructors

  • Acquire(resource: String, holder: String, ttl: Int)
  • Renew(resource: String, holder: String, fence: Int, ttl: Int)
  • Revoke(resource: String, holder: String, fence: Int)
pub type ReadError {
  ReadRedirect(leader: option.Option(String))
  ReadQuorumUnavailable
  ReadIndexUnavailable
}

Constructors

  • ReadRedirect(leader: option.Option(String))
  • ReadQuorumUnavailable
  • ReadIndexUnavailable
pub type State {
  State(
    raft: raft_runtime.State,
    commands: command.State,
    leases: List(Lease),
    last_now: Int,
  )
}

Constructors

pub type SubmitError {
  Redirect(leader: option.Option(String))
  QuorumUnavailable
  NotCommitted
  CommandFailed(error: command.CommandError)
  InvalidClock(now: Int, last_now: Int)
  InvalidTtl
  LeaseHeld(resource: String, fence: Int, expires_at: Int)
  StaleFence(resource: String, expected: Int, received: Int)
  LeaseHolderMismatch(resource: String)
}

Constructors

  • Redirect(leader: option.Option(String))
  • QuorumUnavailable
  • NotCommitted
  • CommandFailed(error: command.CommandError)
  • InvalidClock(now: Int, last_now: Int)
  • InvalidTtl
  • LeaseHeld(resource: String, fence: Int, expires_at: Int)
  • StaleFence(resource: String, expected: Int, received: Int)
  • LeaseHolderMismatch(resource: String)

Values

pub fn lease(
  state: State,
  index: Int,
  replicated: Int,
  now: Int,
  request: LeaseCommand,
) -> Result(#(State, option.Option(Lease)), SubmitError)

Uses a caller-supplied monotonic time domain. Regressing clock values are rejected, so expiry cannot be extended by a local wall-clock rollback.

pub fn linearizable_read(
  state: State,
  read_index: Int,
  quorum_confirmed: Bool,
  key: String,
) -> Result(option.Option(String), ReadError)

Linearizable reads require leader confirmation and a ReadIndex at least as recent as the command state. LeaseRead is intentionally not provided here: callers must use a validated lease instead of relabelling a local read.

pub fn new(raft_state: raft_runtime.State) -> State
pub fn submit(
  state: State,
  index: Int,
  replicated: Int,
  request: command.CommandRequest,
) -> Result(#(State, command.CommandResult), SubmitError)

Submission is accepted only on the elected leader after current-term quorum replication has committed the supplied index.

pub fn validate_fence(
  state: State,
  resource: String,
  fence: Int,
) -> Result(Nil, SubmitError)
Search Document