Nalix.Runtime.Dispatching
On this page
Namespaces: Nalix.Runtime.Dispatching, Nalix.Runtime.Routing
Assembly: Nalix.Runtime
Nalix.Runtime.Dispatching and Nalix.Runtime.Routing contain the execution APIs that transform retained IBufferLease frames into strongly-typed handler invocations with strict per-connection ordering and zero-allocation synchronous fast paths.
OpCode Dispatch Pipeline
flowchart TD
subgraph Ingress["1. Ingress & Actor Mailbox"]
Lease["IBufferLease + IConnection"] --> Retain["HandlePacket: lease.Retain() + PushCore"]
Retain --> Claim["Worker: TryClaim(out IDispatchSession)"]
end
subgraph Resolution["2. O(1) Resolution & Deserialization"]
Claim --> Extract["connection.PacketClassifier.Extract(lease.Span)"]
Extract --> Table["PacketDispatchOptions: _handlerTable[opCode]"]
Table -->|Found| Deser{"ExpectedPacketType == MemoryPacket?"}
Table -->|Not Found| Drop["Dispose lease + IncrementErrorCount"]
Deser -->|Yes| MemPkt["Wrap in MemoryPacket (zero-copy)"]
Deser -->|No| Reg["PacketRegistry.TryDeserialize(lease.Span)"]
end
subgraph Execution["3. Context, Validation & Pipeline"]
MemPkt --> RentCtx["ObjectPoolManager.Get<PacketContext<IPacket>>()"]
Reg --> RentCtx
RentCtx --> TypeCheck["Verify ExpectedPacketType & IPacketValidatable.Validate"]
TypeCheck --> Pipe["MiddlewarePipeline.ExecuteAsync -> ExecuteTerminalHandler"]
Pipe --> CanExec["descriptor.CanExecute (Permission & Encryption Gate)"]
CanExec --> Invoke["Source-Generated Invoker (PacketHandler<IPacket>)"]
Invoke --> Respond["SendHandlerResponseAsync (ReplyAsync / SendAsync / Stream)"]
end
Respond --> Cleanup["Dispose PacketContext (releases Packet & Scope) + Dispose lease"]Internal Workflow (Source-Verified)
- $O(1)$ Handler Resolution:
PacketDispatchOptions<TPacket>stores compiledPacketHandler<TPacket>descriptors in a flat 65,536-element array (HandlerSlot?[ushort.MaxValue + 1]). Resolving an opcode is a singleVolatile.Readarray index lookup. - Actor-Mailbox Session Claiming:
DispatchChannel<IPacket>groups queued frames by connection and priority (URGENTdown toNONE). A worker claims exclusive ownership of a connection viaTryClaim(out IDispatchSession session), guaranteeing that packets from the same connection are processed sequentially in arrival/priority order without cross-worker races. - Pooled
PacketContext<TPacket>: Before invoking middleware or the handler, the runtime rents aPacketContext<TPacket>fromObjectPoolManager.Shared(preallocated to128instances) and initializes it withownsPacket: true. When the context is disposed, it automatically disposes both the deserialized packet and any scoped[FromScope]services. - Built-in Type, Validation, Permission & Encryption Gates:
- Runtime type verification (
expectedType.IsInstanceOfType(context.Packet)) sendsDirective(FAIL, REQUEST_INVALID, FIX_AND_RETRY)on mismatch. - Structural validation (
IPacketValidatable.Validate(out string? failureReason)) sendsDirective(FAIL, MALFORMED_PACKET, FIX_AND_RETRY)on invalid payloads. - Terminal policy check (
descriptor.CanExecute) verifies[PacketEncryption](context.EncryptedOnWire) and[PacketPermission](context.Connection.Level) even when no middleware is registered.
- Runtime type verification (
- Return-Value Dispatch: Source-generated invokers support
void,Task,ValueTask,TPacket/IPacket,byte[],Memory<byte>,ReadOnlyMemory<byte>, andIAsyncEnumerable<TPacket>(streaming with automaticIPacketStreamable.IsEndOfStreammarking on the final item).
Public Surface
- Dispatch Contracts (IPacketDispatch, IDispatchChannel
, IDispatchSession) - Packet Dispatch (PacketDispatchChannel)
- Dispatch Channel and Router (DispatchChannel
, PacketDispatcherBase ) - Packet Context (PacketContext
) - Packet Sender (PacketSender)
- Handler Return Types