using Microsoft.AspNetCore.Server.Kestrel.Core; using NemAnBlazor.Services.Interfaces; using NemAnBlazor.Services; using ProtoBuf.Grpc.Server; using SpotifyService.Services; using GrpcShared.Interfaces; using Polly; using Polly.Extensions.Http; var builder = WebApplication.CreateBuilder(args); #if DEBUG /* builder.WebHost.ConfigureKestrel(options => { options.ListenLocalhost(5050, o => o.Protocols = HttpProtocols.Http2); options.ListenLocalhost(5051, o => o.Protocols = HttpProtocols.Http1AndHttp2); }); */ #endif // Add services to the container. builder.Services.AddHttpClient("HttpClient", c => { c.BaseAddress = new Uri(SpotifyService.GLOBALS.SPOTIFYURL); c.DefaultRequestHeaders.Add("Accept", SpotifyService.GLOBALS.MEDIATYPE); }) .SetHandlerLifetime(TimeSpan.FromMinutes(5)) .AddPolicyHandler(GetRetryPolicy()) .AddPolicyHandler(GetCircuitBreaker()) .AddPolicyHandler(GetBulkheadPolicy(50,200)); IAsyncPolicy GetBulkheadPolicy(int capacity, int queueLength) { //As soon as we hit 50 concurrent requests, the policy will add subsequent requests to the pending request queue. //Once the pending request queue is full, then the policy will start rejecting any other calls to the service. return Policy.BulkheadAsync(capacity, queueLength); } IAsyncPolicy GetCircuitBreaker() { return HttpPolicyExtensions .HandleTransientHttpError() //the circuit will be cut if 25% of requests fail in a 60 second window, with a minimum of 7 requests in the 60 second window, //then the circuit should be cut for 30 seconds: .AdvancedCircuitBreakerAsync(0.25, TimeSpan.FromSeconds(60), 7, TimeSpan.FromSeconds(30), OnBreak, OnReset, OnHalfOpen); } void OnHalfOpen() { Console.WriteLine("Circuit in test mode, one request will be allowed."); } void OnReset() { Console.WriteLine("Circuit closed, requests flow normally."); } void OnBreak(DelegateResult result, TimeSpan ts) { Console.WriteLine("Circuit cut, requests will not flow."); } IAsyncPolicy GetRetryPolicy() { return HttpPolicyExtensions // HttpRequestException, 5XX and 408 .HandleTransientHttpError() // 404 .OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound) // Retry two times after delay .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(3, retryAttempt))); } builder.Services.AddControllersWithViews(); builder.Services.AddRazorPages(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); builder.Services.AddGrpc(); builder.Services.AddCodeFirstGrpc(); builder.Services.AddCodeFirstGrpcReflection(); var app = builder.Build(); app.UseSwagger(); app.UseSwaggerUI(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseWebAssemblyDebugging(); } else { app.UseExceptionHandler("/Error"); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } app.UseHttpsRedirection(); app.UseBlazorFrameworkFiles(); app.UseStaticFiles(); app.UseRouting(); app.UseGrpcWeb(); app.MapRazorPages(); app.MapControllers(); //app.MapGrpcService(); //app.MapGrpcService().EnableGrpcWeb(); app.MapCodeFirstGrpcReflectionService(); app.MapFallbackToFile("index.html"); app.Run();