# SignalR — Known Issues & Limitations

## Protocol

### ACCORE-SIG-I-R4W7: Server-side IsRawBytesData pre-serialize

**Status:** Open
**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.

### ACCORE-SIG-I-L5K3: Parameter serialization is per-parameter

**Status:** Open
**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.

### ACCORE-SIG-I-H8D6: Parameter serialization is AcBinary only

**Status:** Open
**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

### ACCORE-SIG-I-P1J4: BufferWriterChunkSize defaults to 64KB for SignalR

**Status:** Closed (2026-04-25, retroactive — was `Status: DONE` pre-LLMP-DEC-44 vocabulary normalization)
**Affects:** `AcBinaryHubProtocol` constructor, write path

The framework's `BufferWriterChunkSize` default was 64KB, suboptimal for SignalR chunked responses (misaligned with Kestrel slab size, higher latency-to-first-byte).

### Resolution
- **What:** Set `BufferWriterChunkSize = 4096` explicitly in `AcBinaryHubProtocol` constructor.
- **Where:** `AcBinaryHubProtocol` constructor (override applied at construction time).
- **Why:** Aligned with Kestrel's slab allocation size; reduces latency-to-first-byte for chunked SignalR responses.
- **Scope:** Override is SignalR-specific. Non-SignalR paths keep the 64KB default — this is intentional and stable behaviour now.
- **Date:** Code change predates this status update; the entry was already `Status: DONE` before the LLMP-DEC-44 vocabulary normalization. The current update only formalizes it as `Closed` per the new 3-value convention.

### ACCORE-SIG-I-N3V8: WebSocket buffer sizes are hardcoded

**Status:** Open
**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

### ACCORE-SIG-I-T7S2: GetAll returns raw byte[] for populate/merge

**Status:** Open
**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<T>` 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<byte>`). Requires deserializer API changes.

## Server-side Setup & DI

### ACCORE-SIG-I-B5G9: Server-side NopCommerce plugin AcBinaryHubProtocolOptions not bound from appsettings

**Status:** Open · **Severity:** Minor (works, but hardcoded + bypasses DI logger) · **Area:** Consumer adoption gap in `Nop.Plugin.Misc.AIPlugin/Infrastructure/PluginNopStartup.cs`

The framework overload chain is complete on the server side — `AcSignalRProtocolExtensions.BuildProtocol` already resolves `IOptions<AcBinaryHubProtocolOptions>` from DI and falls back to defaults otherwise. The consumer plugin does NOT use it:

Current `PluginNopStartup.ConfigureServices`:
```csharp
.AddAcBinaryProtocol(opts =>
{
    opts.ProtocolMode = BinaryProtocolMode.AsyncSegment;      // ← HARDCODED
    opts.Logger = new Logger(nameof(AyCodeBinaryHubProtocol)); // ← BYPASSES ILogger<T> DI
});
```

What's missing:
- No `services.Configure<AcBinaryHubProtocolOptions>(configuration.GetSection("AyCode:SignalR:Protocol"))` → `ProtocolMode`, `BufferSize`, `FlushPolicy`, `FlushTimeout` are all hardcoded / default.
- The `appsettings.json` has no `AyCode:SignalR` (or equivalent) section at all — so per-deploy tuning (e.g. increasing `FlushTimeout` for a satellite link, switching `ProtocolMode` for diagnostics) requires a code change + redeploy.
- Manual `new Logger(...)` sidesteps the DI `ILogger<AcBinaryHubProtocol>` auto-resolution that `BuildProtocol` provides → creates a parallel logger instance (see `../../../AyCode.Core/docs/LOGGING/LOGGING_ISSUES.md#accore-log-i-m4c9`).

### Fix direction
See `SIGNALR_TODO.md#accore-sig-t-m5l6`.

### Related
- `../../../AyCode.Core/docs/LOGGING/LOGGING_ISSUES.md#accore-log-i-m4c9` (sibling gap — same plugin, logger setup)
- `ACCORE-SIG-I-K6F1` (client-side equivalent — `HubConnectionBuilder.Services` inner DI isolation forces a different workaround)
- Plugin doc drift: `Nop.Plugin.Misc.AIPlugin/docs/SIGNALR/README.md:22` documents `services.AddSingleton<IHubProtocol>(new AcBinaryHubProtocol())` — the actual code uses `.AddAcBinaryProtocol(opts => {...})`. **Resolved 2026-07-13** — plugin-README rewritten (AddAcBinaryProtocol; json+acbinary side-by-side registration; hub list corrected).

## Client-side Setup & DI

### ACCORE-SIG-I-K6F1: HubConnectionBuilder inner DI isolation

**Status:** Open
**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<AcBinaryHubProtocolOptions>(...)` 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<IOptions<AcBinaryHubProtocolOptions>>().Value;
hubBuilder.AddAcBinaryProtocol(protocolOpts);
```

## Dispatch

### ACCORE-SIG-I-X4M7: First-call null response (observed)

**Status:** Open
**Affects:** `PostDataAsync<T>` 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<T>` awaiter's null-mapping path misroutes the parsed result, or `requestId → Task<T>` 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#accore-sig-t-j2p5`

## Cross-cutting (canonical home: `AyCode.Core` repo's `docs/XCUT/`)

### ACCORE-XCUT-I-X8Q1: JSON-in-Binary request parameters — cross-ref

**Status:** Closed (2026-04-26, see canonical entry).

Canonical entry: **`../../../AyCode.Core/docs/XCUT/XCUT_ISSUES.md#accore-xcut-i-x8q1`**. Summary: SignalR transport previously carried `SignalPostJsonDataMessage<T>` (JSON inside a Binary envelope) for request params, while response path was pure Binary. Replacement landed in commits `cdd54d3` + `3b70070`: `SignalParams` (length-prefixed binary pack/unpack) replaces the JSON envelope, coordinated across BINARY serializer + SIGNALR transport + consumer projects. **Breaking change** for older clients.
