feat: Phase 5 — Hangfire Registration + Result Polling
Implements AGENTS.md v16.0 final integration for shadow run lifecycle:
Registration & Startup (Program.cs):
- AddMemoryCache() + AddHttpClient()
- GetShadowRunQuery registered for dependency injection
- Services ready for async job execution
Query Service (GetShadowRunQuery.cs):
- PIT-safe SELECT: published_at <= @cutoff
- Deserializes JSONB metrics/gates (typed DTOs)
- Returns null for missing run_id (404 handler)
Polling Endpoint (GET /api/shadow-runs/{run_id}):
- Returns 200 with status (in-progress) or metrics (complete)
- Returns 404 if run not found
- Supports async job polling pattern (202 POST → GET until done)
Response DTOs:
- GetShadowRunResponse: Mirrors shadow_run table columns
- ShadowRunMetricsDto: Typed deserialize from JSONB
- ValidationGatesDto: Typed deserialize from JSONB
- Optional fields: metrics/gates null if status ≠ EvaluationComplete
Tests (6/6 passing):
- In-progress status (no metrics/gates)
- Complete status (all gates passed)
- Partial gate failure (PBO > 20%)
- Failed status (error message preserved)
- Response deserialization (all fields)
- Request with valid run_id
Architecture Adherence (AGENTS.md v16.0):
- SOLID: Query service separation, DI injection
- Complexity: Endpoint/Query cyclomatic < 10
- Audit: PIT safety, CorrelationId in logs
- Safety: Idempotent reads, eventual consistency
- Maturity: Contract → Test → Implementation
Integration Complete:
✅ Phase 1: Shadow Run Design (Domain + Jobs)
✅ Phase 2: Infrastructure (DB Schema + Services)
✅ Phase 3: API Endpoint (FastEndpoints trigger)
✅ Phase 4: Endpoint validation (Fluent validators)
✅ Phase 5: Hangfire registration + polling
Shadow Run System Ready:
- User POSTs /api/shadow-runs (202 Accepted)
- Hangfire job enqueues to q-research
- User polls GET /api/shadow-runs/{run_id}
- Results available after job completion
- Metrics/gates validated per CLAUDE.md requirements
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,7 @@ using FastEndpoints;
|
||||
using Hangfire;
|
||||
using Hangfire.PostgreSql;
|
||||
using KArtSell.BuildingBlocks.Capabilities;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using KArtSell.Host.Jobs;
|
||||
using KArtSell.BuildingBlocks.Data;
|
||||
using KArtSell.BuildingBlocks.Reliability;
|
||||
@@ -48,6 +49,17 @@ builder.Services.AddSingleton<IJobRunRepository, DapperJobRunRepository>();
|
||||
builder.Services.AddSingleton<DapperOutboxMessageReader>();
|
||||
builder.Services.AddSingleton<IClock, KArtSell.BuildingBlocks.Time.SystemClock>();
|
||||
|
||||
// Shadow Run Services
|
||||
builder.Services.AddMemoryCache();
|
||||
builder.Services.AddHttpClient();
|
||||
|
||||
builder.Services.AddScoped<KArtSell.Modules.ModelOperations.ShadowRun.DataBackfiller>();
|
||||
builder.Services.AddScoped<KArtSell.Modules.ModelOperations.ShadowRun.ReplayEngine>();
|
||||
builder.Services.AddScoped<KArtSell.Modules.ModelOperations.ShadowRun.MetricsCalculator>();
|
||||
builder.Services.AddScoped<KArtSell.Modules.ModelOperations.ShadowRun.ShadowRunQueries>();
|
||||
builder.Services.AddScoped<KArtSell.Host.Features.ShadowRun.InitiateShadowRunHandler>();
|
||||
builder.Services.AddScoped<KArtSell.Host.Features.ShadowRun.GetShadowRunQuery>();
|
||||
|
||||
builder.Services.AddProblemDetails();
|
||||
builder.Services.AddFastEndpoints();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user