Contract lookup
Caller resolves the contract metadata and chooses a transport route.
Это содержимое пока не доступно на вашем языке.
Understanding the end-to-end lifecycle of a call helps you reason about instrumentation, performance optimisations, and where to plug in your own infrastructure pieces. This guide walks through every stage of a unary call and highlights how streaming requests build on the same pipeline.
Contract lookup
Caller resolves the contract metadata and chooses a transport route.
Transport handshake
A stream ID is reserved and request metadata is pushed through the transport.
Responder dispatch
The responder endpoint decodes payloads, finds a handler, and executes it.
Response & trailers
Results flow back with status trailers, health metrics, and optional context data.
RpcCallerEndpoint
receives a method invocation such as
callUnary<Req, Res>()
from a generated or handwritten caller class.x-route-service
) to the outgoing RpcContext
.IRpcTransport.createStream()
. Clients
use odd IDs, responders use even IDs, as enforced by RpcStreamIdManager
.:method
, :path
, content-type
, and te: trailers
headers using
RpcMetadata.forClientRequest()
.RPC Dart supports three data transfer modes controlled by the responder contract:
RpcTransportMessage.directPayload
. This is limited
to transports that return supportsZeroCopy == true
, such as
RpcInMemoryTransport
.IRpcCodec
instances. The built-in RpcCodec
helper uses CBOR for compact binary data.When serialisation is required, RPC Dart wraps your payload with a gRPC-style
5-byte prefix (RpcMessageFrame.encode
) and emits it through
IRpcTransport.sendMessage()
.
IRpcTransport.incomingMessages
and groups
frames by stream ID.RpcResponderContract
.addUnaryMethod
(or a
streaming equivalent) and decides whether zero-copy is allowed for the
specific request/response pair.RpcContext
that carries headers, deadlines, and
cancellation tokens.RpcMessage.isEndOfStream
).
Bidirectional streams use the same infrastructure in both directions.RpcStatus.OK
).RpcMessage<T>
with isEndOfStream = true
, and resolves the pending future
or completes the response stream.RpcError
-like exception populated with the status code and message for easy
debugging.releaseStreamId
so that
future calls can reuse them without reopening the connection.Handlers return Stream<T>
instead of Future<T>
. The endpoint listens to
the stream and converts each event into RpcTransportMessage
frames. The
caller receives a Dart stream that mirrors the server output one-to-one.
The caller passes a Stream<Req>
to callClientStream
. The endpoint pipes
each request event through the same transport stream ID. Once the caller’s
stream completes the responder handler is awaited for a single response.
Both sides exchange independent streams. RPC Dart reuses the same transport
pipeline but keeps two processors running: one for outbound client events
and one for inbound server events. Flow control and cancellation are handled
via the shared RpcContext
.
IRpcMiddleware
and registering it on
the endpoint. Middleware can inspect and mutate requests or responses before
they reach handlers.RpcCallerEndpoint.health()
or
RpcResponderEndpoint.health()
, which aggregate transport status and endpoint
metrics into RpcEndpointHealth
snapshots.IRpcTransport
(or
derive from RpcBaseTransport
) to connect RPC Dart to any messaging fabric
without altering caller/responder code.Understanding these steps makes it easier to decide where to add logging, metrics, retries, or protocol extensions while keeping application logic clean and portable.