Skip to content

Commit f7d56a0

Browse files
committed
Add get quote sse endpouint
1 parent e885358 commit f7d56a0

4 files changed

Lines changed: 77 additions & 40 deletions

File tree

TrainStation/Endpoints/StationEndpoints.cs

Lines changed: 67 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using Microsoft.AspNetCore.Mvc;
2+
using System.Text;
23
using Train.Station.API.Models;
34
using Train.Station.API.Services;
45
using Train.Station.Client;
@@ -17,8 +18,8 @@ public static RouteGroupBuilder MapEndpoints(this RouteGroupBuilder group)
1718
group.MapGet("/routes", GetAllRoutesAsync)
1819
.Produces<IEnumerable<RouteDto>>();
1920

20-
//group.MapGet("/quote", GetQuoteAsync)
21-
// .Produces<ApiResponseQuoteDto>();
21+
group.MapGet("/quote-sse", GetQuoteAsync)
22+
.Produces(statusCode: 200, contentType: "text/event-stream");
2223

2324
//group.MapGet("/{solver}/swaps", GetAllSwapsAsync)
2425
// .Produces<ApiResponseSwapDto>();
@@ -103,34 +104,68 @@ private static async Task<IResult> GetAllRoutesAsync(
103104
return Results.Ok(routes);
104105
}
105106

106-
//private static async Task<IResult> GetQuoteAsync(
107-
// IRouteService routeService,
108-
// HttpContext httpContext,
109-
// [AsParameters] GetQuoteQueryParams queryParams)
110-
//{
111-
// var quoteRequest = new QuoteRequest
112-
// {
113-
// SourceNetwork = queryParams.SourceNetwork!,
114-
// SourceToken = queryParams.SourceToken!,
115-
// DestinationNetwork = queryParams.DestinationNetwork!,
116-
// DestinationToken = queryParams.DestinationToken!,
117-
// Amount = queryParams.Amount!.Value,
118-
// };
119-
120-
// var quote = await routeService.GetValidatedQuoteAsync(quoteRequest);
121-
122-
// if (quote == null)
123-
// {
124-
// return Results.NotFound(new ApiResponse()
125-
// {
126-
// Error = new ApiError()
127-
// {
128-
// Code = "QUOTE_NOT_FOUND",
129-
// Message = "Quote not found",
130-
// }
131-
// });
132-
// }
133-
134-
// return Results.Ok(new ApiResponseQuoteDto { Data = quote });
135-
//}
107+
private static async Task GetQuoteAsync(
108+
HttpContext httpContext,
109+
RouteCache routeCache,
110+
SolverCache solverCache,
111+
IHttpClientFactory httpClientFactory,
112+
[FromQuery] string sourceNetwork,
113+
[FromQuery] string sourceToken,
114+
[FromQuery] string destinationNetwork,
115+
[FromQuery] string destinationToken,
116+
[FromQuery] double amount)
117+
{
118+
httpContext.Response.Headers.ContentType = "text/event-stream";
119+
120+
var lps = routeCache.GetLpsByRoute(
121+
sourceNetwork,
122+
sourceToken,
123+
destinationNetwork,
124+
destinationToken);
125+
126+
var cancellationToken = httpContext.RequestAborted;
127+
128+
foreach (var lpName in lps)
129+
{
130+
if (cancellationToken.IsCancellationRequested)
131+
{
132+
break;
133+
}
134+
135+
try
136+
{
137+
var solverInfo = solverCache.GetAll()[lpName];
138+
var httpClient = httpClientFactory.CreateClient(lpName);
139+
140+
var trainSilverClient = new TrainSolverApiClient(
141+
solverInfo.Url.ToString(), httpClient);
142+
143+
var quote = await trainSilverClient.QuoteAsync(
144+
amount,
145+
sourceNetwork,
146+
sourceToken,
147+
destinationNetwork,
148+
destinationToken);
149+
150+
var message = new
151+
{
152+
Provider = lpName,
153+
Quote = quote.Data
154+
};
155+
156+
var json = System.Text.Json.JsonSerializer.Serialize(message);
157+
158+
await httpContext.Response.WriteAsync($"data: {json}\n\n");
159+
await httpContext.Response.Body.FlushAsync();
160+
161+
}
162+
catch
163+
{
164+
}
165+
}
166+
167+
168+
169+
await httpContext.Response.Body.FlushAsync();
170+
}
136171
}

TrainStation/Program.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@
6767

6868
var app = builder.Build();
6969

70+
app.UseRateLimiter();
71+
app.UseCors();
72+
7073
app.MapGroup("/api")
7174
.MapGet("/health", () => Results.Ok())
7275
.WithTags("System")
@@ -85,7 +88,5 @@
8588
c.DisplayRequestDuration();
8689
});
8790

88-
app.UseRateLimiter();
89-
app.UseCors();
9091

9192
await app.RunAsync();

TrainStation/Services/RoutePollingService.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
1515
{
1616
try
1717
{
18-
var name = lp.Name;
19-
var baseAddress = lp.Url.ToString();
18+
var name = lp.Key;
19+
var baseAddress = lp.Value.Url.ToString();
2020

2121
var trainSilverClient = new TrainSolverApiClient(
2222
baseAddress,

TrainStation/Services/SolverCache.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
using System.Text.Json;
1+
using System.Collections.Concurrent;
2+
using System.Text.Json;
23
using Train.Station.API.Models;
34

45
namespace Train.Station.API.Services;
56

67
public class SolverCache
78
{
8-
private readonly List<Solver> _solvers;
9+
private readonly Dictionary<string, Solver> _solvers;
910

1011
public SolverCache(IWebHostEnvironment env)
1112
{
@@ -19,8 +20,8 @@ public SolverCache(IWebHostEnvironment env)
1920
_solvers = JsonSerializer.Deserialize<List<Solver>>(json, new JsonSerializerOptions
2021
{
2122
PropertyNameCaseInsensitive = true
22-
}) ?? new List<Solver>();
23+
}).ToDictionary(x=> x.Name) ?? new ();
2324
}
2425

25-
public IReadOnlyList<Solver> GetAll() => _solvers;
26+
public IReadOnlyDictionary<string, Solver> GetAll() => _solvers;
2627
}

0 commit comments

Comments
 (0)