Fixed unawaited SendAsync calls of Websocket
This commit is contained in:
parent
abedc6c203
commit
d464c9cd71
|
|
@ -160,7 +160,7 @@ public static class SessionMethods
|
|||
var installation = Db.GetInstallationById(action.InstallationId);
|
||||
installation.TestingMode = action.TestingMode;
|
||||
installation.Apply(Db.Update);
|
||||
WebsocketManager.InformWebsocketsForInstallation(action.InstallationId);
|
||||
await WebsocketManager.InformWebsocketsForInstallation(action.InstallationId);
|
||||
|
||||
// Save the configuration change to the database
|
||||
Db.HandleAction(action);
|
||||
|
|
@ -179,7 +179,7 @@ public static class SessionMethods
|
|||
{
|
||||
installation.TestingMode = action.TestingMode;
|
||||
installation.Apply(Db.Update);
|
||||
WebsocketManager.InformWebsocketsForInstallation(action.InstallationId);
|
||||
await WebsocketManager.InformWebsocketsForInstallation(action.InstallationId);
|
||||
}
|
||||
|
||||
Db.UpdateAction(action);
|
||||
|
|
@ -199,7 +199,7 @@ public static class SessionMethods
|
|||
var installation = Db.GetInstallationById(action.InstallationId);
|
||||
installation.TestingMode = false;
|
||||
installation.Apply(Db.Update);
|
||||
WebsocketManager.InformWebsocketsForInstallation(action.InstallationId);
|
||||
await WebsocketManager.InformWebsocketsForInstallation(action.InstallationId);
|
||||
}
|
||||
|
||||
Db.Delete(action);
|
||||
|
|
|
|||
|
|
@ -181,7 +181,7 @@ public static class RabbitMqManager
|
|||
//If the status has changed, update all the connected front-ends regarding this installation
|
||||
if(prevStatus != receivedStatusMessage.Status && WebsocketManager.InstallationConnections[installationId].Connections.Count > 0)
|
||||
{
|
||||
WebsocketManager.InformWebsocketsForInstallation(installationId);
|
||||
_ = WebsocketManager.InformWebsocketsForInstallation(installationId); // fire-and-forget: sync event handler, can't await
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ public static class WebsocketManager
|
|||
{
|
||||
while (true)
|
||||
{
|
||||
var idsToInform = new List<Int64>();
|
||||
|
||||
lock (InstallationConnections)
|
||||
{
|
||||
Console.WriteLine("Monitoring installation table...");
|
||||
|
|
@ -31,10 +33,8 @@ public static class WebsocketManager
|
|||
(installationConnection.Value.Product == (int)ProductType.SodiStoreMax && (DateTime.Now - installationConnection.Value.Timestamp) > TimeSpan.FromMinutes(2))
|
||||
)
|
||||
{
|
||||
|
||||
Console.WriteLine("Installation ID is " + installationConnection.Key);
|
||||
Console.WriteLine("installationConnection.Value.Timestamp is " + installationConnection.Value.Timestamp);
|
||||
// Console.WriteLine("diff is "+(DateTime.Now-installationConnection.Value.Timestamp));
|
||||
|
||||
installationConnection.Value.Status = (int)StatusType.Offline;
|
||||
Installation installation = Db.Installations.FirstOrDefault(f => f.Product == installationConnection.Value.Product && f.Id == installationConnection.Key);
|
||||
|
|
@ -42,20 +42,29 @@ public static class WebsocketManager
|
|||
installation.Apply(Db.Update);
|
||||
if (installationConnection.Value.Connections.Count > 0)
|
||||
{
|
||||
InformWebsocketsForInstallation(installationConnection.Key);
|
||||
idsToInform.Add(installationConnection.Key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Send notifications outside the lock so we can await the async SendAsync calls
|
||||
foreach (var id in idsToInform)
|
||||
await InformWebsocketsForInstallation(id);
|
||||
|
||||
await Task.Delay(TimeSpan.FromMinutes(1));
|
||||
}
|
||||
}
|
||||
|
||||
//Inform all the connected websockets regarding installation "installationId"
|
||||
public static void InformWebsocketsForInstallation(Int64 installationId)
|
||||
public static async Task InformWebsocketsForInstallation(Int64 installationId)
|
||||
{
|
||||
var installation = Db.GetInstallationById(installationId);
|
||||
byte[] dataToSend;
|
||||
List<WebSocket> connections;
|
||||
|
||||
lock (InstallationConnections)
|
||||
{
|
||||
var installationConnection = InstallationConnections[installationId];
|
||||
Console.WriteLine("Update all the connected websockets for installation " + installation.Name);
|
||||
|
||||
|
|
@ -66,18 +75,26 @@ public static class WebsocketManager
|
|||
testingMode = installation.TestingMode
|
||||
};
|
||||
|
||||
string jsonString = JsonSerializer.Serialize(jsonObject);
|
||||
byte[] dataToSend = Encoding.UTF8.GetBytes(jsonString);
|
||||
|
||||
foreach (var connection in installationConnection.Connections)
|
||||
{
|
||||
connection.SendAsync(
|
||||
new ArraySegment<byte>(dataToSend, 0, dataToSend.Length),
|
||||
WebSocketMessageType.Text,
|
||||
true, // Indicates that this is the end of the message
|
||||
CancellationToken.None
|
||||
);
|
||||
dataToSend = Encoding.UTF8.GetBytes(JsonSerializer.Serialize(jsonObject));
|
||||
connections = installationConnection.Connections.ToList(); // snapshot before releasing lock
|
||||
}
|
||||
|
||||
// Send to all connections concurrently (preserves original fire-and-forget intent),
|
||||
// but isolate failures so one closed socket doesn't affect others or crash the caller.
|
||||
await Task.WhenAll(connections
|
||||
.Where(c => c.State == WebSocketState.Open)
|
||||
.Select(async c =>
|
||||
{
|
||||
try
|
||||
{
|
||||
await c.SendAsync(new ArraySegment<byte>(dataToSend, 0, dataToSend.Length),
|
||||
WebSocketMessageType.Text, true, CancellationToken.None);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"WebSocket send failed for installation {installationId}: {ex.Message}");
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -109,7 +126,7 @@ public static class WebsocketManager
|
|||
|
||||
var jsonString = JsonSerializer.Serialize(jsonObject);
|
||||
var dataToSend = Encoding.UTF8.GetBytes(jsonString);
|
||||
currentWebSocket.SendAsync(dataToSend,
|
||||
await currentWebSocket.SendAsync(dataToSend,
|
||||
WebSocketMessageType.Text,
|
||||
true,
|
||||
CancellationToken.None
|
||||
|
|
@ -120,6 +137,7 @@ public static class WebsocketManager
|
|||
|
||||
//Received a new message from this websocket.
|
||||
//We have a HandleWebSocketConnection per connected frontend
|
||||
byte[] encodedDataToSend;
|
||||
lock (InstallationConnections)
|
||||
{
|
||||
List<WebsocketMessage> dataToSend = new List<WebsocketMessage>();
|
||||
|
|
@ -157,15 +175,7 @@ public static class WebsocketManager
|
|||
|
||||
}
|
||||
var jsonString = JsonSerializer.Serialize(dataToSend);
|
||||
var encodedDataToSend = Encoding.UTF8.GetBytes(jsonString);
|
||||
|
||||
|
||||
currentWebSocket.SendAsync(encodedDataToSend,
|
||||
WebSocketMessageType.Text,
|
||||
true, // Indicates that this is the end of the message
|
||||
CancellationToken.None
|
||||
);
|
||||
|
||||
encodedDataToSend = Encoding.UTF8.GetBytes(jsonString);
|
||||
|
||||
// Console.WriteLine("Printing installation connection list");
|
||||
// Console.WriteLine("----------------------------------------------");
|
||||
|
|
@ -175,6 +185,12 @@ public static class WebsocketManager
|
|||
// }
|
||||
// Console.WriteLine("----------------------------------------------");
|
||||
}
|
||||
|
||||
await currentWebSocket.SendAsync(encodedDataToSend,
|
||||
WebSocketMessageType.Text,
|
||||
true,
|
||||
CancellationToken.None
|
||||
);
|
||||
}
|
||||
|
||||
lock (InstallationConnections)
|
||||
|
|
|
|||
Loading…
Reference in New Issue