# SignalRs

Custom binary SignalR protocol, client infrastructure, message tagging, and serialization helpers.

> **Architecture:** For full dispatch flow, tag system, and tech debt documentation see `AyCode.Services/docs/SIGNALR/README.md`.
> **Binary protocol:** For wire format, zero-copy pipeline, and three-path read logic see `AyCode.Services/docs/SIGNALR_BINARY_PROTOCOL/README.md`.
> **Known issues:** `AyCode.Services/docs/SIGNALR/SIGNALR_ISSUES.md`

## Key Files

### Protocol
- **`AcBinaryHubProtocol.cs`** — Unsealed base `IHubProtocol` replacing JSON+Base64 with `AcBinarySerializer`. Handles all 9 SignalR message types. Write: `BufferWriterBinaryOutput` standalone + `AcBinarySerializer.Serialize(value, output)` zero-copy to pipe. `byte[]` fast-path writes tag+VarUInt+bytes via BWO. Read: `SequenceReader<byte>` from pipe's `ReadOnlySequence`. Three-path `ReadSingleArgument`: byte[] fast-path (0x44 tag), `IsRawBytesData` (raw byte[]), typed deser via `SignalDataType`. `_currentSignalParams` captures arg[2] for type-aware arg[3] deserialization.
- **`AyCodeBinaryHubProtocol.cs`** — Derived protocol (currently empty). Exists for registration and future project-specific hooks. Register this instead of `AcBinaryHubProtocol`.

### Client
- **`AcSignalRClientBase.cs`** — Abstract SignalR client managing `HubConnection`, request/response tracking via pooled `SignalRRequestModel`. `SendCoreAsync` builds `SignalParams` (with `IsRawBytesData` when `T == byte[]`). CRUD helpers (Post, Get, GetAll, GetAllInto). Configurable timeouts.
- **`IAcSignalRHubClient.cs`** — Client interface + `SignalResponseDataMessage` (sealed, `RawResponseData` is `object?` — typed object or byte[], `GetResponseData<T>()` safe `is T` cast — type-mismatch returns null, does **not** throw). Legacy message types (`IdMessage`, `SignalPostJsonDataMessage`) marked `[Obsolete]`.
- **`IAcSignalRHubBase.cs`** — Base hub interface: `OnReceiveMessage(int messageTag, int? requestId, SignalParams signalParams, object data)`.
- **`ISignalParams.cs`** — `ISignalParams` base interface + `SignalParams` (Status, DataSerializerType, Parameters `byte[]?`, SignalDataType `string?`, IsRawBytesData `bool`). Metadata travels as separate hub argument (AcBinary serialized). Parameters and data are independent — both nullable in any direction.

### Message Tagging
- **`SignalMessageTagAttribute.cs`** — Three attributes: `TagAttribute` (base, int messageTag), `SignalRAttribute` (server method routing + client notification), `SignalRSendToClientAttribute` (client-side receive).
- **`AcSignalRTags.cs`** — Static constants: `None`, `PingTag`, `EchoTag`; grid-layout roaming tags `GetGridLayoutTag` / `SaveGridLayoutTag` / `DeleteGridLayoutTag` (90010-12) — key-value layout storage contract (`key`, [`layoutJson`,] `userId`), implemented by consumer hubs.
- **`SignalRCrudTags.cs`** — Sealed class bundling 5 independent CRUD tag integers. `GetMessageTagByTrackingState()` maps `TrackingState` -> tag. See `AyCode.Services/docs/SIGNALR_DATASOURCE/README.md`.
- **`SendToClientType.cs`** — Enum: None, Others, Caller, All.

### Serialization & Pooling
- **`SignalRSerializationHelper.cs`** — Static helpers: `SerializeToBinary()`, `DeserializeFromBinary()`, compressed JSON variants.
- **`SignalRRequestModel.cs`** — Poolable (`IResettable`) request tracking model with `ObjectPool` for reuse.

### Data Source

> **Full specification:** `AyCode.Services/docs/SIGNALR_DATASOURCE/README.md`

- **`AcSignalRDataSource.cs`** — Abstract generic real-time collection (`AcSignalRDataSource<TDataItem, TId, TIList>`) implementing `IList<T>`, `IList`, `IReadOnlyList<T>`. Consumer of the transport above (not part of it) — wraps CRUD-tag communication behind a regular list. Transport-agnostic by design; the current implementation is SignalR-coupled.
  - **Change tracking:** `TrackingItem<T, TId>` wraps each modified item with `TrackingState` + `OriginalValue` (rollback snapshot). `ChangeTracking<T, TId>` manages the tracked list.
  - **Loading:** `LoadDataSource()` (sync-wait), `LoadDataSourceAsync()` (async callback), `LoadItem(id)` (single). Raw-`byte[]` path uses `AcBinaryDeserializer.PopulateMerge` into `IAcObservableCollection` (batch UI notification via `BeginUpdate`/`EndUpdate`); `SerializerType` selects Binary vs JSON+GZip.
  - **Saving:** `SaveChanges()` / `SaveChangesAsync()` iterate tracked items, post each via the state's CRUD tag, roll back on failure; `SaveItem()` for individual saves. `IsSyncing` + `OnSyncingStateChanged` expose sync state.
- **`TrackingItemHelpers.cs`** — `JsonClone` / `ReflectionClone` deep-clone helpers producing the `OriginalValue` rollback snapshots.
