03. Messaging execution — Channel messaging¶
This category covers the entry points IZLinkRouteClient and IZLinkFanoutClient provide. The
exact signatures are owned by the
Channel messaging exact interface
(Korean-only). This document does not repeat that signature — it collects only what is needed to
complete a call to each entry point in practice.
SendToChannel<TMessage>¶
Sends a one-way message to one ready target (RouteMesh or ClientServer) registered under a ChannelName. It does not wait for a reply.
Options. The following modifiers attach to this call.
| Modifier | Default | Meaning |
|---|---|---|
.Metadata(key, value) / .Metadata(ZLinkMessageMetadata) |
none | key-value passed to the handler. Bounded to 1024 bytes (UTF-8) combined; the last value wins for a repeated key |
.Async(ct) |
required terminal | waits only until source-local admission succeeds |
Completion. Normal completion means this process accepted the message onto its queue. It
does not wait for remote handler execution or subscriber receipt. If there is no queue room, it
waits until the socket send timeout (1 second if unset, changed with
SetDefaultSocketSendTimeout) and then completes with DeadlineExceeded. If the ChannelName has
no ready target it completes with NotFound; a broken route completes with Unavailable; a
runtime shutting down completes with ShuttingDown.
When to use it. Use it for fire-and-forget where no reply is needed. If a reply is needed,
use RequestToChannel.
RequestToChannel<TRequest, TResponse>¶
Selects one ready target under a ChannelName, sends a typed request, and waits for a typed reply.
var reply = await routeClient
.RequestToChannel("game.api", new GetPlayer("player-1"))
.Timeout(TimeSpan.FromSeconds(3))
.Async<Player>(ct);
Options. The following modifiers attach to this call.
| Modifier | Default | Meaning |
|---|---|---|
.Metadata(key, value) / .Metadata(ZLinkMessageMetadata) |
none | attaches only to the request; a reply does not automatically copy the request's metadata |
.Timeout(TimeSpan) |
DefaultRequestTimeout (30 seconds by default, changed with SetDefaultRequestTimeout) |
the upper bound for waiting on the reply. The socket send timeout separately covers transport admission |
.Async<TResponse>(ct) |
terminal (choose one) | keeps the current execution waiting until the reply arrives |
.Yield<TResponse>(ct) |
terminal (choose one) | valid only inside a SpotWide User Spot·Instance Spot handler. While waiting it releases the User Spot gate to let a sibling job proceed. Calling it in any other execution context completes with InvalidOperation |
Completion. Completes with TResponse (the handler's return value), or with
DeadlineExceeded on timeout, NotFound if the ChannelName has no ready target, Unavailable
on a broken route, or ShuttingDown while the runtime is shutting down.
When to use it. Use it when a reply value is needed. For one-way, use SendToChannel. Use
Yield inside a SpotWide handler so that your own wait does not block a sibling job while
another request or worker is in progress.
SendToNode<TMessage>¶
Sends a one-way message by directly specifying a MeshName and a target Node RID. Use it only to manage one specific MeshNode, not for ChannelName-based selection.
await routeClient
.SendToNode("play", RoutingId.From("play-node-1"), new DrainRequested())
.Async(ct);
Options. Same as SendToChannel — .Metadata(...), terminal .Async(ct).
Completion. Uses the same completion kinds as SendToChannel. If the target RID is an
Object Client (an RID that cannot register a handler), it completes with NotFound instead of
forwarding to another target.
When to use it. Do not use it for placing or messaging business objects (actor·spot) — use ActorId·SpotId·ChannelName for that. Use Node direct only to target one specific node for operational purposes.
RequestToNode<TRequest, TResponse>¶
Directly specifies a MeshName and a target Node RID to exchange a typed request/reply.
var status = await routeClient
.RequestToNode("play", RoutingId.From("play-node-1"), new GetNodeStatus())
.Async<NodeStatus>(ct);
Options. Same as RequestToChannel — .Metadata(...), .Timeout(...), terminal
.Async<TResponse>(ct) or .Yield<TResponse>(ct).
Completion and usage. Same as RequestToChannel, except that target selection is a fixed
specified RID rather than ChannelName round-robin.
Publish<TEvent> (classic fanout)¶
Publishes a typed event to an independent fanout channel. This is a different family from
IZLinkRouteClient's channel operations — the publisher does not know its subscribers.
await fanoutClient
.Publish("lobby.events", new PlayerJoined("player-1"))
.Async(ct);
// when an explicit topic is required
await fanoutClient
.Publish("lobby.events", "region.eu", new PlayerJoined("player-1"))
.Async(ct);
Options. The following modifiers attach to this call.
| Modifier | Default | Meaning |
|---|---|---|
| omitting the topic argument | uses the event's packet name as the topic | using a reserved topic name completes with ArgumentException |
.Async(ct) |
required terminal | waits only until source-local publish admission completes |
Completion. Normal completion means publish admission finished. It does not report subscriber count or receipt — it completes normally even with zero targets. Once started, it does not turn an individual target's failure into an overall failure, and it does not retry.
When to use it. Use it for observation·notification where the publisher must not know its
subscribers. For messaging aimed at a specific target, use SendToChannel or
RequestToChannel.
Codec registration (configuration time)¶
Unlike the other entries, this is a host configuration-time registration call, not a terminal await. An application that only uses JSON does not need this entry.
Options. The following modifier attaches to this call.
| Modifier | Default | Meaning |
|---|---|---|
.Use(IZLinkCodecExtension) |
JSON if unset | registers a business payload serializer. Call it multiple times to register multiple content types |
Completion. Registers synchronously with no return value. Call it only before the host starts — a call after startup is outside the contract.
When to use it. Use it when the content type is not JSON (MessagePack, Protobuf, etc.).
Besides the official ZLinkMessagePackCodec.Default/ZLinkProtobufCodec.Default, a custom
serializer can also be registered by implementing IZLinkCodecExtension directly.
The wire codec for a STREAM connection is a separate contract
(IZlinkStreamCodecRegistration, owned by the Stream Connector). This entry covers only the
business payload serializer.
Common failure·cancellation rules (apply to every entry)¶
These apply in common to every entry point in this category and are not repeated per entry.
- If the
CancellationTokenis already triggered before admission, it completes as cancelled exactly once and does not start admission. - When admission, timeout, shutdown, and cancellation race, exactly one becomes the terminal atomically, and no late admission is created afterward.
- An invalid argument, handle, or state is handled as a .NET exceptional completion
(an exception) — a different layer from the completion kinds this document lists
(
NotFound/Unavailable/DeadlineExceeded/ShuttingDown).
The full basis is the Channel messaging exact interface and the Common runtime exact interface (both Korean-only).