How to run and stop a subserver node.js with spawn? - javascript

I would like to start/stop a second app with node.js
I have the following 2 nodejs applications in a directory:
--app.js
|
-app2.js
Inside app.js
serverProcess = spawn('node', ['app2.js']);
process.stdin.pipe(serverProcess.stdin);
serverProcess.stdout.on('data', data => {
console.log(`child stdout:\n${data}`);
});
setTimeout(function() {
console.log('kill');
serverProcess.stdin.pause();
serverProcess.kill();
}, 5000);
Inside app2.js
const express = require('express')
const app = express()
const port = 3000
app.get('/', (req, res) => res.send('Hello World!'))
app.listen(port, () => console.log(`Example app listening on port ${port}!`))
What I would like to do is run app.js which runs app2.js for 5 seconds, logs the output to stdout, so I can see it, then terminate the process.
Currently, app2.js is killed, but app.js continues running and it is not terminating.
How would I correct my code so that app.js terminates as soon as app2.js is killed?

The app.js won't exit when app2.js killed because it will listen for input of the stdio stream due to the line:
process.stdin.pipe(serverProcess.stdin);
You either have to write process.stdin.pause() (not serverProcess) after your console.log('kill').
Or remove the process.stdin.pipe(serverProcess.stdin) completely as you do not use the input you get via stdin.

Related

EADDRINUSE: address already in use when adding require

On request my server should execute a cmd command and deploy.js file. Everything works fine, but if I add this line const { getSimpleMessage } = require('../src/server') I get the error that port 3000 is already in use. Why is this happening?
Server.js:
app.post("/", (req,res) =>{
console.log("Get from /");
SimpleMessage = 'Hello world';
exec('npx hardhat run scripts/deploy.js --network goerli',
(error, stdout, stderr) => {
console.log(stdout);
console.log(stderr);
if (error !== null) {
console.log("v error")
console.log(`exec error: ${error}`);
}
});
res.send("Server received the request");
});
// starting the server
app.listen(3000, () => {
console.log('listening on port 3000');
});
Deploy.js:
const { getSimpleMessage } = require('../src/server'); //THIS LINE CAUSES ERROR
async function main() {
const HelloWorld = await ethers.getContractFactory("HelloWorld");
// Start deployment, returning a promise that resolves to a contract object
const hello_world = await HelloWorld.deploy("HelloWorld");
console.log("Contract deployed to address:", hello_world.address);
}
main()
.then(() => process.exit(0))
.catch(error => {
console.error(error);
process.exit(1);
});
I run the file with command: node src/server.
When you run require('../src/server'); in deploy.js file, all code of the src/server.js part is run, including the part app.listen(3000, ...). If the server is already running (using node src/server.js command) the port 3000 is already in use and running deploy.js (and thus attempting to run app.listen(3000, ...)) results in an error.
The simplest solution would be to separate the logic. If you want to keep both the getSimpleMessage and app declarations in the src/server.js file, you can remove the app.listen part from the file and instead export the app object. Then create e.g index.js file that imports the app object and runs the app.listen part.
./index.js:
const { app } = require('./src/server');
// starting the server
app.listen(3000, () => {
console.log('listening on port 3000');
});
However, I would suggest that more clean solution would be to just put getSimpleMessage function in a separate file (if possible).
When the server is running and receives a POST / request, it deploys Deploy.js, which causes the
app.listen(3000, ...)
command in server.js to be executed again, in another process. There would then be two processes both listening to port 3000, which leads to the observed error.
Perhaps you need to separate the getSimpleMessage function out of the server.js file.

How to concurrently run blocking and non blocking code?

I need to be able to run some code that is going to be blocking and some other code that will then, when blocked, start some other actions.
The use-case is the follows:
I have a file, called index.ts, running an express and socket server
I have a testfile, called test.spec.ts, that needs to be able to start the express server and then initiate some commands for running tests either via HTTP request or socket message(I would prefer HTTP)
The only way I found to keep the webserver alive is instantiating it with
import { spawnSync } from 'child_process';
spawnSync('ts-node', ['path/to/index.ts"], { cwd: "path/to/workdir"});
which will block until the child process is killed ( could be up to 30min later ).
Is there a way to split into two processes, one that gets blocked when starting it and one continuing to work that exposes some functions for interactions with the test file?
My target would look like this:
// index.ts
import * as express from "express";
const app = express();
const port = 3000;
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.listen(port, () => {
console.log(`Example app listening on port ${port}`);
});
// test.spec.ts
import { spawnSync } from 'child_process';
describe("Test",()=>{
it("Test", async ()=>{
// create somehow a child process that should block
const childProcess = ...
childProcess.do(spawnSync('ts-node', ['path/to/index.ts'], {cwd: 'path/to/workdir'}) //should block now
// the following code should run in parallel
await new Promise(r => setTimeout(r, 5000)); //wait some time until the webserver is ready
fetch('http://localhost:3000').then((ret)=>{
expect(ret,'to be Hello World').to.contain('Hello World!");
})
... // more tests
});
});
I think I found the reason and a possible solution myself.
Node always runs in a single process therefore it can't work. Luckily I was able to discover a totally different approach. I installed the npm-run-all package and created a new script in my package.json file calling run-p script1 script2. This way I can run both in parallel and the process with the webserver stays alive until all tests are run

Doesn't print a killed node process with node.js

I want to simulate a crash with Node.js by using process.kill. I did a basic app with express.js in terminal #1
app.js
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.send('Hi!');
});
const server = app.listen(3000, () => console.log('Server ready'));
console.log(process.pid);
process.on('SIGINT', function () {
console.log('Simulate crash');
});
Then, I'm running in another terminal (terminal #2) a node file that kill the process of terminal #1
kill.js
const fs = require('fs');
const args = process.argv.slice(2)[0];
process.kill(args, 'SIGINT');
So when I run kill.js with the following command $ node kill.js YOURPROCESSPID in the terminal #2, it didn't print the "simulate crash" in the terminal #1. I'd like to know how to make this happen. Thank you.
I also added the console down here.

How to call a function when I run nodejs server

I need my server to go up, call a function then go down.
From what I've seen on the web I should use this section of code:
const express = require('express');
const app = express();
app.on('listening', () => {
console.log("Server up...");
console.log("Server going down...");
});
but for some reason this does not work for me.
The program does go up but the logs are not written.
const express = require("express");
const app = express();
const server = app.listen(3000);
//call whatever function you need here
server.close(() => console.log("Server going down..."));
First we start the server using app.listen and later when you want to close it just do server.close()

Why doesn't console.log print to the CLI?

I'm following a YouTube tutorial on NodeJs, and for some reason my console.log commands unexpectedly stopped working. Here is the sample code from the tutorial as I've typed it:
const http = require('http');
const server = http.createServer();
server.on('connection', (socket) => {
console.log('New connection')
});
server.listen(3000);
console.log('Listening on port 3000...');
After saving I try using node and nodejs
node app.js
nodejs app.js
but they print nothing.

Categories