MySQL Connection error with NodeJS - javascript

var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var fs = require('fs');
var mysql = require('mysql');
app.get('/', function(req, res){
res.send('<h1>My App</h1>');
});
var db_config = {
host: 'localhost',
user: 'root',
database: 'database',
password: '',
dialect: 'mysql',
insecureAuth: true
};
var connection;
function handleDisconnect() {
connection = mysql.createConnection(db_config); // Recreate the connection, since
// the old one cannot be reused.
connection.connect(function(err) { // The server is either down
if(err) { // or restarting (takes a while sometimes).
console.log('error when connecting to db:', err);
setTimeout(handleDisconnect, 2000); // We introduce a delay before attempting to reconnect,
} // to avoid a hot loop, and to allow our node script to
}); // process asynchronous requests in the meantime.
// If you're also serving http, display a 503 error.
connection.on('error', function(err) {
console.log('db error', err);
if(err.code === 'PROTOCOL_CONNECTION_LOST') { // Connection to the MySQL server is usually
handleDisconnect(); // lost due to either server restart, or a
} else { // connnection idle timeout (the wait_timeout
throw err; // server variable configures this)
}
});
}
handleDisconnect();
http.listen(3000, function(){
console.log('listening on *:3000');
});
.............
I am developing an app that returns real time score updates from database as shown in the code above. When I execute the program above with localhost (wamp) it works fine. When executing with CentOS 7 with MariaDB it returns an error stating:
db error { Error: Connection lost: The server closed the connection.
I have done some changes to my code by following this thread.
But it didn't work. And also I tried with Pooling also. Help me to resolve this issue.

Related

Using a single port for bittorrent-tracker server in Heroku

I am trying to build/deploy a tracker server for use with P2P applications using the below code. It works fine locally, but when I deploy it to Heroku, the port bindings fail because only one port is allowed.
// Create a web sockets signaling server
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
//Allow all requests from all domains & localhost
app.all('/*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With, Content-Type, Accept");
res.header("Access-Control-Allow-Methods", "POST, GET");
next();
});
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
let lookup = {}
const hostname = '0.0.0.0';
const port = process.env.PORT;
var Server = require('bittorrent-tracker').Server
var server = new Server({
udp: false, // enable udp server? [default=true]
http: true, // enable http server? [default=true]
ws: true, // enable websocket server? [default=true]
stats: true, // enable web-based statistics? [default=true]
})
server.on('error', function (err) {
// fatal server error!
console.log(err.message)
})
server.on('warning', function (err) {
// client sent bad data. probably not a problem, just a buggy client.
console.log(err.message)
})
server.on('listening', function () {
// fired when all requested servers are listening
console.log('Signal server http port:' + server.http.address().port)
console.log('Signal server ws port:' + server.ws.address().port)
})
// start tracker server listening! Use 0 to listen on a random free port.
server.listen(port, hostname, 'listening')
// listen for individual tracker messages from peers:
server.on('start', function (addr) {
console.log('got start message from ' + addr)
Object.keys(server.torrents).forEach(hash => {
lookup[server.torrents[hash].infoHash] = server.torrents[hash].peers.length
console.log("peers: " + server.torrents[hash].peers.length)
})
})
server.on('complete', function (addr) {})
server.on('stop', function (addr) {})
app.get('/peers', function(req, res) {
res.send(lookup);
})
app.listen(process.env.PORT, function() {
console.log('Express server port: ' + this.address().port); //Listening on port #
})
If I use process.env.PORT for both server and app, I get the following, which is expected since Heroku only allows 1 listen port:
2021-02-13T05:35:31.016101+00:00 heroku[web.1]: State changed from starting to up
2021-02-13T05:35:30.885170+00:00 app[web.1]: Express server port: 9898
2021-02-13T05:35:30.885204+00:00 app[web.1]: listen EADDRINUSE: address already in use 0.0.0.0:9898
2021-02-13T05:35:30.885205+00:00 app[web.1]: listen EADDRINUSE: address already in use 0.0.0.0:9898
If I hard code the port for either server or app, the application launches fine, but the signaling server doesn't work. No substantial logging is generated.
2021-02-13T05:38:21.141806+00:00 heroku[web.1]: State changed from starting to up
2021-02-13T05:38:20.998054+00:00 app[web.1]: Express server port: 25702
2021-02-13T05:38:20.998550+00:00 app[web.1]: Signal server http port:31415
2021-02-13T05:38:20.998683+00:00 app[web.1]: Signal server ws port:31415
Is it possible that the bittorrent-tracker server and express server can use the same port? For instance, could I get and return the list of peers within this block of code without the need for express at all?
server.on('start', function (addr) {
console.log('got start message from ' + addr)
// Could I do something here to eliminate the need for Express?
Object.keys(server.torrents).forEach(hash => {
lookup[server.torrents[hash].infoHash] = server.torrents[hash].peers.length
console.log("peers: " + server.torrents[hash].peers.length)
})
})
The documentation states:
The http server will handle requests for the following paths:
/announce, /scrape. Requests for other paths will not be handled.
But perhaps there is some way I can shim in the requests that express is handling?
Not long after asking this question, it occurred to me that I might not need express at all. It turns out that was correct.
For anyone wanting a Heroku-ready bittorrent-tracker, here is the updated code:
// Create a web sockets signaling server
let lookup = {}
const hostname = '0.0.0.0';
const port = process.env.PORT;
var Server = require('bittorrent-tracker').Server
var server = new Server({
udp: false, // enable udp server? [default=true]
http: true, // enable http server? [default=true]
ws: true, // enable websocket server? [default=true]
stats: true, // enable web-based statistics? [default=true]
})
server.on('error', function (err) {
// fatal server error!
console.log(err.message)
})
server.on('warning', function (err) {
// client sent bad data. probably not a problem, just a buggy client.
console.log(err.message)
})
server.on('listening', function () {
// fired when all requested servers are listening
console.log('Signal server http port:' + server.http.address().port)
console.log('Signal server ws port:' + server.ws.address().port)
})
// start tracker server listening! Use 0 to listen on a random free port.
server.listen(port, hostname, 'listening')
// listen for individual tracker messages from peers:
server.on('start', function (addr) {
console.log('got start message from ' + addr)
Object.keys(server.torrents).forEach(hash => {
lookup[server.torrents[hash].infoHash] = server.torrents[hash].peers.length
console.log("peers: " + server.torrents[hash].peers.length)
})
})
server.on('complete', function (addr) {})
server.on('stop', function (addr) {})

