feat: add quant engine WBS verification harness
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
using FastEndpoints;
|
||||
using Hangfire;
|
||||
using QuantEngine.Application.Interfaces;
|
||||
using QuantEngine.Core.Interfaces;
|
||||
|
||||
namespace QuantEngine.Web.Endpoints;
|
||||
@@ -214,20 +216,52 @@ public class GetLatestSnapshotsEndpoint : Endpoint<GetLatestSnapshotsRequest, Ge
|
||||
}
|
||||
}
|
||||
|
||||
public class StartCollectionRunEndpoint : EndpointWithoutRequest
|
||||
public class StartCollectionRunResponse
|
||||
{
|
||||
public string RunId { get; set; } = "";
|
||||
}
|
||||
|
||||
public class StartCollectionRunEndpoint : EndpointWithoutRequest<StartCollectionRunResponse>
|
||||
{
|
||||
private readonly IBackgroundJobClient _jobClient;
|
||||
private readonly IConfiguration _configuration;
|
||||
private readonly ILogger<StartCollectionRunEndpoint> _logger;
|
||||
|
||||
public StartCollectionRunEndpoint(
|
||||
IBackgroundJobClient jobClient,
|
||||
IConfiguration configuration,
|
||||
ILogger<StartCollectionRunEndpoint> logger)
|
||||
{
|
||||
_jobClient = jobClient;
|
||||
_configuration = configuration;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public override void Configure()
|
||||
{
|
||||
Post("/api/collection/run");
|
||||
AllowAnonymous();
|
||||
Description(d => d
|
||||
.Produces(202)
|
||||
.Produces<StartCollectionRunResponse>(202)
|
||||
.Produces(500));
|
||||
}
|
||||
|
||||
public override async Task HandleAsync(CancellationToken ct)
|
||||
{
|
||||
// Return 202 Accepted status code via generic status code handler
|
||||
await SendResultAsync(Microsoft.AspNetCore.Http.Results.Accepted());
|
||||
try
|
||||
{
|
||||
var runId = $"api-{DateTime.Now:yyyyMMdd-HHmmss}";
|
||||
var accountMode = _configuration["Kis:AccountMode"] ?? "mock";
|
||||
var tickers = new[] { "005930", "000660", "051910", "005380", "010140", "005490" }.ToList();
|
||||
|
||||
_jobClient.Enqueue<ICollectionOrchestrator>(o => o.RunCollectionAsync(runId, accountMode, tickers));
|
||||
|
||||
_logger.LogInformation("Collection run {RunId} enqueued", runId);
|
||||
|
||||
await SendAsync(new StartCollectionRunResponse { RunId = runId }, 202, ct);
|
||||
}
|
||||
catch
|
||||
{
|
||||
await SendErrorsAsync(500, ct);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,6 +102,11 @@ try
|
||||
builder.Services.AddScoped<ITokenCache, PostgresTokenCache>();
|
||||
builder.Services.AddHttpClient<IKisApiClient, KisApiClient>();
|
||||
|
||||
// Collection Pipeline Services
|
||||
builder.Services.AddScoped<SourcePriorityResolver>();
|
||||
builder.Services.AddScoped<PriceDataNormalizer>();
|
||||
builder.Services.AddScoped<ICollectionOrchestrator, KisDataCollectionOrchestrator>();
|
||||
|
||||
// Hangfire Background Jobs
|
||||
try
|
||||
{
|
||||
|
||||
@@ -5,7 +5,9 @@ using Hangfire.PostgreSql;
|
||||
using Hangfire.MemoryStorage;
|
||||
using System.Linq.Expressions;
|
||||
using QuantEngine.Application.Services;
|
||||
using QuantEngine.Application.Interfaces;
|
||||
using QuantEngine.Infrastructure.Data;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace QuantEngine.Web.Services;
|
||||
|
||||
@@ -17,15 +19,21 @@ public class SchedulerService
|
||||
private readonly ILogger<SchedulerService> _logger;
|
||||
private readonly IBackgroundJobClient _jobClient;
|
||||
private readonly IRecurringJobManager _recurringJobManager;
|
||||
private readonly IServiceScopeFactory _scopeFactory;
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
public SchedulerService(
|
||||
ILogger<SchedulerService> logger,
|
||||
IBackgroundJobClient jobClient,
|
||||
IRecurringJobManager recurringJobManager)
|
||||
IRecurringJobManager recurringJobManager,
|
||||
IServiceScopeFactory scopeFactory,
|
||||
IConfiguration configuration)
|
||||
{
|
||||
_logger = logger;
|
||||
_jobClient = jobClient;
|
||||
_recurringJobManager = recurringJobManager;
|
||||
_scopeFactory = scopeFactory;
|
||||
_configuration = configuration;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -89,14 +97,22 @@ public class SchedulerService
|
||||
// List of tickers to collect
|
||||
var tickers = new[] { "005930", "000660", "051910", "005380", "010140", "005490" };
|
||||
|
||||
foreach (var ticker in tickers)
|
||||
{
|
||||
// Simulate data collection
|
||||
await Task.Delay(100);
|
||||
_logger.LogInformation("Collected data for ticker: {Ticker}", ticker);
|
||||
}
|
||||
// Create scope for scoped services
|
||||
using var scope = _scopeFactory.CreateScope();
|
||||
var orchestrator = scope.ServiceProvider.GetRequiredService<ICollectionOrchestrator>();
|
||||
|
||||
_logger.LogInformation("Daily data collection completed at {Time}", DateTime.Now);
|
||||
// Build runId with timestamp
|
||||
var runId = $"daily-{DateTime.Now:yyyyMMdd-HHmmss}";
|
||||
|
||||
// Read account mode from configuration (default to "mock")
|
||||
var accountMode = _configuration["Kis:AccountMode"] ?? "mock";
|
||||
|
||||
// Execute collection
|
||||
var result = await orchestrator.RunCollectionAsync(runId, accountMode, tickers.ToList());
|
||||
|
||||
// Log completion
|
||||
_logger.LogInformation("Collection run {RunId} completed: {Snapshots} snapshots, {Errors} errors",
|
||||
runId, result.SuccessCount, result.ErrorCount);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user