159 lines
4.5 KiB
C#
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; }
|
|
}
|
|
}
|