Node js mysql query gives error when executed second time

I am trying to make a REST api in node using express. When i open the url in browser the first time, it runs fine and gives me the correct output. But when I hit the api url the second time, the app crashes with the error :
events.js:141
throw er; // Unhandled 'error' event
^
Error: Cannot enqueue Handshake after invoking quit.
This is the code I'm using :
var express = require('express');
var mysql = require('mysql');
var app = express();
var connection = mysql.createConnection({
host: 'localhost',
user: 'USER_NAME',
password: 'PASSWORD'
});
app.use(express.static(__dirname + '/public'));
var port = 3333;
app.get('/api/users/:user_id', function(req, res){
var lead_id = req.params.user_id;
connection.connect();
connection.query('use DB_NAME;', function (err) {
if(err) throw err;
connection.query('select * from users where user_id = ' + user_id, function (err, rows) {
if(err) throw err;
res.json(rows);
connection.end();
});
});
});
app.listen(port);
console.log("The app is running on port " + port);
Can someone tell me what am I doing wrong ?
Just remove connection.connect() and connection.end(). Then it should work.
connection.connect() should be called once or none. Because connection.query will connect I'd it not connected.
PS - connection.connect() need to be called when the connection is lost.
Try this to remove the redudant connection. This was the first result of a google search of the error message - always try to google error messages before asking SO.

MySQL DB Pool with Node.js and Restify

I am currently developing a node.js backend for a mobile app with potentially many users. However it's my first time in developing node.js. I was following a tutorial on how to connect to a mysql database via mysql pools.
I am able to create a single mysql connection and do queries via my routes.
The problem arises once I establish the file structure mentioned in the tutorial:
dbConnect
-[models]
--users.js
-db.js
-server-ks
I am not getting an error message regarding the connection of the mysql database - even if I enter a wrong password.
// server.js
///////////////////////////// basic setup ///////////////////////////////////
var restify = require('restify');
var bodyParser = require('body-parser');
var mysql = require('mysql');
var db = require('./db');
var users = require('./models/users');
///////////////////////////// initilisation of the server ///////////////////////////////////
var server = restify.createServer({
name: 'testUsers',
});
server.use(restify.bodyParser({ mapParams: true }));
///////////////////////////// Säuberung der URL //////////////////////////////////////////
server.pre(restify.pre.sanitizePath());
///////////////////////////// MySQL Instanz starten //////////////////////////////////////////
db.connect(db.MODE_PRODUCTION, function (err) {
if (err) {
console.log('Unable to connect to MySQL.')
process.exit(1)
} else {
server.listen(8080, function () {
console.log('Listening on port 8080 ...')
})
}
})
///////////////////////////// implementation of the routes ///////////////////////////////////
function send(req, res, next) {
var test = users.getAll();
res.json({ test: 'Hello ' + req.params.name });
return next();
};
My DB.js file looks the following:
var mysql = require('mysql'),
sync = require('async')
var PRODUCTION_DB = 'userDB',
TEST_DB = 'userDB'
exports.MODE_TEST = 'mode_test'
exports.MODE_PRODUCTION = 'mode_production'
var state = {
pool: null,
mode: null,
}
exports.connect = function (mode, done) {
state.pool = mysql.createPool({
connectionLimit: 50,
host: 'localhost',
user: 'user',
password: 'password',
database: 'userDB' // test
//mode === exports.MODE_PRODUCTION ? PRODUCTION_DB : TEST_DB
})
state.mode = mode
done()
}
exports.get = function () {
return state.pool
}
Could it be, that the tutorial spared out an essential part in utilizing mysql pools and node.js?
Thanks in advance for at least trying to answer that question.
Are there better methods sequelize(?) available to create performant connections to a MySQL database?
It looks like creating the pool object does not actually connect to the database. A big clue is that the createPool function is not asynchronous, which is what you would expect if it was actually connecting at that moment.
You have to make use of the returned pool object to perform a query, which IS asynchronous.
From the documentation:
var mysql = require('mysql');
var pool = mysql.createPool({
connectionLimit : 10,
host : 'example.org',
user : 'bob',
password : 'secret',
database : 'my_db'
});
pool.query('SELECT 1 + 1 AS solution', function(err, rows, fields) {
if (err) throw err;
console.log('The solution is: ', rows[0].solution);
});

