Skip to content

Commit

Permalink
Wait for python server then reload (#12)
Browse files Browse the repository at this point in the history
Electron window spawns then waits for the python server to finish, When finished the main window will load into the url the python server is serving. 

---------

Co-authored-by: Max Klein <[email protected]>
  • Loading branch information
KenCorma and telamonian authored Sep 8, 2024
1 parent 2411e18 commit 8484686
Show file tree
Hide file tree
Showing 9 changed files with 363 additions and 12 deletions.
15 changes: 15 additions & 0 deletions .github/workflows/publish_all.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
name: Publish All Platforms

on:
workflow_dispatch:

jobs:
build-windows:
secrets: inherit
uses: ./.github/workflows/publish_windows.yml
build-apple:
secrets: inherit
uses: ./.github/workflows/publish_macos.yml
build-linux:
secrets: inherit
uses: ./.github/workflows/publish_linux.yml
2 changes: 1 addition & 1 deletion .github/workflows/publish_linux.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# .github/workflows/publish_linux.yml
name: Publish App
name: Release Linux app

on:
workflow_dispatch:
Expand Down
2 changes: 1 addition & 1 deletion assets/UI/run_cpu.bat
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
.\resources\UI\python_embedded\python.exe -s .//resources//UI//ComfyUI//main.py --cpu --windows-standalone-build
.\resources\python\python.exe -s .//resources//ComfyUI//main.py --cpu --windows-standalone-build
pause
2 changes: 2 additions & 0 deletions forge.config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { ForgeConfig } from '@electron-forge/shared-types';
import { MakerSquirrel } from '@electron-forge/maker-squirrel';
import { MakerZIP } from '@electron-forge/maker-zip';
import { MakerDMG } from '@electron-forge/maker-dmg';
import { MakerDeb } from '@electron-forge/maker-deb';
import { MakerRpm } from '@electron-forge/maker-rpm';
import { VitePlugin } from '@electron-forge/plugin-vite';
Expand Down Expand Up @@ -45,6 +46,7 @@ const config: ForgeConfig = {
},
},
makers: [
new MakerSquirrel({frameworkVersion:'net481'}, ['win32']),
new MakerZIP({}, ['darwin', 'win32']),
// the forge build produces a "ComfyUI" bin, but the rpm/deb makers expect a "comfyui-electron" bin (matching the "name" in package.json). We override this below
new MakerRpm({
Expand Down
6 changes: 6 additions & 0 deletions forge.env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ declare global {
// Used for hot reload after preload scripts.
viteDevServers: Record<string, import('vite').ViteDevServer>;
}
interface ProcessEnv {
PUBLISH? : string | boolean,
APPLE_ID: string,
APPLE_PASSWORD: string,
APPLE_TEAM_ID: string,
}
}

type VitePluginConfig = ConstructorParameters<typeof import('@electron-forge/plugin-vite').VitePlugin>[0];
Expand Down
6 changes: 3 additions & 3 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
<html>
<head>
<meta charset="UTF-8" />
<title>Hello World!</title>
<title>ComfyUI</title>

</head>
<body>
<h1>💖 Hello World!</h1>
<p>Welcome to your Electron application.</p>
<h1>Python Server is Loading</h1>
<p></p>
<script type="module" src="/src/renderer.ts"></script>
</body>
</html>
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"devDependencies": {
"@electron-forge/cli": "^7.4.0",
"@electron-forge/maker-deb": "^7.4.0",
"@electron-forge/maker-dmg": "^7.4.0",
"@electron-forge/maker-rpm": "^7.4.0",
"@electron-forge/maker-squirrel": "^7.4.0",
"@electron-forge/maker-zip": "^7.4.0",
Expand Down
48 changes: 42 additions & 6 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import net from 'node:net';
import path from 'node:path';

import dotenv from "dotenv";
import { app, BrowserWindow } from 'electron';
import { app, BrowserWindow, webContents } from 'electron';
// Handle creating/removing shortcuts on Windows when installing/uninstalling.
import('electron-squirrel-startup').then(ess => {
const {default: check} = ess;
Expand Down Expand Up @@ -36,12 +36,25 @@ const createWindow = () => {
});

// Load the UI from the Python server's URL
mainWindow.loadURL('http://localhost:8188/');
//mainWindow.loadURL('http://localhost:8188/');
mainWindow.loadFile(path.join(__dirname, `../renderer/${MAIN_WINDOW_VITE_NAME}/index.html`));

// Open the DevTools.
mainWindow.webContents.openDevTools();
// mainWindow.webContents.openDevTools();
};

// Server Heartbeat Listener Variables
let serverHeartBeatReference: NodeJS.Timeout = null;
const serverHeartBeatInterval: number = 15 * 1000; //15 Seconds
async function serverHeartBeat() {
const isReady = await isPortInUse(host, port);
if (isReady) {
// Getting webcontents[0] is not reliable if app started with dev window
webContents.getAllWebContents()[0].send("python-server-status", "active");
} else {
webContents.getAllWebContents()[0].send("python-server-status", "false");
}
}

const isPortInUse = (host: string, port: number): Promise<boolean> => {
return new Promise((resolve) => {
Expand All @@ -64,13 +77,25 @@ const isPortInUse = (host: string, port: number): Promise<boolean> => {
});
};

// Launch Python Server Variables
const maxFailWait: number = 10 * 2000; // 10seconds
let currentWaitTime: number = 0;
let spawnServerTimeout: NodeJS.Timeout = null;

const launchPythonServer = async (args: {userResourcesPath: string, appResourcesPath: string}) => {
const {userResourcesPath, appResourcesPath} = args;

const isServerRunning = await isPortInUse(host, port);
if (isServerRunning) {
console.log('Python server is already running');
// Server has been started outside the app, so attach to it.
setTimeout(() => {
// Not sure if needed but wait a few moments before sending the connect message up.
webContents.getAllWebContents()[0].send("python-server-status", "active");
}, 5000);
clearInterval(serverHeartBeatReference);
webContents.getAllWebContents()[0].loadURL('http://localhost:8188/');
serverHeartBeatReference = setInterval(serverHeartBeat, serverHeartBeatInterval);
return Promise.resolve();
}

Expand Down Expand Up @@ -133,9 +158,21 @@ const launchPythonServer = async (args: {userResourcesPath: string, appResources
const checkInterval = 1000; // Check every 1 second

const checkServerReady = async () => {
currentWaitTime += 1000;
if (currentWaitTime > maxFailWait) {
//Something has gone wrong and we need to backout.
clearTimeout(spawnServerTimeout);
reject("Python Server Failed To Start");
}
const isReady = await isPortInUse(host, port);
if (isReady) {
console.log('Python server is ready');
// Start the Heartbeat listener, send connected message to Renderer and resolve promise.
serverHeartBeatReference = setInterval(serverHeartBeat, serverHeartBeatInterval);
webContents.getAllWebContents()[0].send("python-server-status", "active");
//For now just replace the source of the main window to the python server
webContents.getAllWebContents()[0].loadURL('http://localhost:8188/');
clearTimeout(spawnServerTimeout);
resolve();
} else {
console.log('Ping failed. Retrying...');
Expand Down Expand Up @@ -175,10 +212,9 @@ app.on('ready', async () => {
} catch {
// if user-specific resources dir already exists, that is fine
}

try {
await launchPythonServer({userResourcesPath, appResourcesPath});
try {
createWindow();
await launchPythonServer({userResourcesPath, appResourcesPath});
} catch (error) {

}
Expand Down
Loading

0 comments on commit 8484686

Please sign in to comment.