As part of the broadcast challenge, nodes will receive work with below messages
Topology
topology message contains the list of all nodes in the cluster mapped to their neighbors.
Broadcast
broadcast message has an Integer number in it. Not all the nodes will receive all the numbers in broadcast. The goal is to make sure that all nodes get all the numbers eventually using gossip.
Read
read Maelstrom will expect a reply to this message with all the number that that node knows about either via broadcast or gossip.
Gossip
Our nodes will send gossip messages to each other to gossip the numbers they have received via broadcast.
Because there are multiple messages, lets create a sealed trait to represent them. We will use zio-json annotations to make it easy to serialize and deserialize these messages.
objectMainextendsMaelstromNode{// some helper functionsvalgetState=ZIO.serviceWithZIO[Ref[State]](_.get)defupdateState(f:State=>State)=ZIO.serviceWithZIO[Ref[State]](_.update(f))defgossip(state:State)=ZIO.foreachPar(state.neighbours)(_sendGossip(state.messages))valstartGossip=getState.flatMap(gossip).delay(500.millis).forevervalprogram=receive[InMessage]{caseBroadcast(broadcast)=>updateState(_.addBroadcast(broadcast))*>reply(BroadcastOk())caseRead()=>getState.map(_.messages).flatMap(x=>reply(ReadOk(x)))caseTopology(topology)=>for{me<-MaelstromRuntime.meneighbours=topology(me).toSet_<-updateState(_.addNeighbours(neighbours))_<-reply(TopologyOk())_<-startGossip.forkScoped.unit}yield()caseGossip(gossipMessages)=>updateState(_.addGossip(gossipMessages))}.provideSome[MaelstromRuntime](ZLayer(Ref.make(State())))}
Tip
This is a naive implementation of gossip protocol. We are sending all the numbers in a node's state to all its neighbors. This will not scale well. Find a better way to do this.
Note
Source code for this example can be found on Github