mirror of
https://github.com/HeyPuter/puter.git
synced 2026-05-29 21:01:27 +00:00
dev: separate process management from DevWatcherService
This commit is contained in:
@@ -34,7 +34,7 @@ const { PuterFSModule } = require("./src/modules/puterfs/PuterFSModule.js");
|
||||
const { PerfMonModule } = require("./src/modules/perfmon/PerfMonModule.js");
|
||||
const { AppsModule } = require("./src/modules/apps/AppsModule.js");
|
||||
const { DevelopmentModule } = require("./src/modules/development/DevelopmentModule.js");
|
||||
|
||||
const { HostOSModule } = require("./src/modules/hostos/HostOSModule.js");
|
||||
|
||||
module.exports = {
|
||||
helloworld: () => {
|
||||
@@ -52,6 +52,7 @@ module.exports = {
|
||||
EssentialModules: [
|
||||
Core2Module,
|
||||
PuterFSModule,
|
||||
HostOSModule,
|
||||
CoreModule,
|
||||
WebModule,
|
||||
TemplateModule,
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
const { AdvancedBase } = require("@heyputer/putility");
|
||||
|
||||
class HostOSModule extends AdvancedBase {
|
||||
async install (context) {
|
||||
const services = context.get('services');
|
||||
|
||||
const ProcessService = require('./ProcessService');
|
||||
services.registerService('process', ProcessService);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
HostOSModule,
|
||||
};
|
||||
@@ -0,0 +1,97 @@
|
||||
const BaseService = require("../../services/BaseService");
|
||||
|
||||
class ProxyLogger {
|
||||
constructor (log) {
|
||||
this.log = log;
|
||||
}
|
||||
attach (stream) {
|
||||
let buffer = '';
|
||||
stream.on('data', (chunk) => {
|
||||
buffer += chunk.toString();
|
||||
let lineEndIndex = buffer.indexOf('\n');
|
||||
while (lineEndIndex !== -1) {
|
||||
const line = buffer.substring(0, lineEndIndex);
|
||||
this.log(line);
|
||||
buffer = buffer.substring(lineEndIndex + 1);
|
||||
lineEndIndex = buffer.indexOf('\n');
|
||||
}
|
||||
});
|
||||
|
||||
stream.on('end', () => {
|
||||
if (buffer.length) {
|
||||
this.log(buffer);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class ProcessService extends BaseService {
|
||||
static MODULES = {
|
||||
path: require('path'),
|
||||
spawn: require('child_process').spawn,
|
||||
};
|
||||
|
||||
_construct () {
|
||||
this.instances = [];
|
||||
}
|
||||
|
||||
async _init (args) {
|
||||
this.args = args;
|
||||
|
||||
process.on('exit', () => {
|
||||
this.exit_all_();
|
||||
})
|
||||
}
|
||||
|
||||
log_ (name, isErr, line) {
|
||||
let txt = `[${name}:`;
|
||||
txt += isErr
|
||||
? `\x1B[34;1m2\x1B[0m`
|
||||
: `\x1B[32;1m1\x1B[0m`;
|
||||
txt += '] ' + line;
|
||||
this.log.info(txt);
|
||||
}
|
||||
|
||||
async exit_all_ () {
|
||||
for ( const { proc } of this.instances ) {
|
||||
proc.kill();
|
||||
}
|
||||
}
|
||||
|
||||
async start ({ name, fullpath, command, args, env }) {
|
||||
this.log.info(`Starting ${name} in ${fullpath}`);
|
||||
const env_processed = { ...(env ?? {}) };
|
||||
for ( const k in env_processed ) {
|
||||
if ( typeof env_processed[k] !== 'function' ) continue;
|
||||
env_processed[k] = env_processed[k]({
|
||||
global_config: this.global_config
|
||||
});
|
||||
}
|
||||
console.log(
|
||||
'command',
|
||||
command,
|
||||
...args
|
||||
)
|
||||
const proc = this.modules.spawn(command, args, {
|
||||
shell: true,
|
||||
env: {
|
||||
...process.env,
|
||||
...env_processed,
|
||||
},
|
||||
cwd: fullpath,
|
||||
});
|
||||
this.instances.push({
|
||||
name, proc,
|
||||
});
|
||||
const out = new ProxyLogger((line) => this.log_(name, false, line));
|
||||
out.attach(proc.stdout);
|
||||
const err = new ProxyLogger((line) => this.log_(name, true, line));
|
||||
err.attach(proc.stderr);
|
||||
proc.on('exit', () => {
|
||||
this.log.info(`[${name}:exit] Process exited (${proc.exitCode})`);
|
||||
this.instances = this.instances.filter((inst) => inst.proc !== proc);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ProcessService;
|
||||
@@ -53,16 +53,8 @@ class DevWatcherService extends BaseService {
|
||||
spawn: require('child_process').spawn,
|
||||
};
|
||||
|
||||
_construct () {
|
||||
this.instances = [];
|
||||
}
|
||||
|
||||
async _init (args) {
|
||||
this.args = args;
|
||||
|
||||
process.on('exit', () => {
|
||||
this.exit_all_();
|
||||
})
|
||||
}
|
||||
|
||||
// Oh geez we need to wait for the web server to initialize
|
||||
@@ -71,13 +63,16 @@ class DevWatcherService extends BaseService {
|
||||
// this was to debug the first time, like Ahhhhhh!!
|
||||
// but hey at least we have this convenient event listener.
|
||||
async ['__on_ready.webserver'] () {
|
||||
const svc_process = this.services.get('process');
|
||||
|
||||
const { root, commands } = this.args;
|
||||
let promises = [];
|
||||
for ( const entry of commands ) {
|
||||
const { directory } = entry;
|
||||
const fullpath = this.modules.path.join(
|
||||
root, directory);
|
||||
promises.push(this.start_({ ...entry, fullpath }));
|
||||
// promises.push(this.start_({ ...entry, fullpath }));
|
||||
promises.push(svc_process.start({ ...entry, fullpath }));
|
||||
}
|
||||
await Promise.all(promises);
|
||||
|
||||
@@ -85,56 +80,6 @@ class DevWatcherService extends BaseService {
|
||||
// run so we just wait a bit before we say we're ready.
|
||||
await new Promise((resolve) => setTimeout(resolve, 5000));
|
||||
}
|
||||
|
||||
log_ (name, isErr, line) {
|
||||
let txt = `[${name}:`;
|
||||
txt += isErr
|
||||
? `\x1B[34;1m2\x1B[0m`
|
||||
: `\x1B[32;1m1\x1B[0m`;
|
||||
txt += '] ' + line;
|
||||
this.log.info(txt);
|
||||
}
|
||||
|
||||
async start_ ({ name, fullpath, command, args, env }) {
|
||||
this.log.info(`Starting ${name} in ${fullpath}`);
|
||||
const env_processed = { ...(env ?? {}) };
|
||||
for ( const k in env_processed ) {
|
||||
if ( typeof env_processed[k] !== 'function' ) continue;
|
||||
env_processed[k] = env_processed[k]({
|
||||
global_config: this.global_config
|
||||
});
|
||||
}
|
||||
console.log(
|
||||
'command',
|
||||
command,
|
||||
...args
|
||||
)
|
||||
const proc = this.modules.spawn(command, args, {
|
||||
shell: true,
|
||||
env: {
|
||||
...process.env,
|
||||
...env_processed,
|
||||
},
|
||||
cwd: fullpath,
|
||||
});
|
||||
this.instances.push({
|
||||
name, proc,
|
||||
});
|
||||
const out = new ProxyLogger((line) => this.log_(name, false, line));
|
||||
out.attach(proc.stdout);
|
||||
const err = new ProxyLogger((line) => this.log_(name, true, line));
|
||||
err.attach(proc.stderr);
|
||||
proc.on('exit', () => {
|
||||
this.log.info(`[${name}:exit] Process exited (${proc.exitCode})`);
|
||||
this.instances = this.instances.filter((inst) => inst.proc !== proc);
|
||||
})
|
||||
}
|
||||
|
||||
async exit_all_ () {
|
||||
for ( const { proc } of this.instances ) {
|
||||
proc.kill();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = DevWatcherService;
|
||||
|
||||
Reference in New Issue
Block a user