From 5f545bafc9dc68c167943c2eb003876197ee023a Mon Sep 17 00:00:00 2001 From: Simon Martens Date: Tue, 30 Sep 2025 21:00:44 +0200 Subject: [PATCH] Locking whil SyntaxCheck --- HaWeb/Controllers/APIController.cs | 18 ++++++++++++++---- HaWeb/WebSockets/WebSocketMiddleware.cs | 12 ++++++++---- docker-compose.staging.yml | 8 ++------ docker-compose.yml | 8 ++------ 4 files changed, 26 insertions(+), 20 deletions(-) diff --git a/HaWeb/Controllers/APIController.cs b/HaWeb/Controllers/APIController.cs index 2e14c7e..144bd60 100644 --- a/HaWeb/Controllers/APIController.cs +++ b/HaWeb/Controllers/APIController.cs @@ -36,6 +36,7 @@ public class APIController : Controller { // Options private static readonly FormOptions _defaultFormOptions = new FormOptions(); + private static readonly SemaphoreSlim _syntaxCheckLock = new SemaphoreSlim(1, 1); public APIController(IHaDocumentWrappper lib, IXMLInteractionService xmlService, IXMLFileProvider xmlProvider) { @@ -78,12 +79,21 @@ public class APIController : Controller { // [ValidateAntiForgeryToken] [DisableFormValueModelBinding] [FeatureGate(Features.SyntaxCheck, Features.AdminService)] - public ActionResult?> GetSyntaxCheck(string? id) { + public async Task?>> GetSyntaxCheck(string? id) { var SCCache = _xmlService.GetSCCache(); if (_xmlProvider.HasChanged() || SCCache == null) { - var commit = _xmlProvider.GetGitState(); - SCCache = _xmlService.Test(_xmlService.GetState(), commit != null ? commit.Commit : string.Empty); - _xmlService.SetSCCache(SCCache); + await _syntaxCheckLock.WaitAsync(); + try { + // Double-check after acquiring lock + SCCache = _xmlService.GetSCCache(); + if (_xmlProvider.HasChanged() || SCCache == null) { + var commit = _xmlProvider.GetGitState(); + SCCache = _xmlService.Test(_xmlService.GetState(), commit != null ? commit.Commit : string.Empty); + _xmlService.SetSCCache(SCCache); + } + } finally { + _syntaxCheckLock.Release(); + } } return Ok(SCCache); } diff --git a/HaWeb/WebSockets/WebSocketMiddleware.cs b/HaWeb/WebSockets/WebSocketMiddleware.cs index bafc314..d42fc44 100644 --- a/HaWeb/WebSockets/WebSocketMiddleware.cs +++ b/HaWeb/WebSockets/WebSocketMiddleware.cs @@ -81,13 +81,13 @@ public class WebSocketMiddleware : IMiddleware { } result = await webSocket.ReceiveAsync(new ArraySegment(buffer), CancellationToken.None); } catch (WebSocketException ex) { - _openSockets!.Remove(webSocket); + break; } } try { await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None); } catch (WebSocketException ex) { - _openSockets.Remove(webSocket); + // Socket already closed } _openSockets!.Remove(webSocket); } @@ -124,13 +124,17 @@ public class WebSocketMiddleware : IMiddleware { private async Task _SendToAll(T msg) { if (_openSockets == null) return; - foreach (var socket in _openSockets) { + var socketsToRemove = new List(); + foreach (var socket in _openSockets.ToList()) { try { await socket.SendAsync(_SerializeToBytes(msg), WebSocketMessageType.Text, true, CancellationToken.None); } catch (WebSocketException ex) { - _openSockets.Remove(socket); + socketsToRemove.Add(socket); } } + foreach (var socket in socketsToRemove) { + _openSockets.Remove(socket); + } } private ArraySegment _SerializeToBytes(T o) { diff --git a/docker-compose.staging.yml b/docker-compose.staging.yml index 5001554..b1dc10b 100644 --- a/docker-compose.staging.yml +++ b/docker-compose.staging.yml @@ -2,10 +2,10 @@ name: hamann-ausgabe-staging services: hamann-staging: build: . + ports: + - "5000:5000" volumes: - hamann_staging_data:/app/data - networks: - - caddy environment: - ASPNETCORE_URLS=http://+:5000 - DOTNET_ENVIRONMENT=Staging @@ -17,8 +17,4 @@ services: volumes: hamann_staging_data: - external: true - -networks: - caddy: external: true \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 178bb72..d8bc904 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,10 +2,10 @@ name: hamann-ausgabe services: hamann-service: build: . + ports: + - "5000:5000" volumes: - hamann_data:/app/data - networks: - - caddy environment: - ASPNETCORE_URLS=http://+:5000 - DOTNET_ENVIRONMENT=Production @@ -18,7 +18,3 @@ services: volumes: hamann_data: external: true - -networks: - caddy: - external: true