How can i pipe mysql data to a browser window instead of the console in Nodejs?

Hi I am currently trying to output mysql data to a browser window instead of the console, and I have not a clue on how to do this in Node, which I am quite new to.
Here is the mysql.js file:
'
var mysql = require ("mysql");
var connection = mysql.createConnection({
host:"localhost",
user: "root",
});
connection.connect(function (err) {console.log( "Successfully Connected.");
if (err) throw err;
});
var query = connection.query("SELECT * FROM myTable", function (err, result, fields){
if (err) throw err;
console.log('result:', result);
});
connection.end();'
You need to create a server which you can connect to and receive data from with a browser. The most convenient and by far the simplest way to do this is HTTP. You can read about HTTP servers in node.js here. The fist code snippet on that page demonstrates a HTTP server with one handler function, which is all you need to achieve your goal.
An (untested) example for convenience:
// Dependencies
var mysql = require("mysql"),
http = require("http");
// This holds our query results
var results;
// Connect to database
var connection = mysql.createConnection({
host: "localhost",
user: "root"
});
connection.connect(function(err) {
if (err) throw err;
console.log("Connected to database");
});
connection.query("SELECT * FROM myTable", function(err, rows, fields) {
if (err) throw err;
results = rows;
connection.end(); // Disconnect from database
});
// Function to handle browser's requests
function requestHandler(req, res) {
res.end(JSON.stringify(results)); // Respond to request with a string
}
// Create a server
var server = http.createServer(requestHandler);
// That magic number 8080 over here is the port our server listens to.
// You can access this webpage by visiting address http://localhost:8080
server.listen(8080, function() {
console.log("Server online");
});

How to rerun the request handler in node + express?

I am running node + express + mongojs. Here is a sample code:
function mongoCallback(req, res) {
"use strict";
return function (err, o) {
if (err) {
res.send(500, err.message);
} else if (!o) {
res.send(404);
} else {
res.send(o);
}
};
}
var express, app, params, mongo, db;
express = require('express');
params = require('express-params');
app = express();
params.extend(app);
app.use("/", express.static('web'));
mongo = require('mongojs');
db = mongo.connect('mydb', ['inventory']);
app.get('/api/inventory', function (req, res) {
db.inventory.find(mongoCallback(req, res));
});
app.listen(8000);
console.log('Listening on port 8000');
Sometimes I forget running mongod and an attempt to talk to the database fails with "failed to connect to ..." error. The problem is that starting mongod is not enough, the already existing db object seems to remember that no connection could be made and so the server continues to fail, even if mongod is already running.
So, I have come up with the following solution:
var express, app, params, mongo, db, api;
if (!String.prototype.startsWith) {
String.prototype.startsWith = function (str) {
"use strict";
return this.lastIndexOf(str, 0) === 0;
};
}
function setDB() {
db = mongo.connect('IF', ['invoices', 'const', 'inventory']);
}
function mongoCallback(req, res, next, caller, secondTry) {
return function (err, o) {
if (err) {
if (!secondTry && err.message && err.message.startsWith("failed to connect to")) {
setDB();
caller(req, res, next, true);
} else {
res.send(500, err.message);
}
} else if (!o) {
res.send(404);
} else {
res.send(o);
}
};
}
express = require('express');
params = require('express-params');
app = express();
params.extend(app);
app.use("/", express["static"]('web'));
mongo = require('mongojs');
setDB();
api = {
getInventory: function (req, res, next, secondTry) {
db.inventory.find(mongoCallback(req, res, next, api.getInventory, secondTry));
}
};
app.get('/api/inventory', api.getInventory);
app.listen(8000);
console.log('Listening on port 8000');
Basically it recreates the db object if a request fails with the "failed to connect to" error and reruns the request. This is done only for the first failure. A subsequent failure returns the error.
I do not like my solution at all. There has to be a better way. Any suggestions?
Thanks.
What do you mean by "the already existing db object seems to remember that no connection could be made"? Do you mean that the queries on the database fail if you start the express app before running mongod? Since you are connecting to the DB at the startup of the express app, you should have the mongod running first.
If you are worried about the database going down after the initial connection and causing your CRUD operations to fail, you can check for an error in your operations
db.inventory.find(function(err, docs) {
// check err to see if there was a connection issue
});
and then reconnect if there was an error.
As far as I know the mongodb native driver allows to set { auto_reconnect:true }, have you tried to set this?
I'm not sure how this behaves if the database wasn't running at all, mongoose.js for example caches all requests until the DB is ready and issues them after a successful connection.

Categories

Resources