trait CommandProtocol[Alg[_[_]]] {
  def server[F[_]]: Decoder[IncomingCommand[F, Alg]]
  def clientFor[F[_]](id: ID)(implicit sender: CommandSender[F, ID]): Alg[F]

CommandProtocol is to be implemented for each entity algebra. It provides an RPC-like client in charge of transforming calls into instances of OutgoingCommand, delivering such commands to the targeted entity using a CommandSender and decoding the reply. It also defines the corresponding server, which can decode commands into IncomingCommand instances, run the corresponding entity logic and encode the reply.

OutgoingCommand is able to encode the command into a binary representation ready to be sent over the wire and also decode the expected subsequent reply. IncomingCommand is able to decode the incoming command, invoke the corresponding handler and encode the reply.

In other words, clientFor materializes algebra invocations into outgoing commands delivered to server, which acts as a switchboard for incoming commands. See BookingCommandProtocol for a concrete example.

Explicit or implicit representations

CommandProtocol is the entry point for implementations to map algebra entries to concrete commands and replies. Having these lower-level aspects described separately makes it easier to have precise control of versions and to deal with migration challenges.

We provide helpers for definition of binary protocols in endless-protobuf-helpers as well as endless-scodec-helpers and JSON protocols in endless-circe-helpers.

Definition of protobuf protocols is very convenient using endless-protobuf-helpers because scalaPB-generated types can be referenced directly, there is no need for a separate representation of commands (and associated data-mapping headaches).


Command protocols can be tested in isolation via synchronous round-trip exercise of the journey client invocation -> command materialization -> command encoding -> command decoding -> behavior invocation -> reply materialization -> reply encoding -> reply decoding. See BookingCommandProtocolSuite for an example.