# SignalR — Known Issues & Limitations ## Protocol ### PROTO-1: Server-side IsRawBytesData pre-serialize **Status:** Planned removal **Affects:** `AcWebSignalRHubBase.SendMessageToClient` The server forwards the client's `IsRawBytesData` flag in the response `SignalParams`. This causes the protocol to return raw `byte[]` instead of deserializing. The original design pre-serialized on the server side, but with the zero-copy typed deserialization path (`SignalDataType`), this is redundant. **Plan:** Remove `IsRawBytesData` forwarding from server response path. The client should use `SignalDataType` for typed deserialization and explicit `byte[]` type for raw data. ### PROTO-2: Parameter serialization is per-parameter **Status:** Known performance concern **Affects:** `SignalParams.SetParameterValues` / `GetParameterValues` Each parameter is individually serialized via `ToBinary()` / `BinaryTo(Type)` — N context pool acquire/release cycles. For many small primitives (int, bool, string) the per-call overhead may exceed a single bulk serialization. **Possible optimization:** Batch fast-path — single serialization context for all parameters. Benchmark first. ### PROTO-3: Parameter serialization is AcBinary only **Status:** Limitation **Affects:** `SignalParams.SetParameterValues` / `GetParameterValues` Uses `ToBinary()` / `BinaryTo()` exclusively. JSON parameter support would require dispatching on `DataSerializerType` + `AcJsonSerializer` reference. Low priority — binary is the primary transport. ## Transport ### TRANS-1: BufferWriterChunkSize defaults to 64KB for SignalR **Status:** DONE **Affects:** `AcBinaryHubProtocol` constructor, write path `BufferWriterChunkSize = 4096` set in `AcBinaryHubProtocol` constructor. Aligns with Kestrel slab size, reduces latency-to-first-byte. Non-SignalR paths keep 64KB default. ### TRANS-2: WebSocket buffer sizes are hardcoded **Status:** Acceptable **Affects:** `AcSignalRClientBase` connection setup Transport max message size (30MB) and application buffer (30MB) are hardcoded. Sufficient for current payloads but not configurable per-deployment. ## DataSource ### DS-1: GetAll returns raw byte[] for populate/merge **Status:** By design **Affects:** `AcSignalRDataSource.LoadDataSourceAsync` The `GetAll` path uses `IsRawBytesData = true` to receive raw `byte[]` from the protocol, then deserializes into the existing list via `PopulateMerge`. This avoids allocating a temporary `List` for merge. The extra copy (pipe → byte[]) is the trade-off. **Possible optimization:** Direct typed deserialization with merge support in the deserializer (PopulateMerge from `ReadOnlySequence`). Requires deserializer API changes. ## Client-side Setup & DI ### CONN-1: HubConnectionBuilder inner DI isolation **Status:** Workaround-in-place (dedicated options-passing overload) **Affects:** Consumer client setup in `Program.cs` (MAUI, WASM, ASP.NET Core server prerender) `HubConnectionBuilder.Services` is a separate `IServiceCollection` from the outer host DI. `services.Configure(...)` registered in the outer container does NOT flow into `HubConnectionBuilder.Services`. Calling `hubBuilder.AddAcBinaryProtocol()` with no args silently falls back to default options. **Known workaround:** Use the overload `AddAcBinaryProtocol(IHubConnectionBuilder, AcBinaryHubProtocolOptions, Action<...>? = null)` that accepts pre-resolved options explicitly. Canonical consumer pattern: ```csharp var protocolOpts = sp.GetRequiredService>().Value; hubBuilder.AddAcBinaryProtocol(protocolOpts); ``` ## Dispatch ### DISPATCH-1: First-call null response (observed) **Status:** Open — not diagnosed **Affects:** `PostDataAsync` awaiter / OnReceiveMessage → pending-request correlation Observed symptom: first `GetProductDtos_80`-style call returns null despite server serializing and sending a valid ~80KB chunked response. Second call (client-side retry) works normally. Log timeline: - Server: `Serialize end (chunked) dataBytes=80571 chunkCount=20` - Client: `Deserialize end (chunked)` — successful - Client: `OnReceiveMessage ... requestId=5` - Client: ~410ms later — `Client received null response. ... requestId=5` - Client: auto-retry (requestId=6) → full 338 items Hypothesis (unverified): `PostDataAsync` awaiter's null-mapping path misroutes the parsed result, or `requestId → Task` correlation has a race on the first response of a fresh connection. Client auto-retry hides the user-visible impact. **Related TODO:** `SIGNALR_TODO.md#todo-01` ## Cross-cutting (also tracked in serializer-side docs) ### XCUT-1: JSON-in-Binary request parameters — cross-ref Same tech debt as `../../AyCode.Core/docs/BINARY_ISSUES.md#xcut-1`. Planned replacement: migrate client→server request parameters from JSON-in-Binary envelope to direct Binary serialization. Coordinated change across all consuming projects.