Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
153ff83
test log
JulienChampagnol Jun 18, 2026
73de597
fix(Perf): better microservices launch
JulienChampagnol Jun 19, 2026
bf34b61
fix(Perf): better microservices launch
JulienChampagnol Jun 19, 2026
8b8aff2
Merge branch 'fix/perf_run_microservices' of https://github.com/Geode…
JulienChampagnol Jun 19, 2026
6f45181
cleanup
JulienChampagnol Jun 19, 2026
36ab4fc
cleanup
JulienChampagnol Jun 19, 2026
7ed999f
Apply prepare changes
JulienChampagnol Jun 19, 2026
8aa8ef7
oxlint
JulienChampagnol Jun 19, 2026
078b044
Merge branch 'fix/perf_run_microservices' of https://github.com/Geode…
JulienChampagnol Jun 19, 2026
0504815
Apply prepare changes
JulienChampagnol Jun 19, 2026
14f2163
oxlint
JulienChampagnol Jun 22, 2026
ec00239
Apply prepare changes
JulienChampagnol Jun 22, 2026
3e46cae
broken import
JulienChampagnol Jun 22, 2026
914658e
Apply prepare changes
JulienChampagnol Jun 22, 2026
8e7d197
Merge branch 'next' of https://github.com/Geode-solutions/OpenGeodeWe…
JulienChampagnol Jun 23, 2026
06f847e
Merge branch 'next' of https://github.com/Geode-solutions/OpenGeodeWe…
JulienChampagnol Jun 24, 2026
beebc26
CollapseOrExpandAll
JulienChampagnol Jun 24, 2026
2fec093
runBrowser getAvailablePort
JulienChampagnol Jun 25, 2026
a19ca64
Apply prepare changes
JulienChampagnol Jun 25, 2026
ad3b064
cleanup
JulienChampagnol Jun 25, 2026
bcf7f3d
Merge branch 'fix/perf_run_microservices' of https://github.com/Geode…
JulienChampagnol Jun 25, 2026
aeac953
env
JulienChampagnol Jun 25, 2026
5f26611
Apply prepare changes
JulienChampagnol Jun 25, 2026
057127f
getPort
JulienChampagnol Jun 25, 2026
10ab62e
Merge branch 'fix/perf_run_microservices' of https://github.com/Geode…
JulienChampagnol Jun 25, 2026
fbf16c0
await getAvailablePort();
JulienChampagnol Jun 25, 2026
97d88e9
Apply prepare changes
JulienChampagnol Jun 25, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 38 additions & 28 deletions app/utils/local/microservices.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ import { commandExistsSync, waitForReady } from "./scripts.js";
import { microservicesMetadatasPath, projectMicroservices } from "./cleanup.js";
import { executablePath } from "./path.js";

const DEFAULT_TIMEOUT_SECONDS = 60;
const MILLISECONDS_PER_SECOND = 1000;
const DEFAULT_TIMEOUT_SECONDS = 30;
const MAX_ERROR_BUFFER_BYTES = 64 * 1024;

