using JdeScoping.Core.ViewModels; using Microsoft.AspNetCore.SignalR; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Logging; namespace JdeScoping.Api.Hubs; /// /// SignalR hub for real-time status updates /// public class StatusHub : Hub { private const string StatusCacheKey = "StatusHub_CachedStatus"; private readonly IMemoryCache _cache; private readonly ILogger _logger; private readonly TimeProvider _timeProvider; /// /// Initializes a new instance of the class. /// /// The memory cache for caching status updates. /// The logger instance. /// The time provider for getting current UTC time. public StatusHub(IMemoryCache cache, ILogger logger, TimeProvider timeProvider) { _cache = cache; _logger = logger; _timeProvider = timeProvider; } /// /// Called by worker service to update status. /// Caches the update and broadcasts to all clients. /// /// Status update to broadcast public async Task SetStatus(StatusUpdateViewModel statusUpdate) { _cache.Set(StatusCacheKey, statusUpdate); await Clients.All.SendAsync("statusUpdate", statusUpdate); _logger.LogDebug("Status updated: {Message}", statusUpdate.Message); } /// /// Called by clients to get initial cached status on connection. /// /// The most recent status update public StatusUpdateViewModel GetCachedStatus() { return _cache.GetOrCreate(StatusCacheKey, _ => new StatusUpdateViewModel { Message = "Unknown", Timestamp = _timeProvider.GetUtcNow().DateTime })!; } /// /// Called by controllers/services to broadcast search updates. /// /// Search update to broadcast public async Task PublishSearchUpdate(SearchUpdateViewModel searchUpdate) { await Clients.All.SendAsync("searchUpdate", searchUpdate); _logger.LogDebug("Search update published: ID={Id}, Status={Status}", searchUpdate.Id, searchUpdate.Status); } /// public override Task OnConnectedAsync() { _logger.LogInformation("Client {ConnectionId} connected to StatusHub", Context.ConnectionId); return base.OnConnectedAsync(); } /// public override Task OnDisconnectedAsync(Exception? exception) { _logger.LogInformation("Client {ConnectionId} disconnected from StatusHub", Context.ConnectionId); return base.OnDisconnectedAsync(exception); } }