Echo#
Info
This example is for Challenge #1: Echo
It demonstrates how to create a simple node that echoes messages back to the sender
import zio.json.{JsonEncoder, JsonDecoder}
import zio.{ZIOAppDefault, ZIO}
import com.bilalfazlani.zioMaelstrom.*
Here, we define the protocol of the node. It includes messages which the node can handle and messages it can send. Create data classes only for the body part of a maelstrom message. The top level fields (i.e. src, dest) are handled by the library
case class Echo(echo: String, msg_id: MessageId) extends NeedsReply // (1)!
derives JsonDecoder // (2)!
case class EchoOk(echo: String, in_reply_to: MessageId, `type`: String = "echo_ok")
extends Sendable,
Reply // (3)!
derives JsonEncoder // (4)!
- Every messages that needs an acknowledgement or reply should extend
NeedsReply
- All input messages need a way to decode them. We use
zio-json
to deriveJsonDecoder
- Messages that need to be sent out need to extend from
Sendable
. If they are a reply to some other message, they should also extend fromReply
- Outgoing messages need
JsonEncoders
Note
Refer to Maelstrom documentation for more information on the standard message fields like msg_id
, type
, in_reply_to
etc
This is the Node definition. It defines the behavior of the node and is a typical ZIO application. We use the recieve
function to define a handler for incoming request messages
object Main extends ZIOAppDefault {
val echoHandler: ZIO[MaelstromRuntime, Nothing, Unit] =
receive[Echo](msg => reply(EchoOk(echo = msg.echo, in_reply_to = msg.msg_id))) // (1)!
val run = echoHandler.provide(MaelstromRuntime.live)
}
reply
is a function that sends a reply to the sender of the message. It takes aSendable
&Reply
message as an argument. You can only call reply on messages that extendNeedsReply
Using maelstrom DSL functions such as receive
and reply
requires MaelstromRuntime
which can be provided as a ZLayer
to the application as shown above
Note
Source code for this example can be found on Github