Outgoing request

Learn how to create outgoing requests.

In order to make an RPC, you construct an outgoing request and then pass this request as a parameter to the invoke method of an invoker.

An outgoing request carries all the information an invoker needs to send a request:

An outgoing request also holds features. These features are used for local communications within this pipeline; they are also used for communications between invokers in the pipeline and your application code.

The request fields represent out-of-band information carried by a request "over the wire". These fields are usually read and written by interceptors and middleware in an effort to coordinate the processing of the same request in the client and in the server.

A field is an entry in a dictionary RequestFieldKey to sequence of bytes, where RequestFieldKey is an enumeration defined in Slice:

slice
unchecked enum RequestFieldKey : varuint62 {
Context = 0
TraceContext = 1
CompressionFormat = 2
Deadline = 3
Idempotent = 4
}

For example, when the compressor interceptor compresses the payload of an outgoing request, it sets the request field CompressionFormat. This tells the compressor middleware on the other side of the connection "this payload is compressed with brotli"; the compressor middleware can then decompress this (incoming) request payload.

The payload of a request is a stream of bytes that represents the argument(s) of an operation. When a connection sends a request, it reads and logically copies these bytes to the network connection until there is no more byte to read.

On the other side, the connection reads these bytes from the network, creates an incoming request and gives this request to a dispatcher.

The payload of an outgoing request is actually split in two: a first part that the connection sends before awaiting the response, and a second part (the "continuation") that the connection sends in the background while it awaits, receives and returns the response.

On the other side, the dispatcher sees only a single continuous incoming request payload.

It is common for the invokers in an invocation pipeline to transmit information to each other during an invocation. For example, the retry interceptor needs to communicate with the connection cache to make sure the connection cache does not keep retrying with the same server address. In C#, these invokers get and set the request's IFeatureCollection to communicate with each other.

You can also use these features to communicate with the invocation pipeline. For example, you can set the feature ICompressFeature to ask the compressor interceptor (if installed) to compress the payload of your request:

C#
using var request = new OutgoingRequest(serviceAddress)
{
Payload = largePayload,
Features = new FeatureCollection().With<ICompressFeature>(CompressFeature.Compress)
};
// Hopefully invoker is an invocation pipeline with a compressor interceptor.
IncomingResponse response = await invoker.InvokeAsync(request);

By convention, the features are keyed using interface types, such as ICompressFeature in the example above.

Fields are used for communications "over the wire" while features are used for local communications within an invocation pipeline. IceRPC provides both request fields (carried by requests) and response fields (carried by responses), but only request features: since it's all local, there is no need for response features.

Was this page helpful?