The usual semantics of a consumer is that each message is delivered to exactly one receive or subscription.
The usual semantics of a consumer is that each message is delivered to exactly one receive or subscription. Therefore, multiple subscriptions on a consumer receive messages randomly. If messages need to be delivered multiple times, each receiver should have a separate consumer.
Request[RESPONSE] cannot be covariant.
Request[RESPONSE] cannot be covariant. This is easy to see because to enforce the response type, reply(...) must have an argument type of RESPONSE which would be impossible with a covariant type parameter (if it was covariant, it would be possible to assign a Request[SUBTYPE1] to a Request[SUPERTYPE] and then call reply with a SUBTYPE2 as the response, which would break type safety). The consequence of the invariance is that:
1) reply(...) is type safe, which is good; 2) It is not possible to declare RequestResponseClient as RequestResponseClient[REQ <: Request[RESP], RESP] because that would assume covariance; 3) It is not possible to use something like Request[MyResponseType] as the common supertype for requests because that would assume covariance again - the solution is to use another supertype - e.g. declare a separate sealed trait MyRequestType to enforce type safety on the client and the consumers / producers - this is not a huge constraint though.
This is all the consequence of the requirement to enforce type safety on the response for each request and also the fact that we want a common reply(...) method declared in the Request trait. The other option would be the Akka typed route, which is basically making a reply sender reference part of the request message. The downside of that is:
1) A sender reference needs to be declared explicitly in every request message, making it part of the model; 2) The ask syntax is complicated and unintuitive - see https://doc.akka.io/docs/akka/current/typed/interaction-patterns.html#request-response; 3) Requires the existence of sender references with marshalling - this is fine in Akka where serializable references are assumed to be used everywhere, but it is quite intrusive if the application model is forced to have these references everywhere. I think extending the trait is less intrusive and less verbose.
Of course, the choice of adding Request[RESPONSE] does not preclude the addition of an Akka-style API at some point if extending the trait will ever become a constraint.
Type class to bind a request message type to a response type.
Type class to bind a request message type to a response type. It makes request-response mapping pluggable, without enforcing any kind of convention on the implementor.
Configuration for a service.
Configuration for a service. The service config can be used to create or deploy a service or to create a client for it. A service configuration can be shared between the server and client side.