From f9e4cdd4df811f1f35e4eb1962d1840d60d76c07 Mon Sep 17 00:00:00 2001 From: Christoph Keller Date: Sun, 25 Aug 2024 10:33:52 +0200 Subject: [PATCH] fix: ISingleClientProxy is not thread-safe. --- .../Hubs/TrackNodeHub.cs | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/TrackMate.Backend.RestApi/Hubs/TrackNodeHub.cs b/src/TrackMate.Backend.RestApi/Hubs/TrackNodeHub.cs index 7c93af5..8d128de 100644 --- a/src/TrackMate.Backend.RestApi/Hubs/TrackNodeHub.cs +++ b/src/TrackMate.Backend.RestApi/Hubs/TrackNodeHub.cs @@ -10,7 +10,7 @@ namespace TrackMate.Backend.RestApi.Hubs; public class TrackNodeHub(ILogger logger, TrackNodeService trackNodeService, TrackService trackService) : Hub { - private static readonly ConcurrentDictionary> _trackSubscribers = new(); + private static readonly ConcurrentDictionary> _trackSubscribers = new(); /// /// Creates a new to be used to create tracks. @@ -46,10 +46,10 @@ public async Task StartTrack(StartTrackModel startTrackModel) _trackSubscribers.AddOrUpdate( track.TrackId, - [ Clients.Caller ], + [ Context.ConnectionId ], (_, list) => { - list.Add(Clients.Caller); + list.Add(Context.ConnectionId); return list; }); @@ -81,7 +81,7 @@ public async Task GetAllTrackNodes() public async Task JoinTrack(string trackId) { logger.LogInformation("User joined track {trackId}.", trackId); - _trackSubscribers[trackId].Add(Clients.Caller); + _trackSubscribers[trackId].Add(Context.ConnectionId); await SendToTrackAsync(trackId, "UserJoined"); } @@ -92,7 +92,7 @@ public async Task JoinTrack(string trackId) public async Task LeaveTrack(string trackId) { logger.LogInformation("User left track {trackId}.", trackId); - _trackSubscribers[trackId].Remove(Clients.Caller); + _trackSubscribers[trackId].Remove(Context.ConnectionId); await SendToTrackAsync(trackId, "UserLeft"); } @@ -134,6 +134,12 @@ private static byte[] ReadAllBytesFromStream(Stream stream) return memoryStream.ToArray(); } - private static Task SendToTrackAsync(string trackId, string methodName, object? arg1 = null) - => Task.WhenAll(_trackSubscribers[trackId].Select(client => client.SendAsync(methodName, arg1))); + private async Task SendToTrackAsync(string trackId, string methodName, object? arg1 = null) + { + if (_trackSubscribers.TryGetValue(trackId, out var subscribers)) + { + var tasks = subscribers.Select(connectionId => Clients.Client(connectionId).SendAsync(methodName, arg1)); + await Task.WhenAll(tasks); + } + } }