(title, message, buttons = ['OK'])
| 74 | function acquireIpcSlot() { |
| 75 | return new Promise(function(resolve) { |
| 76 | if (ipcInFlight < MAX_IPC_IN_FLIGHT) { |
| 77 | ipcInFlight++; |
| 78 | resolve(); |
| 79 | return; |
| 80 | } |
| 81 | ipcWaitQueue.push(resolve); |
| 82 | }); |
| 83 | } |
| 84 | |
| 85 | function releaseIpcSlot() { |
| 86 | var next = ipcWaitQueue.shift(); |
| 87 | if (next) { |
| 88 | // Transfer the slot to the next waiter (inFlight unchanged). |
| 89 | next(); |
| 90 | } else { |
| 91 | ipcInFlight = Math.max(0, ipcInFlight - 1); |
| 92 | } |
| 93 | } |
| 94 | let connectInFlight = false; |
| 95 | |
| 96 | // Promise that resolves when WebSocket connects (so first load doesn't run before bridge is ready) |
| 97 | let connectionReadyResolve; |
| 98 | let connectionReady = new Promise(function(resolve) { |
| 99 | connectionReadyResolve = resolve; |
| 100 | }); |
| 101 | window.electron.whenConnected = function() { |
| 102 | return connectionReady; |
| 103 | }; |
| 104 | |
| 105 | function resetConnectionReady() { |
| 106 | connectionReady = new Promise(function(resolve) { |
| 107 | connectionReadyResolve = resolve; |
| 108 | }); |
| 109 | } |
| 110 | |
| 111 | function markConnected(socket) { |
| 112 | console.log('WebSocket connected to Printventory server'); |
| 113 | console.log('[Bridge] WebSocket readyState after open:', socket ? socket.readyState : ws?.readyState); |
| 114 | reconnectAttempts = 0; |
| 115 | connectInFlight = false; |
| 116 | if (connectionReadyResolve) { |
| 117 | connectionReadyResolve(); |
| 118 | connectionReadyResolve = null; |
| 119 | } |
| 120 | } |
| 121 | |
| 122 | // Wait for an open socket instead of a fixed short timeout (remote Docker often needs >500ms). |
| 123 | // Also tolerates brief close/reconnect cycles (e.g. container OOM restart) within the timeout window. |
| 124 | function ensureConnected(timeoutMs) { |
| 125 | timeoutMs = typeof timeoutMs === 'number' ? timeoutMs : 15000; |
| 126 | if (ws && ws.readyState === WebSocket.OPEN) { |
| 127 | return Promise.resolve(); |
| 128 | } |
| 129 | connect(); |
| 130 | return new Promise(function(resolve, reject) { |
| 131 | let settled = false; |
| 132 | let pollTimer = null; |
| 133 | const deadline = Date.now() + timeoutMs; |
no test coverage detected