I am building an electron app and using nodejs as the backend server within the app.
How can I auto-restart the nodejs server if it encounters a crash?
I am currently using pm2 and using the following code in electron's main.js file
var pm2 = require("pm2");
pm2.connect(function(err) {
if (err) {
console.error(err);
process.exit(2);
}
pm2.start(
{
name: "mydesktopapp",
script: "./server/server.js", // nodejs Script to be run
exec_mode: "cluster",
instances: 1,
max_memory_restart: "5000M", // Optional: Restarts your app if it reaches 5GB
noDaemonMode: true,
watch: true
},
function(err, apps) {
pm2.disconnect(); // Disconnects from PM2
console.error(`Unable to start PM2: ${err}`);
if (err) throw err;
}
);
});
But this does not seem to work, as its throwing the following error:
Unable to start PM2: null
How do you guys handle this?
Thanks
Related
We used to start Angular and NestJS (based on node.js) projects using Docker containers. This solution was discontinued for various reasons, so we are looking for a way to start these projects at the start of the PC (or on a trigger) and restart the project automatically if a crash occurs.
node-windows
This package builds a Windows service from a node.js project. NestJS being based on node.js, starting it using node.js is done this way (while in the project's folder):
node PATH_TO_PROJECT\node_modules\#nestjs\cli\bin\nest.js start --config .\tsconfig.build.json
The script used:
const svc = new Service({
name: 'Test',
description: 'Test',
script:
'PATH_TO_PROJECT\\node_modules\\#nestjs\\cli\\bin\\nest.js',
scriptOptions: [
'start --watch --config PATH_TO_PROJECT\\tsconfig.build.json',
],
],
execPath: 'C:\\Program Files\\nodejs\\node.exe',
});
svc.on('install', function () {
console.log('installed');
svc.start();
});
svc.install();
The installation works as intended but in a browser, the server cannot be reached.
Questions
Is there a way to use node-windows for a NestJS project?
Is it possible to use an absolute path with the nest cli start command? (e.g nest start --config ABSOLUTE_PATH)
How would you start an Angular project the same way?
Thank you.
am use 'child_process' lib for run command
like this
server.js
const { exec } = require("child_process");
exec("npm run start", (error, stdout, stderr) => {
if (error) {
console.log(`error: ${error.message}`);
return;
}
if (stderr) {
console.log(`stderr: ${stderr}`);
return;
}
console.log(`stdout: ${stdout}`);
});
and use node-windows like this
var Service = require('node-windows').Service;
var serviceDetail = require('./servicename')();
console.log(serviceDetail);
// Create a new service object
var svc = new Service({
name: serviceDetail.name,
description: serviceDetail.detail,
script: './server.js'
});
console.log('start building up service name ' + serviceDetail.name);
// Listen for the "install" event, which indicates the
// process is available as a service.
svc.on('install',function(){
svc.start();
});
svc.install();
I've been using Google Cloud Run for a year now and the issue with cloud run containers restarts / new container start is from the beginning.
I've hosted Node + MongoDB app in Cloud Run, but cloud run container is restarting frequently. It's getting around 10 - 12 requests / second, couldn't find any performance bottleneck, requests are serving smoothly, sometimes requests are served more than normal time, might be new container instance cold start delay.
The issue I am facing is the HIGH Number of connections to the MONGODB Server. After some research I could find that I've to close mongodb connection on node process exit so I've added a graceful shutdown function.
// Function to terminate the app gracefully:
const gracefulShutdown = async () => {
console.log(`MONGODB CONNECTION CLOSED!`);
await mongoose.connection.close();
};
// This will handle process.exit():
process.on('exit', gracefulShutdown);
// This will handle kill commands, such as CTRL+C:
process.on('SIGINT', gracefulShutdown);
process.on('SIGTERM', gracefulShutdown);
// This will prevent dirty exit on code-fault crashes:
process.on('uncaughtException', gracefulShutdown);
But even after adding this, I couldn't find this graceful shutdown function is invoked while checking logs.
Does google cloud run really signals when the nodejs process in the container crashed?
Is there any way to identity a container restart or new instance creation in cloud run?
Here is the MongoDB connection code
exports.connect = () => {
try {
mongoose
.connect(MONGO.URI, {
useCreateIndex: true,
keepAlive: 1,
useNewUrlParser: true,
useUnifiedTopology: true,
useFindAndModify: false,
})
.then((docs) => {
console.log(`DB Connected`);
})
.catch((err) => {
console.log(`err`, err);
});
return mongoose.connection;
} catch (err) {
console.log(`#### Error Connecting DB`, err);
console.log(`Mongo URI: `, MONGO.URI);
}
};
Sometimes cloud run issues a high number of connections to MONGODB, and hits the connection limit of 1500 connections.
Any suggestions are appreciated! I've been facing this issue for a year now.
You should not start the node process using npm or yarn but directly as CMD ["node", "index.js"] (when you are inside a Docker container using Dockerfile)
Explanation here https://maximorlov.com/process-signals-inside-docker-containers/
I am installing a server on Digitalocean and have a MongoDB issue. I installed Mongo on the server and allowed remote access.
I created two users. One is super-user for me and the other is a regular user for the website users. I am able to connect to the mongo through Robomongo 3T (a mongo client) remotely for both users.
However, when I use the application from a browser, a simple login request gives an authentication error. Here is the error:
MongoError: not authorized on DATABASE_NAME to execute command { find: "users", filter: { email: "YYY", password: "XXX" }, limit: 1, singleBatch: true, batchSize: 1 }
Here is the realted server-side code:
Connecting the database at server.js:
MongoClient.connect(config.mongo_url, (err, client) => {
if(err) throw err
console.log('db connected')
app.locals.db = client
// start the server
app.listen(process.env.PORT || 3000, ()=>console.log('listening on port 3000!'))
});
Trying to connect to the local mongo on the server:
database.collection(config.mongo_col_user)
.findOne({
email: username,
password: hash
}, (err, user)=>{
if(err) return done(err)
if(!user) return done(null, false, {msg: 'not found'})
if(user.password)
return done(null, user)
})
I use pm2 on the server side and I use ecosystem.config.js which has the below code:
module.exports = {
apps : [
{
name: "NAME",
script: "SCRIPT_NAME",
watch: true,
env: {
"mongo_url": 'mongodb://USER_NAME:PASSWORD#localhost:27017?authMechanism=SCRAM-SHA-1&authSource=DATABASE_NAME',
"mongo_db_name": 'DATABASE_NAME',
"mongo_col_query": "COLLECTION_NAME",
}
}
]
}
Could you help with the problem please?
I have figured it out.
When I did make changes to pm2 environment file ecosystem.config.js, I did always restart pm2 with pm2 restart all. However, when you change the file, you should tell pm2 that you changed it by pm2 reload ecosystem.config.js --update-env.
Additionally, the correct syntax is no
mongodb://USER_NAME:PASSWORD#localhost:27017?authMechanism=SCRAM-SHA-1&authSource=DATABASE_NAME'
but
mongodb://USER_NAME:PASSWORD#localhost:27017/DATABASE_NAME'
I have got a react app where I need to dynamically pass the API HOST name from environment (docker run --env API_HOST=localhost)
I'm using a child process in gulp to run 'node node.js'
//run npm install then node app
cp.spawn('npm install' ,{cwd:NODE_APP_FOLDER,env:process.env}, function(error, stdout, stderr) {
if (error) {
console.error(`exec error: ${error}`);
return;
}
var server = cp.spawn('node', ['app.js'], {
cwd: NODE_APP_FOLDER,
env: {
API_HOST:'localhost'
}
});
}
but in my code within the app process.env.API_HOST return undefined
Any help would be much appreciated
I am running sailsjs, mocha, and babel on sails and mocha. When I run, my before function to start the sails app before running tests, I get this:
> PORT=9999 NODE_ENV=test mocha --recursive --compilers js:babel/register
lifting sails
1) "before all" hook
0 passing (757ms)
1 failing
1) "before all" hook:
Uncaught Error: only one instance of babel/polyfill is allowed
For the life of me, I can't figure out how to make mocha running babel and sails running babel at the same time work.
My before() code looks like this:
import Sails from 'sails'
// Global before hook
before(function (done) {
console.log('lifting sails')
// Lift Sails with test database
Sails.lift({
log: {
level: 'error'
},
models: {
connection: 'testMongoServer',
migrate: 'drop'
},
hooks: {
// sails-hook-babel: false
babel: false
}
}, function(err) {
if (err) {
return done(err);
}
// Anything else you need to set up
// ...
console.log('successfully lifted sails')
done();
});
});
I use sails-hook-babel and it works like a charm. Here to do it:
Install npm install sails-hook-babel --save-dev
Edit your bootstrap.js/ before function to load babel, i.e.
var Sails = require('sails'),
sails;
var options = {
loose : "all",
stage : 2,
ignore : null,
only : null,
extensions: null
};
global.babel = require("sails-hook-babel/node_modules/babel/register")(options);
before(function (done) {
Sails.lift({
//put your test only config here
}, function (err, server) {
sails = server;
if (err) return done(err);
// here you can load fixtures, etc.
done(err, sails);
});
});
after(function (done) {
// here you can clear fixtures, etc.
sails.lower(done);
});
Now you are able to use ES6 within your tests.
Here is the reference:
Babel issue at GitHub
My Blog, sorry it written in Bahasa Indonesia, use Google translate if you want to.