Why my RestFul API with express and nodejs crashed everyday? - javascript

I have restful api with express and nodejs but this api crashed every time.
So.. I have one function for datatime. This function will replace date in the url address everytime to current datetime.. Im not sure but may be when the current date is change with the new current date the API crashed..
I see this error message on the console:
events.js:187
throw er; // Unhandled 'error' event
^
Error: read ECONNRESET
at TCP.onStreamRead (internal/stream_base_commons.js:201:27)
Emitted 'error' event on Connection instance at:
at Connection._handleProtocolError (C:\Users\Admin\Desktop\node-express\node_modules\mysql\lib\Connection.js:426:8)
at Protocol.emit (events.js:210:5)
at Protocol._delegateError (C:\Users\Admin\Desktop\node-express\node_modules\mysql\lib\protocol\Protocol.js:398:10)
at Protocol.handleNetworkError (C:\Users\Admin\Desktop\node-express\node_modules\mysql\lib\protocol\Protocol.js:371:10)
at Connection._handleNetworkError (C:\Users\Admin\Desktop\node-express\node_modules\mysql\lib\Connection.js:421:18)
at Socket.emit (events.js:210:5)
at emitErrorNT (internal/streams/destroy.js:92:8)
at emitErrorAndCloseNT (internal/streams/destroy.js:60:3)
at processTicksAndRejections (internal/process/task_queues.js:80:21) {
errno: 'ECONNRESET',
code: 'ECONNRESET',
syscall: 'read',
fatal: true
}
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! express-api#1.0.0 start: `node server.js`
npm ERR!
npm ERR! Failed at the express-api#1.0.0 start script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! C:\Users\Admin\AppData\Roaming\npm-cache\_logs\2019-12-29T04_48_17_190Z-debug.log
So this is the code for api.. Its very simple.. but I dont know how to fix this error.
When I wake up and try to see the data from the API every time the API is crashed.
This is the code from the api:
// Create express app
var express = require("express")
var app = express()
var mysql = require('mysql')
var express = require("express")
var cors = require('cors')
app.use(cors())
// Server port
var HTTP_PORT = 8000
// Start server
app.listen(HTTP_PORT, () => {
console.log("Server running on port %PORT%".replace("%PORT%", HTTP_PORT))
});
var con = mysql.createConnection({
host: "192.168.0.1",
port: "1234",
user: "username",
password: "password"
});
let aladinModel = '';
let aladinModelStations = '';
function formatDate(date) {
var d = new Date(date),
month = '' + (d.getMonth() + 1),
day = '' + d.getDate(),
year = d.getFullYear();
if (month.length < 2)
month = '0' + month;
if (day.length < 2)
day = '0' + day;
return [year, month, day].join('-');
}
var dateNow = formatDate(Date());
app.route('/')
.get(function (req, res) {
// omitted
res.setHeader('Access-Control-Allow-Origin', '*', 'Cache-Control', 'private, no-cache, no-store, must-revalidate');
const date = req.query.date;
const id = req.query.id;
const daysForward = req.query.daysForward;
try {
const query = `CALL aladin_surfex.Get_mod_cell_values_meteogram_cell('${dateNow}', ${id}, ${daysForward})`;
con.query(query, function (err, result, fields) {
if (err) throw err;
aladinModel = result;
});
res.json({ aladinModel })
} catch (error) {
console.log("Error query database!!!");
}
});
app.route('/stations')
.get(function (req, res) {
// omitted
res.setHeader('Access-Control-Allow-Origin', '*');
try {
const query2 = `SELECT Station,Ime FROM aladin_surfex.stations_cells;`;
con.query(query2, function (err, result2, fields) {
if (err) throw err;
aladinModelStations = result2;
});
res.json({ aladinModelStations })
} catch (error) {
console.log("Error query database!!!");
}
});
app.use(function (req, res) {
res.status(404);
});
I try to remove the cashe, to update npm, to restart the computer. But without the result.
With nodemon crashed the same..
What can I do ? How can to fix that ?

