This commit is contained in:
Rizky 2024-01-25 13:32:34 +07:00
parent 5e8a44765b
commit 6959145d00
6 changed files with 91 additions and 26 deletions

1
.gitignore vendored
View File

@ -179,3 +179,4 @@ app/srv
app/db app/db
app/static app/static
.data .data
.pm_port

BIN
bun.lockb

Binary file not shown.

BIN
dockerzip

Binary file not shown.

View File

@ -4,7 +4,7 @@
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "bun run --silent --watch ./pkgs/index.ts dev", "dev": "bun run --silent --watch ./pkgs/index.ts dev",
"prod": "bun run --silent ./pkgs/index.ts", "prod": "bun run --silent ./pkgs/prod.ts",
"pkgs-upgrade": "bun run --silent ./pkgs/upgrade.ts" "pkgs-upgrade": "bun run --silent ./pkgs/upgrade.ts"
}, },
"workspaces": [ "workspaces": [
@ -18,6 +18,7 @@
"typescript": "^5.0.0" "typescript": "^5.0.0"
}, },
"dependencies": { "dependencies": {
"exit-hook": "^4.0.0",
"firebase-admin": "^11.11.0" "firebase-admin": "^11.11.0"
} }
} }

63
pkgs/prod.ts Normal file
View File

@ -0,0 +1,63 @@
import { Subprocess } from "bun";
import exitHook from "exit-hook";
import { checkPort, randomBetween } from "utils/ensure";
let port = 0;
try {
port = parseInt(await Bun.file(".pm_port").text());
} catch (e) {
while (true) {
port = randomBetween(5000, 15000);
if (await checkPort(port)) {
Bun.write(".pm_port", port.toString());
break;
}
}
}
exitHook((signal) => {
if (main.process && !main.process.killed) {
main.process.kill();
}
console.log(`Exiting with signal: ${signal}`);
});
const main = {
process: null as null | Subprocess,
restart: {
timeout: null as any,
},
};
console.log("Process Manager running at port:", port);
const startMain = () => {
let mode = "started";
if (main.process && !main.process.killed) return;
if (main.process && main.process.killed) mode = "restarted";
main.process = Bun.spawn({
cmd: ["bun", "run", "pkgs/index.ts"],
cwd: process.cwd(),
stdout: "inherit",
stderr: "inherit",
onExit(subprocess, exitCode, signalCode, error) {
clearTimeout(main.restart.timeout);
main.restart.timeout = setTimeout(startMain, 500);
},
});
console.log(`Main process`, mode, "pid:", main.process.pid);
};
startMain();
Bun.serve({
port,
async fetch(request, server) {
if (main.process && !main.process.killed) {
main.process.kill();
await main.process.exited;
}
return new Response("OK");
},
});

View File

@ -3,12 +3,27 @@ import { g } from "./global";
export const ensureNotRunning = async () => { export const ensureNotRunning = async () => {
await new Promise<void>(async (resolve) => { await new Promise<void>(async (resolve) => {
const checkPort = () => { if (!(await checkPort(g.port))) {
g.log.warn(`Port ${g.port} is used, waiting...`);
setInterval(async () => {
if (await checkPort(g.port)) resolve();
}, 500);
} else {
resolve();
}
});
};
export function randomBetween(min: number, max: number) {
return Math.floor(Math.random() * (max - min + 1) + min);
}
export const checkPort = (port: number) => {
return new Promise<boolean>(async (done) => { return new Promise<boolean>(async (done) => {
try { try {
const s = await connect({ const s = await connect({
hostname: "0.0.0.0", hostname: "0.0.0.0",
port: g.port, port,
socket: { socket: {
open(socket) {}, open(socket) {},
data(socket, data) {}, data(socket, data) {},
@ -24,18 +39,3 @@ export const ensureNotRunning = async () => {
} }
}); });
}; };
if (!(await checkPort())) {
g.log.warn(`Port ${g.port} is used, waiting...`);
setInterval(async () => {
if (await checkPort()) resolve();
}, 500);
} else {
resolve();
}
});
};
export function randomBetween(min: number, max: number) {
return Math.floor(Math.random() * (max - min + 1) + min);
}