[Backend][Metrics] SpikerSoft.Business.Metrics is inert — IInfluxMetricsService has no consumer, metric models are duplicated, namespace doesn't match the project, and InfluxDashboard re-implements the aggregation #577

Closed
opened 2026-07-14 17:20:10 +00:00 by spikerj · 2 comments
Owner

QA Team — filed 2026-07-14 from the README audit, at spikerj's direction (decision: ticket a consolidation).

Four findings in one slice, all verified by grep across non-obj sources:

  1. IInfluxMetricsService / InfluxMetricsService has NO runtime consumer. It exists, it compiles, nothing calls it. The InfluxDashboardHostedService (the one service that would want it) does its own storage aggregation inline instead.
  2. Duplicate model sets: SpikerSoft.Business.Services.InfluxDB.Models.{CpuMetric, AggregatedCpuMetrics} exist in both this project and SpikerSoft.Business — two definitions, no single source of truth.
  3. Namespace/project mismatch: the code is under SpikerSoft.Business.Services.InfluxDB in a project named SpikerSoft.Business.Metrics (a decomposition artifact — the namespace was kept for consumer compatibility, but there are no consumers to keep compatible).
  4. The aggregation lives in the wrong place: storage aggregation is implemented in InfluxDashboardHostedService even though the service's own options already carry Storage* fields — the abstraction was built and then bypassed.

Ask: pick one model set and delete the other; make InfluxDashboardHostedService consume IInfluxMetricsService (moving the aggregation into it) or delete the service outright if the worker is genuinely the right home; align the namespace with the project name while the blast radius is zero.

Related: #566 (the wider Business decomposition — this is one of its slices), #571 (the dashboard's Hostnames config misses dreamstream7 — same worker).

**QA Team** — filed 2026-07-14 from the README audit, at spikerj's direction (decision: ticket a consolidation). **Four findings in one slice, all verified by grep across non-obj sources:** 1. **`IInfluxMetricsService` / `InfluxMetricsService` has NO runtime consumer.** It exists, it compiles, nothing calls it. The `InfluxDashboardHostedService` (the one service that *would* want it) does its own storage aggregation inline instead. 2. **Duplicate model sets:** `SpikerSoft.Business.Services.InfluxDB.Models.{CpuMetric, AggregatedCpuMetrics}` exist in **both** this project and `SpikerSoft.Business` — two definitions, no single source of truth. 3. **Namespace/project mismatch:** the code is under `SpikerSoft.Business.Services.InfluxDB` in a project named `SpikerSoft.Business.Metrics` (a decomposition artifact — the namespace was kept for consumer compatibility, but there are no consumers to keep compatible). 4. **The aggregation lives in the wrong place:** storage aggregation is implemented in `InfluxDashboardHostedService` even though the service's own options already carry `Storage*` fields — the abstraction was built and then bypassed. **Ask:** pick one model set and delete the other; make `InfluxDashboardHostedService` consume `IInfluxMetricsService` (moving the aggregation into it) or delete the service outright if the worker is genuinely the right home; align the namespace with the project name while the blast radius is zero. **Related:** #566 (the wider Business decomposition — this is one of its slices), #571 (the dashboard's Hostnames config misses dreamstream7 — same worker).
Author
Owner

Fix up in spikersoft-backend PR #295 (open, awaiting merge).

Heads up: this ticket's second option would have been a regression. #577 offered "make InfluxDashboardHostedService consume IInfluxMetricsService (moving the aggregation into it)". I read the dead implementation before choosing, and InfluxMetricsService.AggregateMetricsByHost isn't just unused — it's wrong. It groups every metric by field into CpuValues (so RAM bytes and storage bytes land next to CPU percentages), averages all of them into AverageCpu, and computes no RAM/storage aggregation at all. The worker's live implementation already splits by measurement and derives utilisation correctly, and its existing InfluxStorageAggregationTests already prove it. Promoting the dead copy would have swapped correct code for broken code — so it's deleted, not promoted.

