Skip to content

Commit

Permalink
Implement serve detached (process) CLI option
Browse files Browse the repository at this point in the history
  • Loading branch information
t-ski committed Nov 11, 2024
1 parent d441684 commit 5a3fd45
Show file tree
Hide file tree
Showing 12 changed files with 92 additions and 29 deletions.
10 changes: 5 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/cluster/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@rapidjs.org/cluster",
"version": "0.2.1",
"version": "0.2.2",
"description": "Web server cluster (process and thread pool) utility for rJS.",
"author": "Thassilo Martin Schiepanski",
"license": "Apache-2.0",
Expand Down
4 changes: 4 additions & 0 deletions packages/cluster/src/AWorkerPool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ export abstract class AWorkerPool<

private aliveWorkers: number = 0;

protected destroyed: boolean = false;

constructor(
workerModulePath: string,
adapterConfig: IAdapterConfiguration,
Expand Down Expand Up @@ -213,6 +215,8 @@ export abstract class AWorkerPool<
}

public destroy() {
this.destroyed = true;

Array.from(this.activeWorkers.keys())
.concat(this.idleWorkers)
.forEach((worker: Worker) => {
Expand Down
3 changes: 2 additions & 1 deletion packages/cluster/src/thread/ThreadPool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ export class ThreadPool<I = unknown, O = unknown> extends AWorkerPool<
this.deactivateWorkerWithError(thread, errMessage);
});
thread.on("exit", (exitCode: number) => {
if ([0, WORKER_ERROR_CODE].includes(exitCode)) return;
if (this.destroyed || [0, WORKER_ERROR_CODE].includes(exitCode))
return;

this.deactivateWorkerWithError(thread, EClusterError.WORKER_EXIT);

Expand Down
2 changes: 1 addition & 1 deletion packages/rjs-build/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@rapidjs.org/rjs-build",
"version": "0.2.1",
"version": "0.2.2",
"description": "Core builds functionality utility for rJS.",
"author": "Thassilo Martin Schiepanski",
"license": "Apache-2.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/rjs-handler/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@rapidjs.org/rjs-handler",
"version": "0.2.1",
"version": "0.2.2",
"description": "Core HTTP-based request handler utility for rJS.",
"author": "Thassilo Martin Schiepanski",
"license": "Apache-2.0",
Expand Down
6 changes: 5 additions & 1 deletion packages/rjs-handler/src/TypeResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ export class TypeResolver {
return isSet ? obj : null;
},
array<T>(): T[] {
return isSet && Array.isArray(obj) ? obj : [];
return isSet
? Array.isArray(obj)
? ([obj].flat() as T[])
: []
: [];
},
string(): string {
return isSet ? (obj as unknown as string).toString() : null;
Expand Down
2 changes: 1 addition & 1 deletion packages/rjs-server/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@rapidjs.org/rjs-server",
"version": "0.2.1",
"version": "0.2.2",
"description": "Core web server utility for rJS.",
"author": "Thassilo Martin Schiepanski",
"license": "Apache-2.0",
Expand Down
3 changes: 2 additions & 1 deletion packages/rjs-server/src/adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { ISerialRequest, ISerialResponse } from "./.shared/global.interfaces";
import { IHandlerEnv, Handler } from "@rapidjs.org/rjs-handler";

export default function (coreOptions: { env: IHandlerEnv; options: TJSON }) {
const handler: Handler = new Handler(coreOptions.env, coreOptions.options); // TODO: Await for preretrieval done if not dev mode
const handler: Handler = new Handler(coreOptions.env, coreOptions.options);
// TODO: Await for preretrieval done if not dev mode

return async (sReq: ISerialRequest): Promise<ISerialResponse> => {
return await handler.activate(sReq);
Expand Down
2 changes: 1 addition & 1 deletion packages/rjs/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@rapidjs.org/rjs",
"version": "0.2.1",
"version": "0.2.2",
"description": "rJS (pron. ‘rapidJS’) is a plugin-based build interface, and a progressive web server based on virtual build capabilities.",
"author": "Thassilo Martin Schiepanski",
"license": "Apache-2.0",
Expand Down
61 changes: 45 additions & 16 deletions packages/rjs/src/cli/registry/_serve.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,63 @@
import { ChildProcess, fork } from "child_process";

import { Printer } from "../../.shared/Printer";
import { Args } from "../../.shared/Args";
import { DEV_MODE_PREFIX } from "../local.constants";
import { FileServer, createFileServer } from "../../FileServer";
import { Command } from "../Command";
import { join } from "path";
import { IServeData } from "./detached/serve";

// TODO: Print virtual files for overview?
// TODO: Interactive mode?
new Command("serve", async () => {
const dev = Args.parseFlag("dev", "D");
const cert = Args.parseOption("tls-cert", "C").string();

const tls = {
cert: cert,
key: Args.parseOption("tls-key", "K").string()
};

const server: FileServer = await createFileServer({
dev,
tls,

const serveData: IServeData = {
dev: Args.parseFlag("dev", "D"),
tls: {
cert: Args.parseOption("tls-cert", "C").string(),
key: Args.parseOption("tls-key", "K").string()
},
cwd: Args.parseOption("working-dir", "W").string() ?? process.cwd(),
apiDirPath: Args.parseOption("api-dir").string(),
sourceDirPath: Args.parseOption("plugins-dir").string(),
publicDirPath: Args.parseOption("public-dir").string(),
port: Args.parseOption("port", "P").number()
});
};
const detachedModulePath: string = join(__dirname, "./detached/serve");

const port: number = Args.parseFlag("detached")
? await new Promise<number>((resolve) => {
const detachProcess: ChildProcess = fork(detachedModulePath);

detachProcess.on("message", (message: string) => {
resolve(parseInt(message));

detachProcess.disconnect();
detachProcess.unref();

Printer.global.stdout(
Printer.format(
`PID (detached): ${Printer.format(
detachProcess.pid.toString(),
[Printer.escapes.PRIMARY_COLOR_FG],
[39]
)}`,
[2],
[22]
)
);
});

detachProcess.send(serveData);
})
: await (
(await import(detachedModulePath)) as {
serve: (data: IServeData) => Promise<number>;
}
).serve(serveData);

Printer.global.stdout(
`${dev ? DEV_MODE_PREFIX : ""}Server listening on ${Printer.format(
`http${tls.cert ? "s" : ""}://localhost:${server.port}`,
`${serveData.dev ? DEV_MODE_PREFIX : ""}Server listening on ${Printer.format(
`http${serveData.tls.cert ? "s" : ""}://localhost:${port}`,
[Printer.escapes.TERTIARY_COLOR_FG]
)}.`
);
Expand Down
24 changes: 24 additions & 0 deletions packages/rjs/src/cli/registry/detached/serve.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { FileServer, createFileServer } from "../../../FileServer";

export interface IServeData {
dev: boolean;
tls: {
cert: string | Buffer;
key: string | Buffer;
};
cwd: string;
apiDirPath: string;
sourceDirPath: string;
publicDirPath: string;
port: number;
}

export async function serve(data: IServeData): Promise<number> {
const server: FileServer = await createFileServer(data);

return server.port;
}

process.on("message", async (data: IServeData) => {
process.send(await serve(data));
});

0 comments on commit 5a3fd45

Please sign in to comment.