Multiplexed Endpoints
This algebra provides vocabulary to define endpoints multiplexing several requests and responses.
"org.julienrf" %% "endpoints-algebra" % "0.15.0"
In general, each possible resource or action supported by a service is exposed through a specific endpoint, taking a specific request type and a specific response type.
However, in some cases it is useful to use a same endpoint to manage several resources or actions. We call them multiplexed endpoints.
The algebra enriches the Endpoints
algebra with the concept of MuxEndpoint[Req, Resp, Transport]
, defining a multiplexed endpoint with a request containing a type Req
, a response of type Resp
, and serializing data to and from the Transport
type.
For instance, the type MuxEndpoint[Command, Event, Json]
defines and endpoint whose requests contain Command
values, whose responses contain Event
values, and which serialize commands and events to Json
.
Since the type of a response can vary according to the type of specific request, multiplexed endpoints require that request types extend the MuxRequest
type:
val users: MuxEndpoint[Command, Event, Json] =
muxEndpoint[Command, Event, Json](
post(path / "users", jsonRequest[Json]),
ok(jsonResponse[Json])
)
// Types of commands
sealed trait Command extends MuxRequest
final case class CreateUser(name: String) extends Command {
type Response = UserCreated
}
final case class DeleteUser(id: Long) extends Command {
type Response = UserDeleted
}
// Types of responses
trait Event
case class UserCreated(id: Long) extends Event
case class UserDeleted(id: Long) extends Event
Note that the Command
request type extends MuxRequest
and that each concrete Command
refines its Response
type member to refer to a concrete Event
type.
Typically, client interpreters fix the MuxEndpoint[Req, Resp, Transport]
type to be a function from Req
to Future[Req#Response]
, so that calling users(CreateUser("Alice"))
(statically) returns a Future[CreatedUser]
, and calling users(DeleteUser(42))
returns a Future[DeletedUser]
.