def someApplication(i: Int): Int
someApplication(12) // 20
someApplication(12) // 40
Raft is a distributed consensus algorithm, it allows a number of processes to reach consensus on a value over asynchronous network.
Two inter-process RPC:
RaftCluster.read(); // return null
RaftCluster.write(20);
RaftCluster.read(); // return 20
Initial | Desired |
---|---|
Start an election if needed:
1a. Periodic check
import cats.effect.Timer
import fs2.Stream
trait RaftAlgorithm[F[_]] {
def raftProcess[F[_]: Timer](randomTime: F[FiniteDuration]): Stream[F, Unit] = {
Stream.repeatEval {
for {
wait <- randomTime
_ <- Timer[F].sleep(wait)
....
} yield ()
}
}
def needElection: F[Boolean] = ???
}
1b. Check existing cluster state
import cats.effect.Timer
import fs2.Stream
trait RaftAlgorithm[F[_]] {
...
def state: Ref[F, NodeState]
def needElection: F[Boolean] = {
for {
st <- state.get
noLeader = st.leader.isEmpty
responses <- if (noLeader) {
state.update(_.copy(tpe = "Candidate"))
*> getVotes
} else {
F.pure(Map.empty) // do nothing
}
...
} yield {
}
}
def getVotes: F[Map[String, VoteRequest]] = ???
}
case class NodeState(
tpe: String, // Follower, Candidate, Leader
leader: Option[String]
...
)
var on steroid, used to model mutable state that is accessed concurrently
trait Ref[F[_]A] {
def get: F[A]
def update(f: A => A): F[Unit]
}