The error seems to be related to the connection to mysql.
As mysqljs documentation (https://github.com/mysqljs/mysql#error-handling):
Note: 'error' events are special in node. If they occur without an attached listener, a stack trace is printed and your process is killed.
You shuld intercept the connection error like this:
connection.on('error', function(err) {
console.log(err.code); // 'ER_BAD_DB_ERROR'
});
so you can investigate when and why the error occours and eventually you can recreate the connection when a problem occurs.

Move app.listen to the bottom of the file, after you declare all the routes and connect to the database.
Use app.get('route', function...) (more on that in the Express docs)
Move res.json() inside the callback function for each database query. The result will come back asynchronously so will not be accessible outside the function. If you’re new to async and callbacks in Javascript I’d recommend googling them and you’ll find a ton of reading materials.
Initialize your variables, e.g const aladinModel = ...

Related

Failing on sftp deploy, circle CI, nuxt

For several months I have been able to deploy to my server with no problems using Circle CI, ever since the outage 2 days ago, (not sure if things are related) my deployment script has been failing.
Here is the deployment script:
require('dotenv').config();
console.log("Starting upload")
var SftpUpload = require('sftp-upload'),
fs = require('fs');
var options = {
host: process.env.FTP_HOST,
username: process.env.FTP_UN,
password: process.env.FTP_PW,
path: './dist',
remoteDir: process.env.FTP_PATH,
// excludedFolders: ['**/.git', 'node_modules'],
// exclude: ['.gitignore', '.vscode/tasks.json'],
// privateKey: fs.readFileSync('privateKey_rsa'),
// passphrase: fs.readFileSync('privateKey_rsa.passphrase'),
dryRun: false,
}
console.log(options);
sftp = new SftpUpload(options);
console.log("sftp working ahead")
sftp.on('error', function(err) {
console.log(options)
console.log("igoring error for now")
//throw err;
})
.on('uploading', function(progress) {
console.log(options);
console.log('Uploading', progress.file);
console.log(progress.percent+'% completed');
})
.on('completed', function() {
console.log('Upload Completed');
})
.upload();
Here is the error
'
Starting upload
{
host: '************************',
username: '*********',
password: '************',
path: './dist',
remoteDir: '*****************************************',
dryRun: false
}
sftp working ahead
buffer.js:330
throw new ERR_INVALID_ARG_TYPE(
^
TypeError [ERR_INVALID_ARG_TYPE]: The first argument must be of type string or an instance of Buffer, ArrayBuffer, or Array or an Array-like Object. Received undefined
at Function.from (buffer.js:330:9)
at new Buffer (buffer.js:286:17)
at onNEWKEYS (/home/circleci/repo/node_modules/ssh2/lib/Connection.js:2282:29)
at Parser.<anonymous> (/home/circleci/repo/node_modules/ssh2/lib/Connection.js:123:5)
at Parser.emit (events.js:314:20)
at Parser.parsePacket (/home/circleci/repo/node_modules/ssh2/lib/Parser.js:468:12)
at Parser.execute (/home/circleci/repo/node_modules/ssh2/lib/Parser.js:249:14)
at Socket.<anonymous> (/home/circleci/repo/node_modules/ssh2/lib/Connection.js:523:18)
at Socket.emit (events.js:314:20)
at addChunk (_stream_readable.js:297:12) {
code: 'ERR_INVALID_ARG_TYPE'
}
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! nyb.nyb.nyb#1.0.0 deploy: `node deploy-sftp.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the nyb.nyb.nyb#1.0.0 deploy script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! /home/circleci/.npm/_logs/2022-09-16T08_55_31_507Z-debug.log
Exited with code exit status 1
CircleCI received exit code 1
All of this happens after I installed the packages and built the static files that i'm sftp'ing to a server using nuxt generate. I'm confused about what is happening and how I might salvage my pipeline. Any suggestions are greatly appreciated, thank you!
While i did not find the cause of above error, i found a workaround by using the ssh2-sftp-client, documentation and source code is here
The new deployment script is as follows:
let SftpClient = require('ssh2-sftp-client');
const path = require('path');
require('dotenv').config()
const config = {
host: process.env.FTP_HOST,
username: process.env.FTP_UN,
password: process.env.FTP_PW,
port: process.env.FTP_PORT || 22
};
async function main() {
const client = new SftpClient('upload-test');
const src = path.join(__dirname, './dist/');
const dst = process.env.FTP_PATH;
try {
await client.connect(config);
client.on('upload', info => {
console.log(`Listener: Uploaded ${info.source}`);
});
let rslt = await client.uploadDir(src, dst);
return rslt;
} catch (err) {
console.error(err);
} finally {
client.end();
}
}
main()
.then(msg => {
console.log(msg);
})
.catch(err => {
console.log(`main error: ${err.message}`);
});
Hope this helps anyone encountering similar problems.

NodeJS rmdir function error on LINUX ONLY?

So I'm running this section of my NodeJS script on my Windows 10 device running the latest version of Node and another version on my webserver running CentOS8 Linux. When this code is run on windows, it outputs what I would expect but when I run it on my Linux machine, it errors on this line:
fs.rmdir('public/u/' + info[0] + '/', { recursive: true }, (err) => {
With this error:
fs.js:136
throw new ERR_INVALID_CALLBACK();
^
TypeError [ERR_INVALID_CALLBACK]: Callback must be a function
at makeCallback (fs.js:136:11)
at Object.rmdir (fs.js:671:14)
at /home/frontlinemist57server/celeste.js:156:8
at /home/frontlinemist57server/node_modules/line-reader/lib/line_reader.js:279:15
at getLine (/home/frontlinemist57server/node_modules/line-reader/lib/line_reader.js:166:7)
at Object.nextLine (/home/frontlinemist57server/node_modules/line-reader/lib/line_reader.js:183:7)
at Immediate.readNext (/home/frontlinemist57server/node_modules/line-reader/lib/line_reader.js:269:14)
at runCallback (timers.js:705:18)
at tryOnImmediate (timers.js:676:5)
at processImmediate (timers.js:658:5)
Any ideas?
app.post('/api/purge', (req, res) => {
// Get Sent Token //
var giventoken = req.body.token;
var authed = false;
lineReader.eachLine('accounts.txt', function(line, last) {
// If Valid Token //
if (crypto.createHash('md5').update(line).digest("hex") == giventoken) {
authed = true;
var info = line.split("§");
if (fs.existsSync('public/u/' + info[0] + '/')){
fs.rmdir('public/u/' + info[0] + '/', { recursive: true }, (err) => {
if (err) {
res.send(err);
throw err;
} else {
console.log("Account Purged: " + info[0]);
res.send('purged');
}
}
)}
// If Invalid Token //
} else if (last) {
if (authed == false) {
console.log("Invalid Purge Token: " + giventoken);
res.write("invalid");
res.end();
}
}
});
});
Edit: Both Windows and Linux systems are running the same version of node.
It turns out that DNF doesn't actually update you to the latest version of node for some reason. The server was still running an out of date version of node.
This is how I fixed it:
sudo dnf rm nodejs
curl -sL https://rpm.nodesource.com/setup_12.x | sudo bash -
sudo dnf install nodejs

npm-mysql crashes overnight

The class:
const mysql = require('mysql');
module.exports = function () {
this.connection = mysql.createConnection({
host : 'localhost',
user : 'USER',
password : 'PASSWORD',
database : 'DATABASE',
multipleStatements: true
});
this.query = (sql, args) => {
return new Promise( ( resolve, reject ) => {
this.connection.query( sql, args, ( err, rows ) => {
if ( err )
return reject( err );
resolve( rows );
});
});
};
this.close = () => {
return async () => {
try {
this.connection.end(err => {
if (err) throw err;
return;
});
} catch(e) {
return e;
}
}
};
};
In index i call it like this:
const Database = require('./server/modules/mysql'),
connection = new Database();
The problem:
Overnight mysql crashes:
[nodemon] starting `node index.js`
listening on port 420
events.js:292
throw er; // Unhandled 'error' event
^
Error: Connection lost: The server closed the connection.
at Protocol.end (C:\Users\fedesc\Sites\borsalino\node_modules\mysql\lib\protocol\Protocol.js:112:13)
at Socket.<anonymous> (C:\Users\fedesc\Sites\borsalino\node_modules\mysql\lib\Connection.js:94:28)
at Socket.<anonymous> (C:\Users\fedesc\Sites\borsalino\node_modules\mysql\lib\Connection.js:526:10)
at Socket.emit (events.js:327:22)
at endReadableNT (_stream_readable.js:1221:12)
at processTicksAndRejections (internal/process/task_queues.js:84:21)
Emitted 'error' event on Connection instance at:
at Connection._handleProtocolError (C:\Users\fedesc\Sites\borsalino\node_modules\mysql\lib\Connection.js:423:8)
at Protocol.emit (events.js:315:20)
at Protocol._delegateError (C:\Users\fedesc\Sites\borsalino\node_modules\mysql\lib\protocol\Protocol.js:398:10)
at Protocol.end (C:\Users\fedesc\Sites\borsalino\node_modules\mysql\lib\protocol\Protocol.js:116:8)
at Socket.<anonymous> (C:\Users\fedesc\Sites\borsalino\node_modules\mysql\lib\Connection.js:94:28)
[... lines matching original stack trace ...]
at processTicksAndRejections (internal/process/task_queues.js:84:21) {
fatal: true,
code: 'PROTOCOL_CONNECTION_LOST'
}
[nodemon] app crashed - waiting for file changes before starting...
I'm using Nodemon and a simple restart to the application solves the issue until the next morning (or next long period of not coding.)
I'm not really using close() anywhere or after anything since in the docs it says it's not needed, just query().
but clearly i get a timeout somewhere somehow, like i should deal with the opening and closing of connection.
Do i need to close connections after making queries in my app?
Is there a way to set the timeout limit or dealing with him?
Am i just setting it up wrong or using wrong/outdated tool?
Thanks.

Node.js cluster error

Hello i am very new to node.js and javascript, i am trying to create a culster.js with the nodejs cluster module, at the end of my if statement i am calling server.js to start the app.
cluster.js
const cluster = require('cluster');
const cpuCount = require('os').cpus().length;
const startServer = require('./server');
if (cluster.isMaster) {
for (let i = 0; i < cpuCount; i += 1) {
cluster.fork();
}
cluster.on('exit', () => {
cluster.fork();
});
} else {
return startServer;
}
server.js
const fs = require('fs');
const path = require('path');
const express = require('express');
const auth = require('http-auth');
const {
createBundleRenderer,
} = require('vue-server-renderer');
const bundle = fs.readFileSync('dist/server.js', 'utf-8');
const renderer = createBundleRenderer(bundle);
function parseIndexHtml() {
const [
entire,
htmlOpen,
htmlOpenTailAndHead,
headCloseAndBodyOpen,
bodyOpenTailAndContentBeforeApp,
contentAfterAppAndHtmlClose,
] = fs.readFileSync('index.html', 'utf8').match(/^([\s\S]+?<html)([\s\S]+?)(<\/head>[\s\S]*?<body)([\s\S]+?)<div id="?app"?><\/div>([\s\S]+)$/);
return {
entire,
htmlOpen,
htmlOpenTailAndHead,
headCloseAndBodyOpen,
bodyOpenTailAndContentBeforeApp,
contentAfterAppAndHtmlClose,
};
}
const indexHtml = parseIndexHtml();
const app = express();
const basicAuth = auth.basic({
realm: 'Jobportal',
}, (username, password, callback) => {
callback(username === 'x' && password === 'x');
});
app.get('/ping', (request, response) => {
response.status(200).end();
});
app.use(auth.connect(basicAuth));
// serve pure static assets
app.use('/public', express.static(path.resolve('./public')));
app.use('/dist', express.static(path.resolve('./dist')));
app.get('*', (request, response) => {
const context = {
url: request.url,
};
renderer.renderToString(context, (error, html) => {
if (error) {
if (error.code === '404') {
response.status(404).end(indexHtml.entire);
} else {
response.status(500).end(indexHtml.entire);
console.error(`Error during render: ${request.url}`); // eslint-disable-line
console.error(error); // eslint-disable-line
}
return;
}
const {
title,
htmlAttrs,
bodyAttrs,
link,
style,
script,
noscript,
meta,
} = context.meta.inject();
response.write(
`${indexHtml.htmlOpen} data-vue-meta-server-rendered ${htmlAttrs.text()} ${indexHtml.htmlOpenTailAndHead}
${meta.text()}
${title.text()}
${link.text()}
${style.text()}
${script.text()}
<script>
window.__INITIAL_STATE__ = ${JSON.stringify(context.initialState)}
</script>
${noscript.text()}
${indexHtml.headCloseAndBodyOpen} ${bodyAttrs.text()} ${indexHtml.bodyOpenTailAndContentBeforeApp}
${html}
<script src="/dist/client.js"></script>
${indexHtml.contentAfterAppAndHtmlClose}`
);
response.end();
});
});
const port = 8181;
// start server
app.listen(port, () => {
console.log(`server started at port ${port}`); // eslint-disable-line
});
I get an error
server started at port 8181
events.js:163
throw er; // Unhandled 'error' event
^
Error: bind EADDRINUSE null:8181
at Object.exports._errnoException (util.js:1050:11)
at exports._exceptionWithHostPort (util.js:1073:20)
at listenOnMasterHandle (net.js:1336:16)
at rr (internal/cluster/child.js:111:12)
at Worker.send (internal/cluster/child.js:78:7)
at process.onInternalMessage (internal/cluster/utils.js:42:8)
at emitTwo (events.js:111:20)
at process.emit (events.js:194:7)
at process.nextTick (internal/child_process.js:766:12)
at _combinedTickCallback (internal/process/next_tick.js:73:7)
events.js:163
throw er; // Unhandled 'error' event
^
Any ideas why ?
EADDRINUSE means that the port number which listen() tries to bind the server to is already in use.
You need to verify if the port is already taken on your system. To do that:
On linux: sudo netstat -nltp | grep (port) in your case is port 8181.
On OSX: sudo lsof -i -P | grep (port)
If you have a result, you need to kill the process (kill <pid>).
You should check if pm2 list returns 0 process. In addition, when you do a pm2 stopAll, the socket is not released. Don't forget to do a pm2 kill to be sure the daemon is killed.
$ pm2 kill
Daemon killed
Verifying for Windows:
C:\> netstat -a -b
a Displays all connections and listening ports.
b Displays the executable involved in creating each connection or listening port. In some cases well-known executables host multiple independent components, and in these cases the sequence of components involved in creating the connection or listening port is displayed. In this case the executable name is in [] at the bottom, on top is the component it called, and so forth until TCP/IP was reached. Note that this option can be time-consuming and will fail unless you have sufficient permissions.
n Displays addresses and port numbers in numerical form.
o Displays the owning process ID associated with each connection.
EXAMPLES to kill in windows command line:
If you know the name of a process to kill, for example notepad.exe, use the following command from a command prompt to end it:
taskkill /IM notepad.exe
To kill a single instance of a process, specify its process id (PID). For example, if the desired process has a PID of 827, use the following command to kill it:
taskkill /PID 827

Check MongoDB status in node js

I need to be able to run '/etc/init.d/mongod status' or 'service mongod status' from wihtin a node js file, in order to store the response in the database.
When I run the above commands in the command line, I get the following response:
● mongod.service - SYSV: Mongo is a scalable, document-oriented database.
Loaded: loaded (/etc/rc.d/init.d/mongod)
Active: active (running) since Thu 2017-02-02 08:07:42 UTC; 3h 27min ago
Docs: man:systemd-sysv-generator(8)
Process: 793 ExecStart=/etc/rc.d/init.d/mongod start (code=exited, status=0/SUCCESS)
Main PID: 1027 (mongod)
CGroup: /system.slice/mongod.service
└─1027 /usr/bin/mongod -f /etc/mongod.conf
However, I want to include this status in an API response that I write. Therefore, when a user request my API, I want it to return the mongoDB status check as seen above.
I have tried the following ways:
router.get('/status', function(req, res) {
var databaseCheck = service mongod status // not sure how to do this
res.json({
mongoResponse: '//to have the above status check response here'
});
});
I am new to all this, so any help would be appreciated. I may understand that my thinking is wrong - do let me know if there is a different way of doing this please
Connect a database and then check connection like db.serverConfig.isConnected(). The below code is a full example.
const app = express();
let dbClient;
let db;
let collection;
MongoClient.connect(configuration.mongoDbUri, { useNewUrlParser: true, poolSize: 30 }, (error, client) => {
if (error) {
console.log("Connection failed for some reason. Err: ", error);
return error;
}
db = client.db("myDB");
dbClient = client;
collection = db.collection('myCollection');
app.locals.mongoDb = db;
});
app.get("/status", (req, res) => {
if (db.serverConfig.isConnected()) {
console.log("db.serverConfig.isConnected :", db.serverConfig.isConnected());
return res.send({ result: true});
}
return res.send({ result: false});
});
app.listen(configuration.app.port, error => {});
You can use nodejs child-process module to run a shell command like you would from a terminal. In a terminal you would "service mongod status", in the nodejs child-process you would do the same by putting that command as an argument to the child-process execute function, like so:
const exec = require('child_process').exec;
exec('service mongod status', (error, stdout, stderr) => {
if (error) {
console.error(`exec error: ${error}`);
return;
}
console.log(`stdout: ${stdout}`);
console.log(`stderr: ${stderr}`);
});
Try code like this into you app:
db.serverConfig.isConnected();

Categories

Resources