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
ZLayeris used to inject the state.provideSomeis 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