Done:

  • deleted SpikerSoft.Business.Metrics outright (the unregistered IInfluxMetricsService, the duplicate CpuMetric/AggregatedCpuMetrics shadowing SpikerSoft.Data.Models.Influx, the mismatched namespace); dropped from the solution and every ProjectReference
  • moved its one live type, InfluxDashboardOptions, into the worker that consumes it
  • deleted WindowPeriod and TimeRangeStart — their only consumer was the deleted service, so they were inert knobs that bound cleanly and steered nothing (the query path hardcodes range(start: -30s)). The worker README already said to ignore both "until #577".
  • removed the dangling COPY of the deleted csproj from 4 Dockerfiles. Worth knowing: that break would have surfaced only in CI's Docker build, never in dotnet build.

Two guards, both verified to actually fail when the defect is reintroduced: MetricModelsHaveOneSourceOfTruthTests (a duplicate type doesn't break the build — you just silently get the wrong one) and TheDeadTimeWindowKnobs_AreNotBack. Full sweep: 8,419 tests, 0 failures.

Leaving this open until #295 merges.

Two follow-ups filed separately — the three repository methods this orphans, and a committed InfluxDB token I found in SpikerSoft.Api/appsettings.json.

Fix up in spikersoft-backend PR #295 (open, awaiting merge). **Heads up: this ticket's second option would have been a regression.** #577 offered *"make `InfluxDashboardHostedService` consume `IInfluxMetricsService` (moving the aggregation into it)"*. I read the dead implementation before choosing, and `InfluxMetricsService.AggregateMetricsByHost` isn't just unused — it's **wrong**. It groups *every* metric by field into `CpuValues` (so RAM bytes and storage bytes land next to CPU percentages), averages all of them into `AverageCpu`, and computes no RAM/storage aggregation at all. The worker's live implementation already splits by measurement and derives utilisation correctly, and its existing `InfluxStorageAggregationTests` already prove it. Promoting the dead copy would have swapped correct code for broken code — so it's deleted, not promoted. **Done:** - deleted `SpikerSoft.Business.Metrics` outright (the unregistered `IInfluxMetricsService`, the duplicate `CpuMetric`/`AggregatedCpuMetrics` shadowing `SpikerSoft.Data.Models.Influx`, the mismatched namespace); dropped from the solution and every `ProjectReference` - moved its one live type, `InfluxDashboardOptions`, into the worker that consumes it - deleted `WindowPeriod` and `TimeRangeStart` — their only consumer was the deleted service, so they were inert knobs that bound cleanly and steered nothing (the query path hardcodes `range(start: -30s)`). The worker README already said to ignore both "until #577". - removed the dangling `COPY` of the deleted csproj from 4 Dockerfiles. Worth knowing: that break would have surfaced **only in CI's Docker build**, never in `dotnet build`. **Two guards, both verified to actually fail when the defect is reintroduced:** `MetricModelsHaveOneSourceOfTruthTests` (a duplicate type doesn't break the build — you just silently get the wrong one) and `TheDeadTimeWindowKnobs_AreNotBack`. Full sweep: 8,419 tests, 0 failures. Leaving this open until #295 merges. **Two follow-ups filed separately** — the three repository methods this orphans, and a committed InfluxDB token I found in `SpikerSoft.Api/appsettings.json`.
Author
Owner

PR #295 merged to master. Closing.

SpikerSoft.Business.Metrics is gone, InfluxDashboardOptions lives in the worker that consumes it, and the two dead options (WindowPeriod, TimeRangeStart) are removed. Both guards are in place and were verified to fail when their defect is reintroduced.

Follow-ups tracked separately: #601 (the three repository methods this orphaned) and #600 (the committed InfluxDB token found in SpikerSoft.Api/appsettings.json — needs rotation, not just deletion).

PR #295 merged to `master`. Closing. `SpikerSoft.Business.Metrics` is gone, `InfluxDashboardOptions` lives in the worker that consumes it, and the two dead options (`WindowPeriod`, `TimeRangeStart`) are removed. Both guards are in place and were verified to fail when their defect is reintroduced. Follow-ups tracked separately: #601 (the three repository methods this orphaned) and #600 (the committed InfluxDB token found in `SpikerSoft.Api/appsettings.json` — needs rotation, not just deletion).
Sign in to join this conversation.