# SignalR DataSource — TODO

Forward-looking work specific to `AcSignalRDataSource`. Transport-side TODOs live in `../SIGNALR/SIGNALR_TODO.md`.

## Priority legend
- **P0** blocker · **P1** important · **P2** nice-to-have · **P3** idea

---

## ACCORE-SIGDS-T-D9F2: Relocate AcSignalRDataSource + TrackingItemHelpers to AyCode.Services
**Priority:** P2 · **Type:** Architectural cleanup · **Status:** Open

Both files currently live in `AyCode.Services.Server/SignalRs/`, but **neither has any Server-only dependency**:

- `AcSignalRDataSource.cs` using statements: only `AyCode.Core.*` + `AyCode.Services.SignalRs` (client-side namespace) — zero `AyCode.*.Server` references.
- `TrackingItemHelpers.cs` using statements: only `System.Reflection` + `AyCode.Core.Extensions`.
- `AyCode.Services.csproj` reference graph already covers all transitive needs (AyCode.Core, AyCode.Entities, AyCode.Interfaces, AyCode.Models).
- `SignalRCrudTags` (the DataSource constructor's required argument type) lives in `AyCode.Services` — consumers must currently reference both `AyCode.Services` and `AyCode.Services.Server` for one logical API.
- All other files in `AyCode.Services.Server/SignalRs/` are genuinely Server-only (Hub<T> subclasses, session service, broadcast, server protocol extensions, server hub interfaces).

**Practical impact:** Blazor.WebAssembly cannot reference `AyCode.Services.Server` (its dependency graph pulls in `AyCode.Database`, `KeyDerivation`, `SendGrid` — none WASM-compatible). WASM consumers wanting `AcSignalRDataSource` are currently blocked.

### Acceptance
- [ ] `AcSignalRDataSource.cs` moved: `AyCode.Services.Server/SignalRs/` → `AyCode.Services/SignalRs/`; namespace `AyCode.Services.Server.SignalRs` → `AyCode.Services.SignalRs`.
- [ ] `TrackingItemHelpers.cs` moved + namespace updated.
- [ ] Consumer `using AyCode.Services.Server.SignalRs;` lines pulling these types updated to `using AyCode.Services.SignalRs;`.
- [ ] Doc folder relocated: `AyCode.Services.Server/docs/SIGNALR_DATASOURCE/` → `AyCode.Services/docs/SIGNALR_DATASOURCE/` (3 files: README + ISSUES + TODO).
- [ ] `TOPIC_CODES.md` SIGDS row "Docs location" updated (`AyCode.Services.Server/...` → `AyCode.Services/...`).
- [ ] Doc-index READMEs updated: remove SIGDS row from `Services.Server/docs/README.md`; add to `Services/docs/README.md`.
- [ ] All cross-refs in workspace updated (~15 paths across AyCode.Core + AyCode.Blazor) per the path-rewrite pattern used in LLMP-DEC-66.
- [ ] `AyCode.Services.Server/README.md` + `AyCode.Services.Server/SignalRs/README.md` doc tables: SIGDS rows removed.
- [ ] `AyCode.Services/SignalRs/README.md` doc table: DataSource entry added (currently no Data Source section there).
- [ ] Tests in `AyCode.Services.Server.Tests/SignalRs/SignalRDatasources/` re-evaluated — likely keep in Server.Tests (full hub environment) but update `using` statements; or split into `AyCode.Services.Tests/SignalRs/SignalRDatasources/` if isolated.
- [ ] New `LLMP-DEC` entry filed (SIGDS phase 2 relocation, cross-references `LLMP-DEC-66`).
- [ ] Build green across all consumers (AyCode.Blazor.Components, FruitBankHybridApp, etc.); WASM build verified if applicable.

### Related
- `LLMP-DEC-66` (SIGDS topic introduction — this TODO completes the architectural side that the docs-side migration left open)
- Parallels `LLMP-DEC-58` Framework-First retightening principle (consumer-side code shouldn't live in Server-flavored projects)

---

## ACCORE-SIGDS-T-N5R8: ChangeTracking._trackingItems → Dictionary<TId, TrackingItem>
**Priority:** P3 · **Type:** Performance refactor · **Status:** Open

Pre-existing `//TODO: Dictionary... - J.` comment in `AcSignalRDataSource.cs:68`:

```csharp
private readonly List<TrackingItem<TDataItem, TId>> _trackingItems = [];
```

`ChangeTracking.FindIndex(newValue)` and `TryGetTrackingItem(id)` both linear-scan `_trackingItems`. For DataSources with many concurrent tracked changes (large grids with frequent edits), this is O(N) per operation. A `Dictionary<TId, TrackingItem<TDataItem, TId>>` would give O(1) lookup; `ToList()` enumeration (the only external read path) is order-agnostic, so no behavioural regression.

Trade-off: per-tracking-item dictionary overhead; negligible for typical workload.

**Acceptance:**
- `_trackingItems` switched to `Dictionary<TId, TrackingItem<TDataItem, TId>>`.
- `FindIndex` removed (caller paths in `AddTrackingItem` re-flow as TryGetValue + Add/Update).
- `TryGetTrackingItem` becomes single dict lookup.
- `ToList()` returns `_trackingItems.Values.ToList()`.
- `Remove(trackingItem)` → `Remove(trackingItem.CurrentValue.Id)`.
- All existing tests pass without change to public API surface.
