Unique ID Generation#
Info
This example is for Challenge #2: Unique ID Generation
In this challenge we generate globally-unique IDs in a distributed network
Imports
import com.bilalfazlani.zioMaelstrom.* import zio.json.* import zio.*
Here, we define the protocol of the node. It includes messages which the node can handle and messages it can send
Message definitions
case class Generate() derives JsonDecoder case class GenerateOk(id: String) derives JsonEncoder
Unlike echo, this node has some state which we have modeled using Ref[Int]
. We increment the Int
every time we generate a new Id. To make it unique across the cluster, we append the node Id to the generated id.
Why use a Ref
?
Using a Ref
ensures that I can update the state in a thread-safe manner. This is important because the messages are received and processed concurrently
Node application
object Main extends MaelstromNode { val program = receive[Generate] { _ => for { generated <- ZIO.serviceWithZIO[Ref[Int]](_.getAndIncrement) me <- MaelstromRuntime.me combinedId = s"${me}_${generated}" _ <- reply(GenerateOk(id = combinedId)) } yield () }.provideSome[MaelstromRuntime](ZLayer(Ref.make(0))) }
Tip
ZLayer
is used to inject the state.provideSome
is used to provideRef[Int]
layer to the program. This method provides all the layers exceptMaelstromRuntime
Note
Source code for this example can be found on Github