feat(kpi): K11 — KpiHistoryQueryService (scoped read + bucketing)

This commit is contained in:
Joseph Doherty
2026-06-17 20:21:17 -04:00
parent e14433cd64
commit f0177d5073
5 changed files with 341 additions and 0 deletions
@@ -1,10 +1,12 @@
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using ZB.MOM.WW.ScadaBridge.CentralUI.Auth;
using ZB.MOM.WW.ScadaBridge.CentralUI.Components.Shared;
using ZB.MOM.WW.ScadaBridge.CentralUI.ScriptAnalysis;
using ZB.MOM.WW.ScadaBridge.CentralUI.Services;
using ZB.MOM.WW.ScadaBridge.HealthMonitoring;
using ZB.MOM.WW.ScadaBridge.KpiHistory;
namespace ZB.MOM.WW.ScadaBridge.CentralUI;
@@ -51,6 +53,19 @@ public static class ServiceCollectionExtensions
// Backs the Audit Log page's Export button via GET /api/centralui/audit/export.
services.AddScoped<IAuditLogExportService, AuditLogExportService>();
// KPI History (M6, K11): CentralUI facade over IKpiHistoryRepository that
// fetches a raw series and reduces it with KpiSeriesBucketer for the trend chart.
//
// Registered with an explicit factory so the IServiceScopeFactory ctor is
// always chosen — KpiHistoryQueryService has a second (test-seam) ctor that
// takes IKpiHistoryRepository directly, and both are constructor-resolvable,
// so default activation would be ambiguous. The scope-factory ctor opens a
// fresh DbContext per query, mirroring AuditLogQueryService so a chart's
// auto-load never races other reads on the shared circuit-scoped context.
services.AddScoped<IKpiHistoryQueryService>(sp => new KpiHistoryQueryService(
sp.GetRequiredService<IServiceScopeFactory>(),
sp.GetRequiredService<IOptions<KpiHistoryOptions>>()));
// OPC UA Tag Browser (Task 14): facade over CommunicationService.BrowseNodeAsync
// that enforces the CentralUI-side Design-role trust boundary and translates
// transport failures into typed BrowseFailure results for the dialog.