Skip to content

Child processes #115

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 17 commits into from
Oct 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 1 addition & 7 deletions resources/js/electron-plugin/dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { app } from "electron";
import { autoUpdater } from "electron-updater";
import state from "./server/state";
import { electronApp, optimizer } from "@electron-toolkit/utils";
import { retrieveNativePHPConfig, retrievePhpIniSettings, runScheduler, startAPI, startPhpApp, startQueue, startWebsockets, } from "./server";
import { retrieveNativePHPConfig, retrievePhpIniSettings, runScheduler, startAPI, startPhpApp, startQueue, } from "./server";
import { notifyLaravel } from "./server/utils";
import { resolve } from "path";
import ps from "ps-node";
Expand Down Expand Up @@ -74,7 +74,6 @@ class NativePHP {
state.phpIni = yield this.loadPhpIni();
yield this.startPhpApp();
yield this.startQueueWorker();
yield this.startWebsockets();
this.startScheduler();
yield notifyLaravel("booted");
});
Expand Down Expand Up @@ -152,11 +151,6 @@ class NativePHP {
this.processes.push(yield startQueue());
});
}
startWebsockets() {
return __awaiter(this, void 0, void 0, function* () {
this.processes.push(yield startWebsockets());
});
}
startScheduler() {
const now = new Date();
const delay = (60 - now.getSeconds()) * 1000 + (1000 - now.getMilliseconds());
Expand Down
16 changes: 13 additions & 3 deletions resources/js/electron-plugin/dist/preload/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
import { ipcRenderer } from 'electron';
import * as remote from '@electron/remote';
import Native from './native';
const { contextBridge, ipcRenderer } = require('electron');
const remote = require('@electron/remote');
const Native = {
on: (event, callback) => {
ipcRenderer.on('native-event', (_, data) => {
event = event.replace(/^(\\)+/, '');
data.event = data.event.replace(/^(\\)+/, '');
if (event === data.event) {
return callback(data.payload, event);
}
});
}
};
window.Native = Native;
window.remote = remote;
ipcRenderer.on('log', (event, { level, message, context }) => {
Expand Down
2 changes: 2 additions & 0 deletions resources/js/electron-plugin/dist/server/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import settingsRoutes from "./api/settings";
import shellRoutes from "./api/shell";
import progressBarRoutes from "./api/progressBar";
import powerMonitorRoutes from "./api/powerMonitor";
import childProcessRoutes from "./api/childProcess";
function startAPIServer(randomSecret) {
return __awaiter(this, void 0, void 0, function* () {
const port = yield getPort({
Expand All @@ -56,6 +57,7 @@ function startAPIServer(randomSecret) {
httpServer.use("/api/menu-bar", menuBarRoutes);
httpServer.use("/api/progress-bar", progressBarRoutes);
httpServer.use("/api/power-monitor", powerMonitorRoutes);
httpServer.use("/api/child-process", childProcessRoutes);
httpServer.use("/api/broadcast", broadcastingRoutes);
if (process.env.NODE_ENV === "development") {
httpServer.use("/api/debug", debugRoutes);
Expand Down
128 changes: 128 additions & 0 deletions resources/js/electron-plugin/dist/server/api/childProcess.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import express from 'express';
import { utilityProcess } from 'electron';
import state from '../state';
import { notifyLaravel } from "../utils";
import { join } from 'path';
const router = express.Router();
function startProcess(settings) {
const { alias, cmd, cwd, env, persistent } = settings;
if (getProcess(alias) !== undefined) {
return state.processes[alias];
}
const proc = utilityProcess.fork(join(__dirname, '../../electron-plugin/dist/server/childProcess.js'), cmd, {
cwd,
serviceName: alias,
stdio: 'pipe',
env: Object.assign(Object.assign({}, process.env), env)
});
proc.stdout.on('data', (data) => {
notifyLaravel('events', {
event: 'Native\\Laravel\\Events\\ChildProcess\\MessageReceived',
payload: {
alias,
data: data.toString(),
}
});
});
proc.stderr.on('data', (data) => {
console.error('Error received from process [' + alias + ']:', data.toString());
notifyLaravel('events', {
event: 'Native\\Laravel\\Events\\ChildProcess\\ErrorReceived',
payload: {
alias,
data: data.toString(),
}
});
});
proc.on('spawn', () => {
console.log('Process [' + alias + '] spawned!');
state.processes[alias] = {
pid: proc.pid,
proc,
settings
};
notifyLaravel('events', {
event: 'Native\\Laravel\\Events\\ChildProcess\\ProcessSpawned',
payload: [alias, proc.pid]
});
});
proc.on('exit', (code) => {
console.log(`Process [${alias}] exited with code [${code}].`);
notifyLaravel('events', {
event: 'Native\\Laravel\\Events\\ChildProcess\\ProcessExited',
payload: {
alias,
code,
}
});
delete state.processes[alias];
if (persistent) {
startProcess(settings);
}
});
return {
pid: null,
proc,
settings
};
}
function stopProcess(alias) {
const proc = getProcess(alias);
if (proc === undefined) {
return;
}
if (proc.kill()) {
delete state.processes[alias];
}
}
function getProcess(alias) {
var _a;
return (_a = state.processes[alias]) === null || _a === void 0 ? void 0 : _a.proc;
}
function getSettings(alias) {
var _a;
return (_a = state.processes[alias]) === null || _a === void 0 ? void 0 : _a.settings;
}
router.post('/start', (req, res) => {
const proc = startProcess(req.body);
res.json(proc);
});
router.post('/stop', (req, res) => {
const { alias } = req.body;
stopProcess(alias);
res.sendStatus(200);
});
router.post('/restart', (req, res) => {
const { alias } = req.body;
const settings = getSettings(alias);
stopProcess(alias);
if (settings === undefined) {
res.sendStatus(410);
return;
}
const proc = startProcess(settings);
res.json(proc);
});
router.get('/get/:alias', (req, res) => {
const { alias } = req.params;
const proc = state.processes[alias];
if (proc === undefined) {
res.sendStatus(410);
return;
}
res.json(proc);
});
router.get('/', (req, res) => {
res.json(state.processes);
});
router.post('/message', (req, res) => {
const { alias, message } = req.body;
const proc = getProcess(alias);
if (proc === undefined) {
res.sendStatus(200);
return;
}
proc.postMessage(message);
res.sendStatus(200);
});
export default router;
4 changes: 4 additions & 0 deletions resources/js/electron-plugin/dist/server/api/screen.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,8 @@ router.get('/primary-display', (req, res) => {
router.get('/cursor-position', (req, res) => {
res.json(screen.getCursorScreenPoint());
});
router.get('/active', (req, res) => {
const cursor = screen.getCursorScreenPoint();
res.json(screen.getDisplayNearestPoint(cursor));
});
export default router;
2 changes: 1 addition & 1 deletion resources/js/electron-plugin/dist/server/api/window.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ router.post('/open', (req, res) => {
state.windows[id].focus();
return res.sendStatus(200);
}
let preloadPath = join(__dirname, '../../preload/index.js');
let preloadPath = join(__dirname, '../../electron-plugin/dist/preload/index.js');
let windowState = undefined;
if (req.body.rememberState === true) {
windowState = windowStateKeeper({
Expand Down
14 changes: 14 additions & 0 deletions resources/js/electron-plugin/dist/server/childProcess.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
const { spawn } = require('child_process');
const proc = spawn(process.argv[2], process.argv.slice(3), {});
process.parentPort.on('message', (message) => {
proc.stdin.write(message.data);
});
proc.stdout.on('data', (data) => {
console.log(data.toString());
});
proc.stderr.on('data', (data) => {
console.error(data.toString());
});
proc.on('close', (code) => {
process.exit(code);
});
3 changes: 1 addition & 2 deletions resources/js/electron-plugin/dist/server/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
import startWebsockets from "./websockets";
import startAPIServer from "./api";
import { retrieveNativePHPConfig, retrievePhpIniSettings, serveApp, startQueueWorker, startScheduler, } from "./php";
import { appendCookie } from "./utils";
Expand All @@ -34,4 +33,4 @@ export function runScheduler() {
export function startAPI() {
return startAPIServer(state.randomSecret);
}
export { startWebsockets, retrieveNativePHPConfig, retrievePhpIniSettings };
export { retrieveNativePHPConfig, retrievePhpIniSettings };
2 changes: 1 addition & 1 deletion resources/js/electron-plugin/dist/server/php.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ function getArgumentEnv() {
return env;
}
function getAppPath() {
let appPath = join(__dirname, '../../resources/app/').replace('app.asar', 'app.asar.unpacked');
let appPath = join(__dirname, '../../../../../resources/app/').replace('app.asar', 'app.asar.unpacked');
if (process.env.NODE_ENV === 'development' || argumentEnv.TESTING == 1) {
appPath = process.env.APP_PATH || argumentEnv.APP_PATH;
}
Expand Down
1 change: 1 addition & 0 deletions resources/js/electron-plugin/dist/server/state.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export default {
icon: null,
store: settingsStore,
randomSecret: generateRandomString(32),
processes: {},
windows: {},
findWindow(id) {
return this.windows[id] || null;
Expand Down
6 changes: 0 additions & 6 deletions resources/js/electron-plugin/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {
startAPI,
startPhpApp,
startQueue,
startWebsockets,
} from "./server";
import { notifyLaravel } from "./server/utils";
import { resolve } from "path";
Expand Down Expand Up @@ -99,7 +98,6 @@ class NativePHP {

await this.startPhpApp();
await this.startQueueWorker();
await this.startWebsockets();
this.startScheduler();

await notifyLaravel("booted");
Expand Down Expand Up @@ -186,10 +184,6 @@ class NativePHP {
this.processes.push(await startQueue());
}

private async startWebsockets() {
this.processes.push(await startWebsockets());
}

private startScheduler() {
const now = new Date();
const delay =
Expand Down
17 changes: 14 additions & 3 deletions resources/js/electron-plugin/src/preload/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
import { contextBridge, ipcRenderer } from 'electron'
import * as remote from '@electron/remote'
const { contextBridge, ipcRenderer } = require('electron')
const remote = require('@electron/remote')
const Native = {
on: (event, callback) => {
ipcRenderer.on('native-event', (_, data) => {
// Strip leading slashes
event = event.replace(/^(\\)+/, '');
data.event = data.event.replace(/^(\\)+/, '');

import Native from './native';
if (event === data.event) {
return callback(data.payload, event);
}
})
}
};

// @ts-ignore
window.Native = Native;
Expand Down
16 changes: 0 additions & 16 deletions resources/js/electron-plugin/src/preload/native.ts

This file was deleted.

2 changes: 2 additions & 0 deletions resources/js/electron-plugin/src/server/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import settingsRoutes from "./api/settings";
import shellRoutes from "./api/shell";
import progressBarRoutes from "./api/progressBar";
import powerMonitorRoutes from "./api/powerMonitor";
import childProcessRoutes from "./api/childProcess";
import { Server } from "net";

export interface APIProcess {
Expand Down Expand Up @@ -55,6 +56,7 @@ async function startAPIServer(randomSecret: string): Promise<APIProcess> {
httpServer.use("/api/menu-bar", menuBarRoutes);
httpServer.use("/api/progress-bar", progressBarRoutes);
httpServer.use("/api/power-monitor", powerMonitorRoutes);
httpServer.use("/api/child-process", childProcessRoutes);
httpServer.use("/api/broadcast", broadcastingRoutes);

if (process.env.NODE_ENV === "development") {
Expand Down
Loading
Loading