@@ -39,6 +39,7 @@ const { resolveServerEntry } = require("./lib/resolveServerEntry");
3939const { resolveDarwinHelperExecutable } = require ( "./lib/resolveNodeHelper" ) ;
4040const { resolveRemoteServerUrl, isValidHttpUrl } = require ( "./lib/resolveRemoteServerUrl" ) ;
4141const { writeRemoteServerUrl } = require ( "./lib/remoteServerPreferences" ) ;
42+ const { buildReadinessUrl, waitForServer } = require ( "./lib/serverReadiness" ) ;
4243
4344// ── Single Instance Lock ───────────────────────────────────
4445const gotTheLock = app . requestSingleInstanceLock ( ) ;
@@ -86,6 +87,7 @@ let remoteServerUrl = resolveRemoteServerUrl({
8687} ) ;
8788
8889const getServerUrl = ( ) => remoteServerUrl || `http://localhost:${ serverPort } ` ;
90+ const getServerReadinessUrl = ( ) => buildReadinessUrl ( getServerUrl ( ) ) ;
8991
9092function resolveNodeExecutable ( env = process . env ) {
9193 // #1081: Ensure Next.js standalone runs using Electron's Node runtime
@@ -185,26 +187,6 @@ function sendToRenderer(channel, data) {
185187 }
186188}
187189
188- // ── Helper: Wait for server readiness (#1, #10) ────────────
189- // Default raised to 180s: the first launch after an upgrade can run long DB
190- // migrations, during which the server accepts the TCP connection but holds the
191- // HTTP response until handlers initialize. The previous 30s cap timed out and
192- // left the window stuck on a hanging connection (#2460).
193- async function waitForServer ( url , timeoutMs = 180000 ) {
194- const start = Date . now ( ) ;
195- while ( Date . now ( ) - start < timeoutMs ) {
196- try {
197- const res = await fetch ( url ) ;
198- if ( res . ok || res . status < 500 ) return true ;
199- } catch {
200- /* server not ready yet */
201- }
202- await new Promise ( ( r ) => setTimeout ( r , 500 ) ) ;
203- }
204- console . warn ( "[Electron] Server readiness timeout — showing window anyway" ) ;
205- return false ;
206- }
207-
208190// ── Helper: Wait for server process exit with timeout (#2) ─
209191async function waitForServerExit ( proc , timeoutMs = 5000 ) {
210192 if ( ! proc ) return ;
@@ -533,7 +515,7 @@ async function changePort(newPort) {
533515
534516 // Start server on new port
535517 startNextServer ( ) ;
536- await waitForServer ( getServerUrl ( ) ) ;
518+ await waitForServer ( getServerReadinessUrl ( ) ) ;
537519
538520 // Reload window and update tray
539521 if ( mainWindow && ! mainWindow . isDestroyed ( ) ) {
@@ -603,7 +585,7 @@ async function setRemoteServerUrl(nextUrl) {
603585
604586 startNextServer ( ) ;
605587 try {
606- await waitForServer ( ` ${ getServerUrl ( ) } /api/monitoring/health` ) ;
588+ await waitForServer ( getServerReadinessUrl ( ) ) ;
607589 } catch ( err ) {
608590 console . warn ( "[Electron] Server did not become ready after remote-server change:" , err . message ) ;
609591 }
@@ -935,7 +917,7 @@ function setupIpcHandlers() {
935917 stopNextServer ( ) ;
936918 await waitForServerExit ( serverToStop ) ;
937919 startNextServer ( ) ;
938- await waitForServer ( getServerUrl ( ) ) ;
920+ await waitForServer ( getServerReadinessUrl ( ) ) ;
939921 return { success : true } ;
940922 } ) ;
941923
@@ -1078,8 +1060,8 @@ app.whenReady().then(async () => {
10781060 startNextServer ( ) ;
10791061 let serverReady = true ;
10801062 if ( ! isDev ) {
1081- // Probe the auth-exempt health endpoint (not the root URL, which may redirect) .
1082- serverReady = await waitForServer ( ` ${ getServerUrl ( ) } /api/monitoring/health` ) ;
1063+ // Probe the lightweight auth-exempt endpoint instead of aggregating full monitoring state .
1064+ serverReady = await waitForServer ( getServerReadinessUrl ( ) ) ;
10831065 }
10841066
10851067 if ( isHeadless ) {
@@ -1095,7 +1077,7 @@ app.whenReady().then(async () => {
10951077 // If readiness timed out (e.g. very long first-launch migrations), don't leave the
10961078 // window stuck on a hanging connection — keep polling and reload once it responds (#2460).
10971079 if ( ! isDev && ! serverReady && ! isHeadless ) {
1098- void waitForServer ( ` ${ getServerUrl ( ) } /api/monitoring/health` , 300000 ) . then ( ( ready ) => {
1080+ void waitForServer ( getServerReadinessUrl ( ) , 300000 ) . then ( ( ready ) => {
10991081 if ( ready && mainWindow && ! mainWindow . isDestroyed ( ) ) {
11001082 mainWindow . loadURL ( getServerUrl ( ) ) ;
11011083 }
0 commit comments