.NET RouteMesh/MeshNode Public Interface¶
.NET per-language interface table of contents · Common Topology · MeshNode · Message Model
1. Scope¶
This document fixes ZLink Framework's .NET RouteMesh/MeshNode public interface. The target audience is .NET application developers and public provider implementers. This document owns the C# signature for physical mesh registration, logical channel membership, manual peer, handler, Spot/Actor registration, and runtime weight change.
2. Registration Interface¶
public interface IZLinkFrameworkOptions
{
TimeSpan DefaultRequestTimeout { get; set; }
TimeSpan SessionReplacementCallbackTimeout { get; set; }
long ApplicationVersion { get; set; }
string? MaintenanceWave { get; set; }
IZLinkCodecRegistryBuilder Codecs { get; }
IZLinkWorkerOptions Worker { get; }
void AddHandlersFromAssemblyOf<TMarker>();
void AddHandlersFromAssemblyOf(Type markerType);
void AddHandlersFromAssembly(System.Reflection.Assembly assembly);
void DisableImplicitHandlerAutoRegistration();
IZLinkMetadataPolicyBuilder ConfigureMetadata();
void AddLocationStore(IZLinkLocationStore store);
void AddRelocationStore(IZLinkRelocationStore store);
ZLinkLocationOptions ConfigureLocations();
IZLinkNetworkOptions ConfigureNetwork();
IZLinkDispatchOptions ConfigureDispatch();
IZLinkInboundDispatchOptions ConfigureInboundDispatch();
IZLinkStreamCompressionBuilder ConfigureStreamCompression();
void UseFilter<TFilter>() where TFilter : class, IZLinkHandlerFilter;
IZLinkMeshNodeBuilder AddRouteMesh(string meshName);
IZLinkClientServerChannelRoleBuilder AddClientServerChannel(string channelName);
IZLinkFanoutChannelBuilder AddFanoutChannel(string channelName);
IZLinkStreamNodeBuilder AddStreamNode(string streamNodeName);
}
public enum ZLinkCoreHwmProfile
{
Compact = 0,
LowLatency = 1,
Balanced = 2,
Throughput = 3
}
public enum ZLinkApplicationJobQueueProfile
{
Compact = 0,
LowLatency = 1,
Balanced = 2,
Throughput = 3
}
public enum ZLinkApplicationJobQueuePressureState
{
Running = 0,
Paused = 1
}
public interface IZLinkMeshNodeBuilder
{
IZLinkMeshChannelRoleBuilder Channel(string channelName);
IZLinkMeshNodeBuilder Listen(string endpoint);
IZLinkMeshNodeBuilder Listen(int port = 0);
IZLinkMeshNodeBuilder SetBindHost(string bindHost);
IZLinkMeshNodeBuilder SetAdvertiseHost(string advertiseHost);
IZLinkMeshNodeBuilder SetRoutingId(RoutingId routingId);
IZLinkMeshNodeBuilder SetRoutingIdPrefix(string prefix);
IZLinkMeshNodeBuilder SetPlacementWeight(int weight);
IZLinkMeshNodeBuilder SetActorLimit(int limit);
IZLinkMeshNodeBuilder SetSpotLimit(int limit);
IZLinkMeshNodeBuilder SetActivationConcurrency(int limit);
IZLinkMeshNodeBuilder SetInstanceSpotIdleTimeout(TimeSpan timeout);
IZLinkMeshObjectRoleBuilder Objects();
IZLinkMeshNodeSocketConfig ConfigureRouterSocket();
IZLinkMeshPeerConnections PeerConnections { get; }
IZLinkMeshNodeBuilder SetDefaultRequestTimeout(TimeSpan timeout);
IZLinkMeshNodeBuilder AddRouteSendHandler<THandler, TMessage>(
string? packetName = null)
where THandler : class, IZLinkRouteSendHandler<TMessage>;
IZLinkMeshNodeBuilder AddRouteSendHandler<THandler>(string? packetName = null)
where THandler : class;
IZLinkMeshNodeBuilder AddRouteRequestHandler<THandler, TRequest, TReply>(
string? packetName = null)
where THandler : class, IZLinkRouteRequestHandler<TRequest, TReply>;
IZLinkMeshNodeBuilder AddRouteRequestHandler<THandler>(string? packetName = null)
where THandler : class;
}
public interface IZLinkMeshObjectRoleBuilder
{
IZLinkMeshObjectClientBuilder Client();
IZLinkMeshObjectServerBuilder Server();
}
public interface IZLinkMeshObjectClientBuilder
{
}
public interface IZLinkMeshObjectServerBuilder
{
IZLinkMeshObjectServerBuilder AddEntrySpot<TEntrySpot>()
where TEntrySpot : class, IZLinkEntrySpot;
IZLinkMeshObjectServerBuilder AddSpotFactory<TSpot>(
string spotType,
Action<IZLinkUserSpotFactoryBuilder<TSpot>> configure)
where TSpot : class, IZLinkSpot;
IZLinkMeshObjectServerBuilder AddInstanceSpotFactory<TSpot>(
string instanceSpotType,
Action<IZLinkInstanceSpotFactoryBuilder<TSpot>> configure)
where TSpot : class, IZLinkInstanceSpot;
IZLinkMeshObjectServerBuilder AddActorFactory<TActor, TFactory>(
string actorType,
Action<IZLinkActorFactoryBuilder<TActor>> configure)
where TActor : class, IZLinkActor
where TFactory : class, IZLinkActorFactory<TActor>;
}
public enum ZLinkUserSpotExecutionMode
{
SpotWide = 0,
PerActor = 1
}
public enum ZLinkSpotRelocationCoordinationMode
{
FrameworkManaged = 0,
ApplicationSignaled = 1
}
public interface IZLinkActorFactoryBuilder<TActor>
where TActor : class, IZLinkActor
{
IZLinkActorFactoryBuilder<TActor> DisableRelocation();
IZLinkActorFactoryBuilder<TActor> RecreateOnRelocation();
IZLinkActorFactoryBuilder<TActor> PreserveStateWith<TAdapter>()
where TAdapter : class, IZLinkActorRelocationAdapter<TActor>;
}
public interface IZLinkUserSpotFactoryBuilder<TSpot>
where TSpot : class, IZLinkSpot
{
IZLinkUserSpotFactoryBuilder<TSpot> StableTypeLimit(int limit);
IZLinkUserSpotFactoryBuilder<TSpot> ExecutionMode(
ZLinkUserSpotExecutionMode mode);
IZLinkUserSpotFactoryBuilder<TSpot> RelocationCoordinationMode(
ZLinkSpotRelocationCoordinationMode mode);
IZLinkUserSpotFactoryBuilder<TSpot> DisableRelocation();
IZLinkUserSpotFactoryBuilder<TSpot> RecreateOnRelocation();
IZLinkUserSpotFactoryBuilder<TSpot> PreserveStateWith<TAdapter>()
where TAdapter : class, IZLinkSpotRelocationAdapter<TSpot>;
}
public interface IZLinkInstanceSpotFactoryBuilder<TSpot>
where TSpot : class, IZLinkInstanceSpot
{
IZLinkInstanceSpotFactoryBuilder<TSpot> StableTypeLimit(int limit);
IZLinkInstanceSpotFactoryBuilder<TSpot> DisableRelocation();
IZLinkInstanceSpotFactoryBuilder<TSpot> RecreateOnRelocation();
IZLinkInstanceSpotFactoryBuilder<TSpot> PreserveStateWith<TAdapter>()
where TAdapter : class, IZLinkSpotRelocationAdapter<TSpot>;
}
public interface IZLinkNetworkOptions
{
string BindHost { get; set; }
string? AdvertiseHost { get; set; }
}
public interface IZLinkMeshChannelRoleBuilder
{
IZLinkMeshChannelClientBuilder Client();
IZLinkMeshChannelServerBuilder Server();
}
public interface IZLinkMeshChannelClientBuilder
{
}
public interface IZLinkMeshChannelServerBuilder
{
IZLinkMeshChannelServerBuilder SetWeight(int weight);
IZLinkMeshChannelServerBuilder AddHandlerGroup(string groupName);
IZLinkMeshChannelServerBuilder AddSendHandler<THandler, TMessage>(
string? packetName = null)
where THandler : class, IZLinkSendHandler<TMessage>;
IZLinkMeshChannelServerBuilder AddSendHandler<THandler>(string? packetName = null)
where THandler : class;
IZLinkMeshChannelServerBuilder AddRequestHandler<THandler, TRequest, TReply>(
string? packetName = null)
where THandler : class, IZLinkRequestHandler<TRequest, TReply>;
IZLinkMeshChannelServerBuilder AddRequestHandler<THandler>(string? packetName = null)
where THandler : class;
}
public interface IZLinkClientServerChannelRoleBuilder
{
IZLinkClientServerChannelClientBuilder Client();
IZLinkClientServerChannelServerBuilder Server();
}
public interface IZLinkClientServerChannelClientBuilder
{
IZLinkClientServerChannelClientBuilder Connect(string endpoint);
}
public interface IZLinkClientServerChannelServerBuilder
{
IZLinkClientServerChannelServerBuilder Listen(int port = 0);
IZLinkClientServerChannelServerBuilder SetBindHost(string bindHost);
IZLinkClientServerChannelServerBuilder SetAdvertiseHost(string advertiseHost);
IZLinkClientServerChannelServerBuilder SetWeight(int weight);
IZLinkClientServerChannelServerBuilder AddHandlerGroup(string groupName);
IZLinkClientServerChannelServerBuilder AddSendHandler<THandler, TMessage>(
string? packetName = null)
where THandler : class, IZLinkSendHandler<TMessage>;
IZLinkClientServerChannelServerBuilder AddRequestHandler<THandler, TRequest, TReply>(
string? packetName = null)
where THandler : class, IZLinkRequestHandler<TRequest, TReply>;
}
public interface IZLinkEndpointConnections
{
void Connect(string endpoint);
void Disconnect(string endpoint);
IReadOnlyList<string> ListConnections();
}
public interface IZLinkFanoutChannelBuilder
{
IZLinkFanoutChannelBuilder EnablePublisher(string endpoint);
IZLinkFanoutChannelBuilder EnablePublisher(int port = 0);
IZLinkFanoutChannelBuilder SetBindHost(string bindHost);
IZLinkFanoutChannelBuilder SetAdvertiseHost(string advertiseHost);
IZLinkFanoutChannelBuilder SetRoutingId(RoutingId publisherRoutingId);
IZLinkFanoutChannelBuilder SetRoutingIdPrefix(string prefix);
IZLinkFanoutChannelBuilder SetSendTimeout(TimeSpan timeout);
IZLinkFanoutChannelBuilder SetNoDrop(bool noDrop = true);
IZLinkFanoutChannelBuilder EnableSubscriber();
IZLinkFanoutChannelBuilder Subscribe(string topic);
IZLinkFanoutChannelBuilder Connect(string endpoint);
IZLinkEndpointConnections SubscriberConnections { get; }
IZLinkFanoutChannelBuilder AddHandler<THandler, TEvent>(
string? packetName = null)
where THandler : class, IZLinkFanoutHandler<TEvent>;
}
public interface IZLinkStreamNodeBuilder
{
IZLinkStreamNodeBuilder Bind(string endpoint);
IZLinkStreamNodeBuilder Bind(int port = 0);
IZLinkStreamNodeBuilder SetBindHost(string bindHost);
IZLinkStreamNodeBuilder SetAdvertiseHost(string advertiseHost);
IZLinkStreamNodeBuilder MaxMessageSize(long bytes);
IZLinkStreamNodeBuilder SetHeartbeat(TimeSpan interval, TimeSpan timeout);
IZLinkStreamNodeBuilder SetIdleTimeout(TimeSpan timeout);
IZLinkStreamSocketConfig ConfigureSocket();
IZLinkStreamNodeBuilder EnableActorDispatch();
IZLinkStreamNodeBuilder SetTlsServer(
string certificatePath,
string keyPath,
bool requireClientCertificate = false);
IZLinkStreamNodeBuilder AddSession<TSession>()
where TSession : class, IZLinkSession;
}
public interface IZLinkStreamCompressionBuilder
{
IZLinkStreamCompressionBuilder UseDefault();
IZLinkStreamCompressionBuilder UseLz4();
IZLinkStreamCompressionBuilder Use(IZlinkStreamCompressionCodec codec);
IZLinkStreamCompressionBuilder Disable();
}
public interface IZLinkMetadataPolicyBuilder
{
IZLinkMetadataPolicyBuilder AllowSessionToActor(string key);
IZLinkMetadataPolicyBuilder AllowActorToSession(string key);
}
The defaults, validation, and idle closing rule of the heartbeat interval, heartbeat timeout, and idle timeout are owned by STREAM session §7.
IZLinkStreamNodeBuilder.MaxMessageSize(long bytes) defaults to
64 KiB. It is used only when a StreamNode's Core STREAM inbound path checks
a complete client-to-server message, measured as header bytes plus payload
bytes and excluding the 6-byte prefix. 0 maps to Core -1, so Framework
adds no limit; a negative value is a startup configuration error. A message
over the limit is never partly delivered to the handler. The server records
EMSGSIZE and a diagnostic trace, then closes the connection. The raw client
observes the close rather than a separate wire error code. The Framework
limit doesn't apply to server-to-client outbound messages. ClientServer and
RouteMesh SS don't gain this setting.
The declaration of IZLinkCodecRegistryBuilder and the codec
extension is owned by Serialization.
AddRouteMesh(meshName) registers one process-local
MeshNode. Registering the same
meshName twice in the same process fails host startup with
ZLinkConfigurationException. After Channel(channelName), call exactly
one of Client() or Server(). Client() only creates the send path,
and only Server() provides
weight and handler registration.
A MeshNode with no Server membership
can also start.
RouteMesh connection direction and peer necessity follow Channel topology §8.
Channel topology §8 defines manual handshake and NotRequired handling.
Listen(string endpoint), Bind(string endpoint), and
EnablePublisher(string endpoint) are provided, and the host/port
combination overload expresses the same listener configuration.
AddClientServerChannel(channelName) exposes Client() and Server(); registration and connection decisions follow ClientServer channel.
ClientServer channel §4 defines local Server candidacy and selection.
ConfigureNetwork()'s default BindHost is 127.0.0.1, and if AdvertiseHost is omitted,
the default of Network listener identity §2.1 applies. An
automatic discovery
listener binds to port 0 if the port on Listen()/Bind()/
EnablePublisher() is omitted, or if the listener call itself is
omitted. In manual mode, if the endpoint can't be obtained from a
different discovery source, the listen port and remote endpoint are
specified explicitly. A per-listener host setting takes priority over the
root default.
Channel topology defines fanout descriptors, discovery, and connection direction; this builder exposes EnableSubscriber() and Connect(endpoint).
Automatic RID has the format prefix-<lowercase-canonical-uuid-v4>.
UUID v4 is represented as a lowercase canonical string in 8-4-4-4-12
digit groups. Prefix is ASCII [A-Za-z0-9._-] 1..64 characters, and the
full RID is at most 255 UTF-8 bytes. On conflict with an active owner, it
fails immediately with RoutingIdConflict instead of retrying with a
new UUID. Common MeshNode §3.3 defines where a fixed RID can be used and how its restart conflicts are handled. Slot count, allocation
group, and a public allocation provider aren't provided.
The Object Server's Entry Spot ID also uses the same prefix, but with a
UUID v4 generated separately from the MeshNode RID attached. The format
is <prefix>-entry-<lowercase-canonical-uuid-v4>, and the caller doesn't
specify a fixed Entry Spot ID. This ID's global conflict and the reserved
format validation for a caller-specified Spot ID are defined by the
Spot Model. The prefix and the
generated RID/Spot ID aren't interpreted as placement, shard, or stable
application identity.
A registered MeshNode descriptor must be at most 1 MiB. The Spot type and stateful object capability collection are each at most 1024. Exceeding the bound fails startup — it doesn't apply only some of the registrations.
SubscriberConnections is a runtime handle for the manual subscriber
endpoint set. It provides connect, disconnect, and current-list query
targeting the same set of endpoints registered on the builder. An
automatic subscriber's discovery results aren't changed by this handle.
AddHandlersFromAssemblyOf(...) and AddHandlersFromAssembly(...) only
add the specified assembly to the handler scan scope. The
declaration of the method, group, and packet attributes used for the
scan is owned by Common Runtime.
EnableActorDispatch() only activates a STREAM node's Actor dispatch
capability. If the same host has no Mesh whose object role is Client
or Server, and no Location Store, startup fails. Since the global
ActorId determines the current Mesh and owner route, this setting doesn't
take a MeshName.
DefaultRequestTimeout's default is 30 seconds. Publisher configuration on the fanout builder follows Channel messaging §7.
SessionReplacementCallbackTimeout is the maximum time an actor-binding replacement callback may
run before Framework force-closes the retired session; its default is 30 seconds. Worker sets the
worker's minimum/maximum thread count and idle timeout before host
startup.
ConfigureStreamCompression() and IZLinkStreamCompressionBuilder pick
the STREAM payload compression. This builder doesn't configure the
service transport lifecycle or a relocation codec.
ApplicationVersion is set once for the whole host, in the range
0..long.MaxValue, defaulting to 0. Every local MeshNode publishes
this value, and a negative value is rejected with
ZLinkConfigurationException before startup. MaintenanceWave is a
stable ID that, when null, means no wave exclusion is used.
Objects().Client() and Objects().Server() are the .NET role builders; MeshNode defines the roles.
Channel topology defines Channel peer connection requirements for Object Client. Invalid Node direct handler registration maps to ZLinkConfigurationException.
Channel topology defines Object Client pair connection requirements.
The Actor/User Spot/Instance Spot factory fixes stable type, per-object-kind factory options, and explicit relocation policy in the same registration. There's no overload that omits the policy. Stable type is UTF-8 1..255 bytes, and a duplicate type is a startup error. The Entry Spot ID is issued by the framework.
The .NET placement builder exposes weight and population-capacity options; Location runtime defines eligibility and capacity decisions.
SetInstanceSpotIdleTimeout(...) is the .NET option; Spot model §6.2 defines its default, validation, and idle cleanup.
3. Manual Peer¶
public readonly record struct ZLinkMeshPeerConnection(
string Endpoint,
RoutingId? ExpectedRoutingId);
public interface IZLinkMeshPeerConnections
{
void Connect(string endpoint);
void Connect(RoutingId expectedRoutingId, string endpoint);
void Disconnect(string endpoint);
IReadOnlyList<ZLinkMeshPeerConnection> ListConnections();
}
Channel topology §8 defines Connect peer admission and liveness.
A handler filter is a public extension point the application implements
and registers on the root. Calling next runs the remaining filters and
handler. A request that doesn't call it ends with Rejected, and the
filter doesn't build a business reply directly. The applicable scope,
execution order, and fanout isolation are determined by the common
Framework API.
public enum ZLinkHandlerDispatchKind
{
NodeDirectSend = 0,
NodeDirectRequest = 1,
ChannelSend = 2,
ChannelRequest = 3,
ClassicFanout = 4
}
public interface IZLinkHandlerFilterContext : IZLinkMessageContext
{
ZLinkHandlerDispatchKind DispatchKind { get; }
}
public delegate ValueTask ZLinkHandlerFilterNext();
public interface IZLinkHandlerFilter
{
ValueTask InvokeAsync(
IZLinkHandlerFilterContext context,
ZLinkHandlerFilterNext next,
CancellationToken cancellationToken);
}
ChannelSend and ChannelRequest cover RouteMesh and ClientServer. .NET maps filter failures to ZLinkFrameworkErrorKind.InvalidOperation and Rejected; Framework API §10 defines filter execution and rejection.
AddInstanceSpotFactory's type name can't be empty and must be at most
255 UTF-8 bytes. Per-type active and pending limits can be omitted, but
an explicit value is 1..int.MaxValue. On the same MeshNode, the same
stable type or the same implementation class can't be duplicated across
a User Spot factory and an Instance factory. If TSpot also implements
the closed generic IZLinkUserSpotActorLifecycle<TActor>, it conflicts
with the actor-free contract, so startup fails. Both options apply per
local MeshNode and per Instance type. The registered type set is fixed
before the descriptor is first published, and doesn't change after
startup.
The factory configure callback sets options and relocation policy on one
builder. The callback must call exactly one of DisableRelocation(),
RecreateOnRelocation(), PreserveStateWith<TAdapter>(). Selecting
none or more than one is a startup configuration error before socket
bind. The Actor builder only takes
IZLinkActorRelocationAdapter<TActor>, and the User/Instance Spot
builder only takes IZLinkSpotRelocationAdapter<TSpot>. If the factory
target and adapter kind don't match, it fails with the same error. There
is no separate registration API.
The framework synchronously runs the callback exactly once inside the registration call. Once the callback returns, the builder configuration is fixed. If the application keeps the builder outside the callback and calls it again, it's a configuration error. If the callback throws, the factory isn't registered and the same exception is propagated to the caller.
Spot model defines PerActor relocation policy; .NET names the option ZLinkUserSpotExecutionMode.PerActor.
Spot model defines execution and coordination mode defaults and eligibility; .NET exposes SpotWide, FrameworkManaged, and ApplicationSignaled.
If expected RID is omitted, the admission handshake determines the remote identity. If expected RID is specified, the connection isn't admitted if the handshake identity differs. A manual connection also uses the same MeshName/RID/ ChannelName/security validation as an automatic discovery connection.
4. Dispatch Scope Of Handler And Filter¶
A DI scope is created each time a Node direct/Channel send/request and classic fanout subscription handler runs. The handler and filter are each created once by the framework in this scope, and use the same scoped dependency. If a classic fanout message matches multiple subscription handlers, a separate scope is created per subscription handler. Even if the application registers the handler or filter type as singleton/scoped/transient, this lifetime doesn't change. Once dispatch finishes, the framework cleans up the instances it created first, then cleans up the scope.
A Channel handler is distinguished by (ChannelName, message kind,
packet name). A RID direct route handler is registered on the MeshNode
builder and uses a route handler context that provides source RID.
Duplicate registration of the same key is a startup error, and the same
packet name can be registered across different channels or route
families.
AddHandlerGroup(groupName) exposes, on that ChannelName, the send/
request handlers found by scanning that have the same
ZLinkHandlerGroupAttribute value. TicTacToe's manual topology does not mean
manual handler registration. The .NET sample exposes its handlers through
assembly scanning and AddHandlerGroup(...); use typed
AddSendHandler(...)/AddRequestHandler(...) directly only for a separate
example that intentionally demonstrates direct registration.
The weight of IZLinkMeshChannelServerBuilder and
IZLinkClientServerChannelServerBuilder is 0 to 10000, defaulting to
100. An out-of-range value is ZLinkConfigurationException in both
startup config and runtime change. Weighted selection, including node
placement, computes the sum of candidate weight using at least a 64-bit
integer. 0 is only excluded from that channel's new select-one and a
RouteMesh Logical Multicast remote target. It doesn't affect a RID
direct route, other membership, or an already-submitted operation.
5. Publisher And Runtime Option¶
public interface IZLinkSocketConfig
{
long MaxMessageSize { get; set; }
ulong SendHighWaterMark { get; set; }
ulong ReceiveHighWaterMark { get; set; }
int SendBufferSize { get; set; }
int ReceiveBufferSize { get; set; }
TimeSpan? Linger { get; set; }
TimeSpan? ReceiveTimeout { get; set; }
TimeSpan? ConnectTimeout { get; set; }
TimeSpan? HandshakeInterval { get; set; }
bool? IPv6 { get; set; }
bool? TcpNoDelay { get; set; }
bool? Immediate { get; set; }
int Weight { get; set; }
}
public interface IZLinkStreamSocketConfig
{
ulong SendHighWaterMark { get; set; }
ulong ReceiveHighWaterMark { get; set; }
int SendBufferSize { get; set; }
int ReceiveBufferSize { get; set; }
TimeSpan? Linger { get; set; }
TimeSpan? ReceiveTimeout { get; set; }
TimeSpan? ConnectTimeout { get; set; }
TimeSpan? HandshakeInterval { get; set; }
bool? IPv6 { get; set; }
bool? TcpNoDelay { get; set; }
bool? Immediate { get; set; }
}
public interface IZLinkRouteConfig
{
bool RequireKnownPeer { get; set; }
bool AllowPeerHandover { get; set; }
bool EnablePeerProbe { get; set; }
RoutingId ConnectRoutingId { get; set; }
}
public interface IZLinkOutboundRouteConfig
{
bool ProbeRouterOnConnect { get; set; }
}
public interface IZLinkRouteMeshRuntimeOptions
{
IZLinkMeshPlacementRuntimeOptions Mesh(string meshName);
IZLinkMeshChannelRuntimeOptions Channel(string channelName);
}
public interface IZLinkMeshPlacementRuntimeOptions
{
int PlacementWeight { get; set; }
}
public interface IZLinkMeshChannelRuntimeOptions
{
int Weight { get; set; }
}
public interface IZLinkMeshNodeSocketConfig
{
ulong SendHighWaterMark { get; set; }
ulong ReceiveHighWaterMark { get; set; }
TimeSpan? ReceiveTimeout { get; set; }
}
MaxMessageSize is the .NET ClientServer application listener option. Framework API §4 owns its default bound, the meaning of 0, and its exclusion from RouteMesh.
IPv6, TcpNoDelay, and Immediate are applied to the socket only when a value is set. A null value isn't applied, so the Core default stays in effect.
Submit and completion §6 defines Logical Multicast completion.
IZLinkRouteMeshRuntimeOptions is a public DI singleton. Querying
unregistered membership is ZLinkConfigurationException.
At runtime, Mesh(meshName).PlacementWeight and
Channel(channelName).Weight can be changed. The two weights are
independent of each other, and node weight is only used for object
create/relocation target selection. ChannelName uniquely selects a local
RouteMesh or ClientServer Server registration. HWM and timeout are set
before startup in ConfigureRouterSocket().
IZLinkMeshNodeSocketConfig is the .NET socket-config surface; Application job queue and backpressure defines message bounds and resource guards.
ConfigureInboundDispatch() returns IZLinkInboundDispatchOptions; Application job queue and backpressure defines Core HWM, capacity, and threshold decisions.
6. Messaging Metadata¶
The Node direct, ChannelName, Spot direct, Actor send/request, and
Logical Multicast call builders commonly have the following overload.
The handler context provides an immutable ZLinkMessageMetadata
snapshot.
public interface IZLinkMetadataCall<TSelf>
{
TSelf Metadata(string key, string value);
TSelf Metadata(ZLinkMessageMetadata metadata);
}
Setting the same key multiple times sends the last value. The whole
metadata's UTF-8 encoded size can't exceed 1024 bytes. A reply doesn't
automatically copy request metadata, and a regular reply doesn't have a
metadata setter. The allowlist applied to STREAM session and Actor relay
is owned by the root's ConfigureMetadata().
7. Location Store And Startup¶
A host using automatic discovery, distributed Spot/Actor address, or Actor relocation must explicitly register a location store. The official Redis location store package is the production default implementation. Without registration, host startup fails. A process-local in-memory implementation can only be registered in a single-process contract test. The store capability and the Redis constructor/options are owned by .NET Location And Maintenance.