diff --git a/EpsonPrintService/PrinterDiscoveryBackgroundTask.cs b/EpsonPrintService/PrinterDiscoveryBackgroundTask.cs index a3644e0..858a2f0 100644 --- a/EpsonPrintService/PrinterDiscoveryBackgroundTask.cs +++ b/EpsonPrintService/PrinterDiscoveryBackgroundTask.cs @@ -67,34 +67,45 @@ public class PrinterDiscoveryBackgroundTask private async Task DiscoverAndNotifyAsync() { - _printServer.EnterDiscoveryLock(); + List printers; + HashSet currentIps; + bool configChanged; + + await _printServer.EnterDiscoveryLockAsync(); try { - var printers = await _discoveryService.DiscoverPrintersAsync(_discoveryTimeout); + printers = await _discoveryService.DiscoverPrintersAsync(_discoveryTimeout); + currentIps = printers.Select(p => p.IPAddress).ToHashSet(); + configChanged = HasConfigurationChanged(currentIps); - var currentIps = printers.Select(p => p.IPAddress).ToHashSet(); - - foreach (string currentIp in currentIps) + if (configChanged) { - _printServer.RegisterPrinter(currentIp); - } - - if (HasConfigurationChanged(currentIps)) - { - _logger.LogInformation("Discovered printer configuration changed: {Count} printer(s)", printers.Count); _lastDiscoveredPrinterIps = currentIps; _lastDiscoveredPrinters = printers; - await _receiver.OnPrintersDiscoveredAsync(printers.AsReadOnly()); } } catch (Exception ex) { _logger.LogWarning(ex, "Failed to discover printers"); + return; // Exit early on error } finally { _printServer.ExitDiscoveryLock(); } + + // Register printers AFTER releasing the lock + foreach (string currentIp in currentIps) + { + _logger.LogDebug("Registering discovered printer with IP: {IP}", currentIp); + _printServer.RegisterPrinter(currentIp); + } + + if (configChanged) + { + _logger.LogInformation("Discovered printer configuration changed: {Count} printer(s)", printers.Count); + await _receiver.OnPrintersDiscoveredAsync(printers.AsReadOnly()); + } } private bool HasConfigurationChanged(HashSet currentIps) diff --git a/EpsonPrintService/config.txt b/EpsonPrintService/config.txt index 751958f..4a63b8d 100644 --- a/EpsonPrintService/config.txt +++ b/EpsonPrintService/config.txt @@ -1 +1 @@ -aHR0cDovL2xvY2FsaG9zdDo1MDAyOzY1YzM2MDYyZDM2ZTRjZmVlNmVjZjIyODtvWTVpcjViQi9pMXlSeFdpQ2FRTE1QdkFsS0dBaVVjNy8yK0IyczhXcUJzPQ== \ No newline at end of file +aHR0cHM6Ly9hcGkuZGV2Lmdhc3Ryb2phbWVzLmNoOzY4ODc1MjY2MTcxMjgxN2RlMjcxNTlmMjtGTEVEL1phQ2F5a0NrdEpCOHZzN1lqVFNyaStleGdKVWIva21WWk1lUHBNPQ== \ No newline at end of file diff --git a/EpsonTest/invoice.json b/EpsonTest/invoice.json new file mode 100644 index 0000000..1da4b24 --- /dev/null +++ b/EpsonTest/invoice.json @@ -0,0 +1,6 @@ +{ + "PrinterIp": "10.0.20.12", + "LogoUrl": "https://james-dev-public-images.s3.eu-central-1.amazonaws.com/01-21-26-15:26:16.jpeg", + "ReceiptType": 4, + "Content": "{\"CompanyName\":\"Gaumenfreuden\",\"Address1\":\"Orellistrasse 21\",\"Address2\":\"8044 Zurich\",\"Phone\":\"\\u002B380504371463\",\"ReceiptNumber\":null,\"DateTime\":\"2026-01-28T12:47:47.0874074Z\",\"Guests\":null,\"Items\":[{\"Quantity\":1,\"Description\":\"Beer light\",\"UnitPrice\":40,\"TotalPrice\":40,\"TaxCategory\":\"A\",\"SubItems\":null},{\"Quantity\":1,\"Description\":\"Premium Juice\",\"UnitPrice\":1.2,\"TotalPrice\":1.2,\"TaxCategory\":\"B\",\"SubItems\":null},{\"Quantity\":1,\"Description\":\"Beer light from Catalog\",\"UnitPrice\":20,\"TotalPrice\":20,\"TaxCategory\":\"A\",\"SubItems\":null},{\"Quantity\":1,\"Description\":\"Beer light from Catalog\",\"UnitPrice\":20,\"TotalPrice\":20,\"TaxCategory\":\"A\",\"SubItems\":null}],\"Total\":81.2,\"Currency\":\"CHF\",\"ThankYouMessage\":\"Thanks\",\"TableNumber\":\"HappyHoursDrinks\"}" +} \ No newline at end of file diff --git a/Inspectron.Epson/Queue/PrintServer.cs b/Inspectron.Epson/Queue/PrintServer.cs index 7fa3137..1993a05 100644 --- a/Inspectron.Epson/Queue/PrintServer.cs +++ b/Inspectron.Epson/Queue/PrintServer.cs @@ -6,7 +6,9 @@ public class PrintServer private readonly IPrintService _printService; private readonly ILogger _logger; private readonly ConcurrentDictionary _printerQueues; - private readonly ReaderWriterLockSlim _printDiscoveryLock = new(); + private readonly SemaphoreSlim _printDiscoveryLock = new(1, 1); + private int _readerCount = 0; + private readonly object _readerCountLock = new(); public PrintServer(IPrintService printService, ILogger logger) { @@ -19,23 +21,58 @@ public class PrintServer /// /// Acquires a read lock for print operations. Multiple print operations can run concurrently. /// - public void EnterPrintLock() => _printDiscoveryLock.EnterReadLock(); + public void EnterPrintLock() + { + _logger.LogDebug("Entering print lock"); + lock (_readerCountLock) + { + _readerCount++; + if (_readerCount == 1) + { + _printDiscoveryLock.Wait(); + } + } + _logger.LogDebug("Entered print lock"); + + } /// /// Releases the read lock after a print operation completes. /// - public void ExitPrintLock() => _printDiscoveryLock.ExitReadLock(); + public void ExitPrintLock() + { + _logger.LogDebug("Exiting print lock"); + lock (_readerCountLock) + { + _readerCount--; + if (_readerCount == 0) + { + _printDiscoveryLock.Release(); + } + } + _logger.LogDebug("Exited print lock"); + } /// /// Acquires a write lock for discovery operations. This blocks until all print operations complete /// and prevents new print operations from starting. /// - public void EnterDiscoveryLock() => _printDiscoveryLock.EnterWriteLock(); + public async Task EnterDiscoveryLockAsync() + { + _logger.LogDebug("Entering discovery lock"); + await _printDiscoveryLock.WaitAsync(); + _logger.LogDebug("Entered discovery lock"); + } /// /// Releases the write lock after discovery completes. /// - public void ExitDiscoveryLock() => _printDiscoveryLock.ExitWriteLock(); + public void ExitDiscoveryLock() + { + _logger.LogDebug("Exiting discovery lock"); + _printDiscoveryLock.Release(); + _logger.LogDebug("Exited discovery lock"); + } public void RegisterPrinter(string printerIp) {