mirror of
https://github.com/logos-storage/logos-storage-installer.git
synced 2026-02-17 03:53:08 +00:00
cleanup processControl
This commit is contained in:
parent
7661d829cb
commit
5fcb55015a
@ -15,6 +15,7 @@ export const mockConfigService = {
|
||||
get: vi.fn(),
|
||||
saveConfig: vi.fn(),
|
||||
loadConfig: vi.fn(),
|
||||
writeCodexConfigFile: vi.fn(),
|
||||
};
|
||||
|
||||
export const mockFsService = {
|
||||
@ -32,6 +33,7 @@ export const mockFsService = {
|
||||
|
||||
export const mockShellService = {
|
||||
run: vi.fn(),
|
||||
spawnDetachedProcess: vi.fn(),
|
||||
};
|
||||
|
||||
export const mockOsService = {
|
||||
@ -39,4 +41,10 @@ export const mockOsService = {
|
||||
isDarwin: vi.fn(),
|
||||
isLinux: vi.fn(),
|
||||
getWorkingDir: vi.fn(),
|
||||
listProcesses: vi.fn(),
|
||||
};
|
||||
|
||||
export const mockCodexGlobals = {
|
||||
getPublicIp: vi.fn(),
|
||||
getTestnetSPRs: vi.fn(),
|
||||
};
|
||||
|
||||
@ -1,95 +1,49 @@
|
||||
import fs from "fs";
|
||||
import { spawn, exec } from "child_process";
|
||||
import psList from 'ps-list';
|
||||
|
||||
export class ProcessControl {
|
||||
constructor(configService, shellService, osService, fsService) {
|
||||
constructor(configService, shellService, osService, fsService, codexGlobals) {
|
||||
this.configService = configService;
|
||||
this.config = configService.get();
|
||||
this.shell = shellService;
|
||||
this.os = osService;
|
||||
this.fs = fsService;
|
||||
this.codexGlobals;
|
||||
}
|
||||
|
||||
getPublicIp = async () => {
|
||||
getCodexProcesses = async () => {
|
||||
const processes = await this.os.listProcesses();
|
||||
if (this.os.isWindows()) {
|
||||
const result = await this.shell.run(
|
||||
"for /f \"delims=\" %a in ('curl -s --ssl-reqd ip.codex.storage') do @echo %a",
|
||||
);
|
||||
return result.trim();
|
||||
return processes.filter((p) => p.name === "codex.exe");
|
||||
} else {
|
||||
return await this.shell.run("curl -s https://ip.codex.storage");
|
||||
return processes.filter((p) => p.name === "codex");
|
||||
}
|
||||
};
|
||||
|
||||
detectThing = async () => {
|
||||
console.log("detecting...");
|
||||
getNumberOfCodexProcesses = async () => {
|
||||
return (await this.getCodexProcesses()).length;
|
||||
};
|
||||
|
||||
const processes = await psList();
|
||||
const codexProcesses = processes.filter((p) => p.name === "codex.exe");
|
||||
if (codexProcesses.length > 0) {
|
||||
console.log("Codex is already running.");
|
||||
codexProcesses.forEach((p) => {
|
||||
console.log(`PID: ${JSON.stringify(p)}`);
|
||||
});
|
||||
|
||||
console.log("Stopping codex...");
|
||||
await this.stopThing(codexProcesses[0].pid);
|
||||
await this.detectThing();
|
||||
} else {
|
||||
console.log("Codex is not running.");
|
||||
}
|
||||
}
|
||||
|
||||
stopThing = async (pid) => {
|
||||
console.log("stopping process...");
|
||||
stopCodexProcess = async () => {
|
||||
const processes = await this.getCodexProcesses();
|
||||
if (processes.length < 1) throw new Error("No codex process found");
|
||||
|
||||
const pid = processes[0].pid;
|
||||
process.kill(pid, "SIGINT");
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 2000));
|
||||
}
|
||||
};
|
||||
|
||||
doThing = async () => {
|
||||
if (this.config.dataDir.length < 1)
|
||||
throw new Error("Missing config: dataDir");
|
||||
if (this.config.logsDir.length < 1)
|
||||
throw new Error("Missing config: logsDir");
|
||||
startCodexProcess = async () => {
|
||||
this.saveCodexConfigFile();
|
||||
this.startCodex();
|
||||
};
|
||||
|
||||
console.log("start a codex detached");
|
||||
saveCodexConfigFile = async () => {
|
||||
const publicIp = await this.codexGlobals.getPublicIp();
|
||||
const bootstrapNodes = await this.codexGlobals.getTestnetSPRs();
|
||||
this.configService.writeCodexConfigFile(publicIp, bootstrapNodes);
|
||||
};
|
||||
|
||||
startCodex = async () => {
|
||||
const executable = this.config.codexExe;
|
||||
const args = [`--config-file=${this.config.codexConfigFilePath}`];
|
||||
const bootstrapNodes = [
|
||||
"spr:CiUIAhIhAiJvIcA_ZwPZ9ugVKDbmqwhJZaig5zKyLiuaicRcCGqLEgIDARo8CicAJQgCEiECIm8hwD9nA9n26BUoNuarCEllqKDnMrIuK5qJxFwIaosQ3d6esAYaCwoJBJ_f8zKRAnU6KkYwRAIgM0MvWNJL296kJ9gWvfatfmVvT-A7O2s8Mxp8l9c8EW0CIC-h-H-jBVSgFjg3Eny2u33qF7BDnWFzo7fGfZ7_qc9P",
|
||||
];
|
||||
const publicIp = await this.getPublicIp();
|
||||
|
||||
this.configService.writeCodexConfigFile(publicIp, bootstrapNodes);
|
||||
|
||||
const command = `"${executable}" ${args.join(" ")}`;
|
||||
console.log("command: " + command);
|
||||
console.log("\n\n");
|
||||
|
||||
var child = spawn(executable, args, {
|
||||
detached: true,
|
||||
//stdio: ["ignore", "ignore", "ignore"],
|
||||
});
|
||||
|
||||
child.stdout.on("data", (data) => {
|
||||
console.log(`stdout: ${data}`);
|
||||
});
|
||||
|
||||
child.stderr.on("data", (data) => {
|
||||
console.error(`stderr: ${data}`);
|
||||
});
|
||||
|
||||
child.on("close", (code) => {
|
||||
console.log(`child process exited with code ${code}`);
|
||||
});
|
||||
|
||||
child.unref();
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 2000));
|
||||
return;
|
||||
await this.shell.spawnDetachedProcess(executable, args);
|
||||
};
|
||||
}
|
||||
|
||||
@ -35,6 +35,7 @@ import { Installer } from "./handlers/installer.js";
|
||||
import { ShellService } from "./services/shellService.js";
|
||||
import { OsService } from "./services/osService.js";
|
||||
import { ProcessControl } from "./handlers/processControl.js";
|
||||
import { CodexGlobals } from "./services/codexGlobals.js";
|
||||
|
||||
async function showNavigationMenu() {
|
||||
console.log("\n");
|
||||
@ -133,14 +134,20 @@ export async function main() {
|
||||
new DataDirMover(fsService, uiService),
|
||||
);
|
||||
|
||||
const codexGlobals = new CodexGlobals();
|
||||
|
||||
const processControl = new ProcessControl(
|
||||
configService,
|
||||
shellService,
|
||||
osService,
|
||||
fsService,
|
||||
);
|
||||
|
||||
console.log("ip: " + (await codexGlobals.getPublicIp()));
|
||||
console.log("spr: " + (await codexGlobals.getTestnetSprs()));
|
||||
|
||||
//await processControl.doThing();
|
||||
await processControl.detectThing();
|
||||
// await processControl.detectThing();
|
||||
return;
|
||||
|
||||
await mainMenu.show();
|
||||
|
||||
12
src/services/codexGlobals.js
Normal file
12
src/services/codexGlobals.js
Normal file
@ -0,0 +1,12 @@
|
||||
import axios from "axios";
|
||||
|
||||
export class CodexGlobals {
|
||||
getPublicIp = async () => {
|
||||
return (await axios.get(`https://ip.codex.storage`)).data;
|
||||
};
|
||||
|
||||
getTestnetSPRs = async () => {
|
||||
const result = (await axios.get(`https://spr.codex.storage/testnet`)).data;
|
||||
return result.split("\n").filter((line) => line.length > 0);
|
||||
};
|
||||
}
|
||||
@ -77,7 +77,23 @@ export class ConfigService {
|
||||
return this.fs.pathJoin([this.config.logsDir, "codex.log"]);
|
||||
};
|
||||
|
||||
missing = (name) => {
|
||||
throw new Error(`Missing config value: ${name}`);
|
||||
};
|
||||
|
||||
validateConfiguration = () => {
|
||||
if (this.config.codexExe.length < 1) this.missing("codexExe");
|
||||
if (this.config.codexConfigFilePath.length < 1)
|
||||
this.missing("codexConfigFilePath");
|
||||
if (this.config.dataDir.length < 1) this.missing("dataDir");
|
||||
if (this.config.logsDir.length < 1) this.missing("logsDir");
|
||||
if (this.config.storageQuota < 1024 * 1024 * 100)
|
||||
throw new Error("Storage quota must be at least 100MB");
|
||||
};
|
||||
|
||||
writeCodexConfigFile = (publicIp, bootstrapNodes) => {
|
||||
this.validateConfiguration();
|
||||
|
||||
const nl = "\n";
|
||||
const bootNodes = bootstrapNodes.map((v) => `"${v}"`).join(",");
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import os from "os";
|
||||
import psList from "ps-list";
|
||||
|
||||
export class OsService {
|
||||
constructor() {
|
||||
@ -20,4 +21,8 @@ export class OsService {
|
||||
getWorkingDir = () => {
|
||||
return process.cwd();
|
||||
};
|
||||
|
||||
listProcesses = async () => {
|
||||
await psList();
|
||||
};
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { exec } from "child_process";
|
||||
import { exec, spawn } from "child_process";
|
||||
import { promisify } from "util";
|
||||
|
||||
export class ShellService {
|
||||
@ -6,7 +6,7 @@ export class ShellService {
|
||||
this.execAsync = promisify(exec);
|
||||
}
|
||||
|
||||
async run(command) {
|
||||
run = async (command) => {
|
||||
try {
|
||||
const { stdout, stderr } = await this.execAsync(command);
|
||||
return stdout;
|
||||
@ -14,5 +14,28 @@ export class ShellService {
|
||||
console.error("Error:", error.message);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
spawnDetachedProcess = async (cmd, args) => {
|
||||
var child = spawn(cmd, args, {
|
||||
detached: true,
|
||||
stdio: ["ignore", "ignore", "ignore"],
|
||||
});
|
||||
|
||||
// child.stdout.on("data", (data) => {
|
||||
// console.log(`stdout: ${data}`);
|
||||
// });
|
||||
|
||||
// child.stderr.on("data", (data) => {
|
||||
// console.error(`stderr: ${data}`);
|
||||
// });
|
||||
|
||||
// child.on("close", (code) => {
|
||||
// console.log(`child process exited with code ${code}`);
|
||||
// });
|
||||
|
||||
child.unref();
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 2000));
|
||||
};
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user