function getAvailablePort() {
return getPort({
Expand All @@ -23,40 +24,41 @@ function getAvailablePort() {
});
}

function resolveCommand(execPath, execName) {
const command = commandExistsSync(execName) ? execName : executablePath(execPath, execName);
return command;
}

async function runScript(
execPath,
execName,
args,
expectedResponse,
timeoutSeconds = DEFAULT_TIMEOUT_SECONDS,
) {
let command = "";
if (commandExistsSync(execName)) {
command = execName;
} else {
command = path.join(executablePath(execPath, execName));
}
const command = resolveCommand(execPath, execName);
console.log("runScript", command, args);

const child = child_process.spawn(process.platform === "win32" ? command : `"${command}"`, args, {
encoding: "utf8",
shell: true,
const child = child_process.spawn(command, args, {
stdio: ["ignore", "pipe", "pipe"],
});
child.stdout.on("data", (data) => console.log(`[${execName}] ${data.toString()}`));
child.stderr.on("data", (data) => console.log(`[${execName}] ${data.toString()}`));

child.on("close", (code) => console.log(`[${execName}] exited with code ${code}`));
child.on("kill", () => {
console.log(`[${execName}] process killed`);
});
child.name = command.replace(/^.*[\\/]/u, "");

child.on("spawn", () => {
console.log(`[${child.name}] spawned, pid=${child.pid}`);
});

const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), timeoutSeconds * MILLISECONDS_PER_SECOND);
if (typeof timer.unref === "function") timer.unref();

try {
return await pTimeout(waitForReady(child, expectedResponse), {
milliseconds: timeoutSeconds * MILLISECONDS_PER_SECOND,
message: `Timed out after ${timeoutSeconds} seconds`,
});
const result = await waitForReady(child, expectedResponse, controller.signal);
clearTimeout(timer);
return result;
} catch (error) {
clearTimeout(timer);
child.kill();
throw error;
}
Expand All @@ -73,11 +75,16 @@ async function runBack(execName, execPath, args = {}) {
}
const port = await getAvailablePort();
const backArgs = [
`--port ${port}`,
`--data_folder_path ${projectFolderPath}`,
`--upload_folder_path ${uploadFolderPath}`,
`--allowed_origin http://localhost:*`,
`--timeout ${0}`,
"--port",
String(port),
"--data_folder_path",
projectFolderPath,
"--upload_folder_path",
uploadFolderPath,
"--allowed_origin",
"http://localhost:*",
"--timeout",
"0",
];
if (process.env.NODE_ENV === "development" || !process.env.NODE_ENV) {
backArgs.push("--debug");
Expand All @@ -94,9 +101,12 @@ async function runViewer(execName, execPath, args = {}) {
}
const port = await getAvailablePort();
const viewerArgs = [
`--port ${port}`,
`--data_folder_path ${projectFolderPath}`,
`--timeout ${0}`,
"--port",
String(port),
"--data_folder_path",
projectFolderPath,
"--timeout",
"0",
];
console.log("runViewer", execPath, execName, viewerArgs);
await runScript(execPath, execName, viewerArgs, "Starting factory");
Expand Down
72 changes: 64 additions & 8 deletions app/utils/local/scripts.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
// Node imports
import child_process from "node:child_process";
import fs from "node:fs";
import { on } from "node:events";
import path from "node:path";
import readline from "node:readline";

import { appMode } from "./app_mode.js";

const MAX_ERROR_BUFFER_BYTES = 64 * 1024;

Check failure on line 9 in app/utils/local/scripts.js

View workflow job for this annotation

GitHub Actions / test / oxlint

eslint(no-magic-numbers)

No magic number: 64

function commandExistsSync(execName) {
const envPath = process.env.PATH || "";
return envPath.split(path.delimiter).some((dir) => {
Expand All @@ -14,13 +16,67 @@
});
}

async function waitForReady(child, expectedResponse) {
for await (const [data] of on(child.stdout, "data")) {
if (data.toString().includes(expectedResponse)) {
return child;
}
}
throw new Error("Process closed before signal");
function waitForReady(child, expectedResponse, signal) {
return new Promise((resolve, reject) => {
const readlineStdout = readline.createInterface({ input: child.stdout });
const readlineStderr = readline.createInterface({ input: child.stderr });

let recentOutput = "";
const recordOutput = (line) => {
recentOutput = (recentOutput + line + "\n").slice(-MAX_ERROR_BUFFER_BYTES);
};

Check failure on line 27 in app/utils/local/scripts.js

View workflow job for this annotation

GitHub Actions / test / oxlint

eslint(func-style)

Expected a function declaration.

const cleanup = () => {
readlineStdout.removeAllListeners();
readlineStdout.close();
readlineStderr.removeAllListeners();
readlineStderr.close();
child.removeListener("error", onError);
child.removeListener("close", onClose);
if (signal) signal.removeEventListener("abort", onAbort);

Check failure on line 36 in app/utils/local/scripts.js

View workflow job for this annotation

GitHub Actions / test / oxlint

eslint(curly)

Expected { after 'if' condition.
};

Check failure on line 37 in app/utils/local/scripts.js

View workflow job for this annotation

GitHub Actions / test / oxlint

eslint(func-style)

Expected a function declaration.

const onLine = (line) => {
console.log(`[${child.name}] ${line}`);
recordOutput(line);
if (line.includes(expectedResponse)) {
cleanup();
resolve(child);
}
};

Check failure on line 46 in app/utils/local/scripts.js

View workflow job for this annotation

GitHub Actions / test / oxlint

eslint(func-style)

Expected a function declaration.

const onErrLine = (line) => {
console.log(`[${child.name}] ${line}`);
recordOutput(line);
};

Check failure on line 51 in app/utils/local/scripts.js

View workflow job for this annotation

GitHub Actions / test / oxlint

eslint(func-style)

Expected a function declaration.

const onError = (err) => {
cleanup();
reject(err);
};

Check failure on line 56 in app/utils/local/scripts.js

View workflow job for this annotation

GitHub Actions / test / oxlint

eslint(func-style)

Expected a function declaration.

const onClose = (code) => {
console.log(`[${child.name}] exited with code ${code}`);
cleanup();
reject(
new Error(
`[${child.name}] exited with code ${code} before becoming ready.` +
(recentOutput ? `\nRecent output:\n${recentOutput}` : ""),
),
);
};

Check failure on line 67 in app/utils/local/scripts.js

View workflow job for this annotation

GitHub Actions / test / oxlint

eslint(func-style)

Expected a function declaration.

const onAbort = () => {
cleanup();
reject(new Error(`[${child.name}] timed out waiting for "${expectedResponse}"`));
};

Check failure on line 72 in app/utils/local/scripts.js

View workflow job for this annotation

GitHub Actions / test / oxlint

eslint(func-style)

Expected a function declaration.

readlineStdout.on("line", onLine);
readlineStderr.on("line", onErrLine);
child.once("error", onError);
child.once("close", onClose);
if (signal) signal.addEventListener("abort", onAbort, { once: true });

Check failure on line 78 in app/utils/local/scripts.js

View workflow job for this annotation

GitHub Actions / test / oxlint

eslint(curly)

Expected { after 'if' condition.
});
}

async function waitNuxt(nuxtProcess) {
Expand Down
Loading