From f8729953d2d16cce2f1afcbf8fe28a9cb6129bec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Del=20Rinc=C3=B3n=20L=C3=B3pez?= Date: Fri, 17 Nov 2023 09:55:09 +0100 Subject: [PATCH] Add SignalR HUB refresh instead of polling. --- .../BlazorApp1.Application.csproj | 2 ++ .../IWeatherForecastService.cs | 1 + .../WeatherForecastService.cs | 28 ++++++++++++++++++- .../WeatherForecastSummaryHub.cs | 13 +++++++++ BlazorApp1/Client/Pages/FetchData.razor | 22 ++++++++------- BlazorApp1/Server/Program.cs | 2 +- 6 files changed, 56 insertions(+), 12 deletions(-) create mode 100644 BlazorApp1.Application/WeatherForecastSummaryHub.cs diff --git a/BlazorApp1.Application/BlazorApp1.Application.csproj b/BlazorApp1.Application/BlazorApp1.Application.csproj index c8d5e66..5df0294 100644 --- a/BlazorApp1.Application/BlazorApp1.Application.csproj +++ b/BlazorApp1.Application/BlazorApp1.Application.csproj @@ -8,6 +8,8 @@ + + diff --git a/BlazorApp1.Application/IWeatherForecastService.cs b/BlazorApp1.Application/IWeatherForecastService.cs index b5228ff..420ea51 100644 --- a/BlazorApp1.Application/IWeatherForecastService.cs +++ b/BlazorApp1.Application/IWeatherForecastService.cs @@ -5,5 +5,6 @@ namespace BlazorApp1.Application; public interface IWeatherForecastService { Task AddForecast(WeatherForecastDto weatherForecast, CancellationToken cancellationToken = default); + ValueTask ProcessSignalRWeatherSummary(CancellationToken cancellationToken); ValueTask ProcessWeatherSummary(WeatherForecast forecast, CancellationToken cancellationToken); } \ No newline at end of file diff --git a/BlazorApp1.Application/WeatherForecastService.cs b/BlazorApp1.Application/WeatherForecastService.cs index 47cb7ca..1341ed7 100644 --- a/BlazorApp1.Application/WeatherForecastService.cs +++ b/BlazorApp1.Application/WeatherForecastService.cs @@ -3,6 +3,10 @@ using BlazorApp1.Domain; using BlazorApp1.Domain.Abstractions.Repositories; using BlazorApp1.Server.Abstractions.Contracts; +using BlazorApp1.Server.Hubs; +using Microsoft.AspNetCore.Components; +using Microsoft.AspNetCore.SignalR; +using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; @@ -14,18 +18,21 @@ public class WeatherForecastService : IWeatherForecastService private readonly IWeatherForecastSummaryRepository _weatherForecastSummaryRepository; private readonly IMapper _mapper; private readonly IBackgroundTaskQueue _backgroundTaskQueue; + private readonly IHubContext hubContext; private readonly ILogger _logger; public WeatherForecastService(IWeatherForecastRepository weatherForecastRepository, IWeatherForecastSummaryRepository weatherForecastSummaryRepository, IMapper mapper, IBackgroundTaskQueue backgroundTaskQueue, + IHubContext hubContext, ILogger logger) { _weatherForecastRepository = weatherForecastRepository; _weatherForecastSummaryRepository = weatherForecastSummaryRepository; _mapper = mapper; _backgroundTaskQueue = backgroundTaskQueue; + this.hubContext = hubContext; _logger = logger; } @@ -35,7 +42,24 @@ public async Task AddForecast(WeatherForecastDto weatherForecast, CancellationTo await _weatherForecastRepository.AddWeatherForecast(forecast); - var tasktoDo = _backgroundTaskQueue.QueueBackgroundWorkItemAsync(ProcessWeatherSummary(forecast)); + await _backgroundTaskQueue.QueueBackgroundWorkItemAsync(ProcessWeatherSummary(forecast)); + } + + private static Func ProcessSignalRWeatherSummary(WeatherForecast forecast) + { + return (serviceProvider, cancellationToken) => + { + var service = serviceProvider.GetRequiredService(); + return service.ProcessSignalRWeatherSummary(cancellationToken); + }; + } + + public async ValueTask ProcessSignalRWeatherSummary(CancellationToken cancellationToken) + { + //TODO: Move to a new RepoMethod. + var forecasts = await _weatherForecastSummaryRepository.GetAllForecastSummaries(); + + await this.hubContext.Clients.All.SendAsync("ReceiveForecastSummaries", forecasts.ToArray()); } private static Func ProcessWeatherSummary(WeatherForecast forecast) @@ -70,6 +94,8 @@ public async ValueTask ProcessWeatherSummary(WeatherForecast forecast, Cancellat await _weatherForecastSummaryRepository.AddWeatherForecastSummary(forecastSummary); } + await _backgroundTaskQueue.QueueBackgroundWorkItemAsync(ProcessSignalRWeatherSummary(forecast)); + _logger.LogInformation($"Processing ForecastSummary and added {forecast.Date}"); } } diff --git a/BlazorApp1.Application/WeatherForecastSummaryHub.cs b/BlazorApp1.Application/WeatherForecastSummaryHub.cs new file mode 100644 index 0000000..d4b850d --- /dev/null +++ b/BlazorApp1.Application/WeatherForecastSummaryHub.cs @@ -0,0 +1,13 @@ +using BlazorApp1.Domain; +using BlazorApp1.Server.Abstractions.Contracts; +using Microsoft.AspNetCore.SignalR; + +namespace BlazorApp1.Server.Hubs; + +public class WeatherForecastSummaryHub : Hub +{ + public async Task SendWeatherforecastSummaries(WeatherForecastSummaryDto[] summaries) + { + await Clients.All.SendAsync("ReceiveForecastSummaries", summaries); + } +} \ No newline at end of file diff --git a/BlazorApp1/Client/Pages/FetchData.razor b/BlazorApp1/Client/Pages/FetchData.razor index 94be7f1..613044b 100644 --- a/BlazorApp1/Client/Pages/FetchData.razor +++ b/BlazorApp1/Client/Pages/FetchData.razor @@ -4,6 +4,8 @@ @using BlazorApp1.Domain @using BlazorApp1.Server.Abstractions.Contracts @using System.Text.Json.Serialization; +@using Microsoft.AspNetCore.SignalR.Client; +@inject NavigationManager Navigation @inject HttpClient Http Weather forecast @@ -74,7 +76,7 @@ else private WeatherForecastDto[]? forecasts; private WeatherForecastSummary[]? forecastSummaries; private WeatherForecastDto? forecastToAdd; - private static System.Timers.Timer _timer; + private HubConnection? hubConnection; protected override async Task OnInitializedAsync() { @@ -84,20 +86,20 @@ else Date = DateTime.Now }; - _timer = new System.Timers.Timer(5000); - _timer.Elapsed += CountDownTimer; - _timer.Enabled = true; - } - public async void CountDownTimer(Object source, System.Timers.ElapsedEventArgs e) - { - forecastSummaries = await Http.GetFromJsonAsync("WeatherForecastSummary"); + hubConnection = new HubConnectionBuilder() + .WithUrl(Navigation.ToAbsoluteUri("/weatherforecastsummaryhub")) + .Build(); - await InvokeAsync(async () => + hubConnection.On("ReceiveForecastSummaries", (summaries) => { + forecastSummaries = summaries; StateHasChanged(); }); + + await hubConnection.StartAsync(); } + private async Task AddForecast() { if (forecastToAdd != null) @@ -105,7 +107,7 @@ else var response = await Http.PostAsJsonAsync("WeatherForecast", forecastToAdd, WeatherForecastDtoJsonContext.Default.WeatherForecastDto); } - await ReloadDataAsync(); + forecasts = await Http.GetFromJsonAsync("WeatherForecast", WeatherForecastDtoJsonContext.Default.WeatherForecastDtoArray); } private async Task ReloadDataAsync() diff --git a/BlazorApp1/Server/Program.cs b/BlazorApp1/Server/Program.cs index 449da2f..6c67180 100644 --- a/BlazorApp1/Server/Program.cs +++ b/BlazorApp1/Server/Program.cs @@ -6,7 +6,6 @@ using BlazorApp1.Server.Profiles; using Microsoft.AspNetCore.ResponseCompression; using Microsoft.EntityFrameworkCore; -using System.Text.Encodings.Web; var builder = WebApplication.CreateBuilder(args); @@ -65,6 +64,7 @@ app.MapControllers(); app.MapHub("/chathub"); +app.MapHub("/weatherforecastsummaryhub"); app.MapFallbackToFile("index.html");