refactor: save current workspace state including FinlyticAnalyzer fixes, FinlyticApp trade route alignment, and DTO audit documentation
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
@@ -8,24 +10,71 @@ namespace FinlyticBackend.Hubs;
|
||||
/// <summary>
|
||||
/// SignalR Hub streaming real-time stock prices & daily % growth updates for favorite assets every 10 seconds.
|
||||
/// </summary>
|
||||
[Authorize]
|
||||
public class FavoritesPriceHub : Hub
|
||||
{
|
||||
private readonly ILogger<FavoritesPriceHub> _logger;
|
||||
|
||||
// Speichert thread-sicher, wie viele aktive Verbindungen ein User hat (UserId -> ConnectionCount)
|
||||
private static readonly ConcurrentDictionary<string, int> ActiveUserConnections = new();
|
||||
|
||||
public FavoritesPriceHub(ILogger<FavoritesPriceHub> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Liefert eine Übersicht aller aktuell mit dem Hub verbundenen User-IDs.
|
||||
/// </summary>
|
||||
public static string[] GetActiveUserIds() => [.. ActiveUserConnections.Keys];
|
||||
|
||||
public override async Task OnConnectedAsync()
|
||||
{
|
||||
_logger.LogInformation("[FavoritesPriceHub] SignalR client connected: ConnectionId={ConnectionId}", Context.ConnectionId);
|
||||
var userId = Context.UserIdentifier;
|
||||
|
||||
if (!string.IsNullOrEmpty(userId))
|
||||
{
|
||||
// Füge die Verbindung der benutzerspezifischen Gruppe hinzu
|
||||
await Groups.AddToGroupAsync(Context.ConnectionId, GetGroupName(userId));
|
||||
|
||||
ActiveUserConnections.AddOrUpdate(userId, 1, (_, count) => count + 1);
|
||||
|
||||
_logger.LogInformation("[FavoritesPriceHub] User '{UserId}' connected (ConnectionId={ConnectionId}). Active connections for user: {Count}",
|
||||
userId, Context.ConnectionId, ActiveUserConnections[userId]);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogWarning("[FavoritesPriceHub] Anonymous SignalR client connected without UserIdentifier: ConnectionId={ConnectionId}", Context.ConnectionId);
|
||||
}
|
||||
|
||||
await base.OnConnectedAsync();
|
||||
}
|
||||
|
||||
public override async Task OnDisconnectedAsync(Exception? exception)
|
||||
{
|
||||
_logger.LogInformation("[FavoritesPriceHub] SignalR client disconnected: ConnectionId={ConnectionId}", Context.ConnectionId);
|
||||
var userId = Context.UserIdentifier;
|
||||
|
||||
if (!string.IsNullOrEmpty(userId))
|
||||
{
|
||||
await Groups.RemoveFromGroupAsync(Context.ConnectionId, GetGroupName(userId));
|
||||
|
||||
ActiveUserConnections.AddOrUpdate(userId, 0, (_, count) =>
|
||||
{
|
||||
var newCount = count - 1;
|
||||
return newCount < 0 ? 0 : newCount;
|
||||
});
|
||||
|
||||
// Wenn keine aktiven Verbindungen mehr bestehen, aus Dictionary entfernen
|
||||
if (ActiveUserConnections.TryGetValue(userId, out var remainingCount) && remainingCount <= 0)
|
||||
{
|
||||
ActiveUserConnections.TryRemove(userId, out _);
|
||||
}
|
||||
|
||||
_logger.LogInformation("[FavoritesPriceHub] User '{UserId}' disconnected (ConnectionId={ConnectionId})", userId, Context.ConnectionId);
|
||||
}
|
||||
|
||||
await base.OnDisconnectedAsync(exception);
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetGroupName(string userId) => $"User_{userId.Trim()}";
|
||||
}
|
||||
Reference in New Issue
Block a user