Files
QuantEngineByItz/src/dotnet/QuantEngine.Web/Endpoints/CollectionEndpoints.cs
T

159 lines
4.5 KiB
C#

using QuantEngine.Core.Interfaces;
using QuantEngine.Application.Services;
namespace QuantEngine.Web.Endpoints;
public static class CollectionEndpoints
{
public static void MapCollectionEndpoints(this WebApplication app)
{
var group = app.MapGroup("/api/collection")
.WithName("Collection");
group.MapGet("/state", GetCollectionState)
.WithName("GetCollectionState")
.Produces(200)
.Produces(500);
group.MapGet("/runs", GetRecentRuns)
.WithName("GetRecentRuns")
.Produces(200)
.Produces(500);
group.MapGet("/runs/{runId}/snapshots", GetRunSnapshots)
.WithName("GetRunSnapshots")
.Produces(200)
.Produces(404)
.Produces(500);
group.MapGet("/runs/{runId}/errors", GetRunErrors)
.WithName("GetRunErrors")
.Produces(200)
.Produces(404)
.Produces(500);
group.MapGet("/latest/{ticker}", GetLatestSnapshotsForTicker)
.WithName("GetLatestSnapshotsForTicker")
.Produces(200)
.Produces(500);
group.MapPost("/run", StartCollectionRun)
.WithName("StartCollectionRun")
.Produces(202)
.Produces(500);
}
private static async Task<IResult> GetCollectionState(ICollectionRepository repo)
{
try
{
var state = await repo.GetDashboardStateAsync();
return Results.Ok(state);
}
catch
{
return Results.StatusCode(500);
}
}
private static async Task<IResult> GetRecentRuns(ICollectionRepository repo, int limit = 20)
{
try
{
var runs = await repo.GetRecentRunsAsync(limit);
return Results.Ok(new { runs, count = runs.Count });
}
catch
{
return Results.StatusCode(500);
}
}
private static async Task<IResult> GetRunSnapshots(string runId, ICollectionRepository repo)
{
try
{
var snapshots = await repo.GetRunSnapshotsAsync(runId);
return Results.Ok(new { runId, snapshots, count = snapshots.Count });
}
catch
{
return Results.StatusCode(500);
}
}
private static async Task<IResult> GetRunErrors(string runId, ICollectionRepository repo, int limit = 50)
{
try
{
var errors = await repo.GetRunErrorsAsync(runId, limit);
return Results.Ok(new { runId, errors, count = errors.Count });
}
catch
{
return Results.StatusCode(500);
}
}
private static async Task<IResult> GetLatestSnapshotsForTicker(string ticker, ICollectionRepository repo, int limit = 10)
{
try
{
var snapshots = await repo.GetLatestSnapshotsForTickerAsync(ticker, limit);
return Results.Ok(new { ticker, snapshots, count = snapshots.Count });
}
catch
{
return Results.StatusCode(500);
}
}
private static async Task<IResult> StartCollectionRun(
DataCollectionService collectionService,
HttpRequest request,
ILogger<Program> logger)
{
try
{
var runId = Guid.NewGuid().ToString("N");
var now = DateTime.UtcNow.ToString("o");
var body = await request.ReadFromJsonAsync<CollectionRunRequest>();
var account = body?.Account ?? "real";
var tickers = body?.Tickers ?? new List<string> { "005930", "000660" };
// Trigger async collection (fire-and-forget)
_ = Task.Run(async () =>
{
try
{
await collectionService.RunCollectionAsync(runId, account, tickers);
}
catch (Exception ex)
{
logger.LogError(ex, "Collection run {RunId} failed", runId);
}
});
return Results.Accepted($"/api/collection/runs/{runId}", new
{
runId,
status = "running",
startedAt = now,
tickerCount = tickers.Count
});
}
catch (Exception ex)
{
logger.LogError(ex, "Failed to start collection run");
return Results.StatusCode(500);
}
}
private class CollectionRunRequest
{
public string? Account { get; set; }
public List<string>? Tickers { get; set; }
}
}