HttpCommandCaller

The synchronous calls of a node's sagas to the HTTP command gateways of other contexts: the service mode of the command client (ClientMode.Service), at the base URL endpoints gives each context's internal port (wow.peers.<context>.url), the only one that takes a call; its public port refuses Wow-Call. Each call goes to the command's route as the contracts list it (CommandIndex.routeOf), those of the peers' api jars on the class path by default, as the HttpCommandClient sends one (a command whose body names its aggregate to its route without an id), and carries:

  • the command's body as JSON, and its expected version as If-Match;

  • its deterministic request id as Wow-Request-Id, so every retry and replay is the same request, which the target decides once and answers with the same aggregate;

  • Wow-Call (me.ahoo.wow.api.wire.CallHeader): its command id, the root command's tenant, scope, operator and causation, the root request's facts that propagate, and the wait context a wait that follows the saga goes on with;

  • the calling service's name as Wow-Service, which makes the target take Wow-Call;

  • the trace the call runs in.

The target answers once the command is committed: 200 with its result, or a problem+json whose result is its REJECTED or FAILED result. Anything else is a WowProblemException: an error answered without a result (401 or 403 for a call the target refuses, such as one of a service its lists do not name) as its own code, a connection that fails or no answer within the timeout as the transport's (wow.command.unknown, wow.peer.unavailable), and a success the client cannot read as wow.command.failed, retried with the same request id. The saga's handler fails and its subscription retries it, then parks the aggregate. The call itself is not retried here: the subscription's retry budget is the one that counts.

Constructors

Link copied to clipboard
constructor(endpoints: Map<String, URI>, service: String? = null, client: HttpClient = client(), timeout: Duration = DEFAULT_TIMEOUT, contracts: List<Manifest> = classPathContracts())

The caller of the contexts' internal ports at the fixed endpoints, as the service named service, on client, each call answered within timeout and routed as contracts list its command.

constructor(endpoints: EndpointResolver, service: String?, client: HttpClient, timeout: Duration, timeouts: Map<String, Duration> = emptyMap(), contracts: List<Manifest> = classPathContracts())

The caller of the contexts' internal ports endpoints finds, as the service named service, each call answered within its context's timeout of timeouts, else timeout, and routed as contracts list its command.

Types

Link copied to clipboard

Functions

Link copied to clipboard
open suspend override fun call(call: OutgoingCall): CommandResult
Link copied to clipboard
open override fun reaches(context: String): Boolean

Whether the endpoints give context an internal URL: the node does not start when a saga calls a context without one, rather than failing the call later. A resolver that discovers its services says whether it can find one without looking it up (EndpointResolver.reaches), so a peer need not be up then.