How to reconnect SQL Server tedious when connection is lost - node.js

js and using tedious to connect. Connection is successful and I'm able to connect. However in period of time I would lose connect and receive these errors in Azure.
RequestError: Requests can only be made in the LoggedIn state, not the Final stateat RequestError (D:\home\site\wwwroot\node_modules\tedious\lib\errors.js:32:12)
at Connection.makeRequest (D:\home\site\wwwroot\node_modules\tedious\lib\connection.js:2380:49)at Connection.execSql (D:\home\site\wwwroot\node_modules\tedious\lib\connection.js:2034:10)at submitCode (D:\home\site\wwwroot\controller\mssqlController.js:121:16)at Layer.handle [as handle_request] (D:\home\site\wwwroot\node_modules\express\lib\router\layer.js:95:5)at next (D:\home\site\wwwroot\node_modules\express\lib\router\route.js:137:13)at Route.dispatch (D:\home\site\wwwroot\node_modules\express\lib\router\route.js:112:3)at Layer.handle [as handle_request] (D:\home\site\wwwroot\node_modules\express\lib\router\layer.js:95:5)at D:\home\site\wwwroot\node_modules\express\lib\router\index.js:281:22at Function.process_params (D:\home\site\wwwroot\node_modules\express\lib\router\index.js:335:12) {code: 'EINVALIDSTATE'}[0mPOST /login [32m200 [0m11.820 ms - 27[0m
Here is my code:
let config = {
server: '',
authentication: {
type: 'default',
options: {
userName: '',
password: ''
}
},
options: {
// If you are on Microsoft Azure, you need encryption:
encrypt: true,
database: ''
}
};
let connection = new Connection(config);
connection.on('connect', function (err) {
// If no error, then good to proceed.
console.log("err", err);
});
let Request = require('tedious').Request
let TYPES = require('tedious').TYPES;
My question is where and what can I add to reconnect or reset SQL Server in Azure if connection is lost?

You can try using the below code to retry the connection:
let intervalFunction;
const INTERVAL_DURATION = 4000;
if (require.main === module){
console.log("Listening on http://localhost:" + config.port + " ...");
app.listen(config.port);
// try to connect to db and fire main on succes.
intervalFunction = setInterval(()=> getConnection(), INTERVAL_DURATION);
}
function getConnection() {
sql.close();
sql.connect(config.database).then(() => {
sql.close();
clearInterval(intervalFunction);
main();
}).catch(function(err) {
console.error(err);
console.log(`DB connection will be tried again in ${INTERVAL_DURATION}ms`)
sql.close();
});
}
Once the initial connection has been made but it got lost in the meantime, then the pool will pick up the connection automatically and handle your connections.

I suggest using the mssql node package, which still uses tedious, and using a pool -- which will auto-reconnect.
https://www.npmjs.com/package/mssql#connections-1
Otherwise, you can look for connection.on('end') event, or error event, and write a custom function to retry the connection then. See an example of listening here: https://github.com/tediousjs/tedious/blob/master/examples/simple-client.js

Related

Is it possible to connect to mssql with windows auth mode from a nodejs app running on linux?

I'm trying to connect to a mssql with Windows authentication mode (can't change that) from nodejs running on a linux machine.
I tried many things, all of them resulted in nearly the same error, here is an attempt using tedious with this simple code running on a linux machine with nodejs:
let tedious = require('tedious');
let Connection = tedious.Connection;
const config = {
userName: 'myUserName',
password: 'myPassword',
server: 'MyServ',
options: {
database: 'MyDbName'
}
}
function handleConnection(err: any) {
if (err) console.error("error connecting :-(", err);
else console.log("successfully connected!!")
}
let connection = new Connection(config);
connection.on('connect', handleConnection);
I get this error
error connecting :-( { ConnectionError: Login failed for user ''.
at ConnectionError (./node_modules/tedious/lib/errors.js:13:12)
at Parser.tokenStreamParser.on.token (./node_modules/tedious/lib/connection.js:848:51)
at Parser.emit (events.js:198:13)
at Parser.parser.on.token (./node_modules/tedious/lib/token/token-stream-parser.js:37:14)
at Parser.emit (events.js:198:13)
at addChunk (./node_modules/readable-stream/lib/_stream_readable.js:298:12)
at readableAddChunk (./node_modules/readable-stream/lib/_stream_readable.js:280:11)
at Parser.Readable.push (./node_modules/readable-stream/lib/_stream_readable.js:241:10)
at Parser.Transform.push (./node_modules/readable-stream/lib/_stream_transform.js:139:32)
at doneParsing (./node_modules/tedious/lib/token/stream-parser.js:122:14) message: 'Login failed for user \'\'.', code: 'ELOGIN' }
The credentials I used do have SQL rights (tested with ODBC on windows machine).
Am I doing something wrong or is it just impossible ?
#ADyson thank you a lot for your informations, you managed to pinpoint the solution to my poorly formulated problem caused by my total lack of knowledge on the subject, really thank you again. the solution was to use domain login this snippet worked :
const config = {
user: MyUserName,
password: MyPassword,
server: 'MyServAdress',
database: 'MyDbName,
domain: 'MyDomain'
}
const sql = require('mssql');
sql.connect(config).then((pool: any) => {
console.log('connected!');
}).catch((err: any) => {
console.log(err);
});
Yes indeed, it's possible to receive data form a linux client using windows authentication only enabled. MS SQL Server and NodeJS Linux Server are in the same network. The linux Server isn't domain-joined:
I used this to run execute my query:
const sql = require('mssql')
const config = {
server: 'SERVER',
database: 'DATABASE',
user: 'USER',
password: 'PASSWORD',
domain: 'DOMAIN',
options: {
enableArithAbort: true // required, otherwise deprecation warning
}
}
sql.connect(config)
.then((conn) => {
console.log('MSSQL: connected');
conn.query(`SELECT ..`)
.then(data => console.log(data))
.then(() => conn.close())
}).catch(err => { console.log(err) });

Error: Can't add new command when connection is in closed state

I have recently deployed my node.js API application on live server. I am getting these issue on live server.
I have googled it, but could not get any exact solution. Can anyone suggest how can i solve this problem?
{ Error: read ETIMEDOUT at TCP.onread (net.js:622:25) errno: 'ETIMEDOUT', code: 'ETIMEDOUT', syscall: 'read', fatal: true }
{ Error: Can't add new command when connection is in closed state at PoolConnection._addCommandClosedState }
I amd using the mysql connection pool like this
var mysql = require('mysql2');
var mysqlPool = mysql.createPool({
host: 'localhost',
user: 'root',
password: 'xyz',
database: 'xyz',
waitForConnections: true,
connectionLimit: 10,
queueLimit: 0
});
module.exports = mysqlPool;
I had a similar problem and ended up having to put the connection request in it's own .js file and import it into the controller-
connectionRequest.js
module.exports = function () {
let mysql = require('mysql2')
let connCreds = require('./connectionsConfig.json');
//Establish Connection to the DB
let connection = mysql.createConnection({
host: connCreds["host"],
user: connCreds['username'],
password: connCreds['password'],
database: connCreds['database'],
port: 3306
});
//Instantiate the connection
connection.connect(function (err) {
if (err) {
console.log(`connectionRequest Failed ${err.stack}`)
} else {
console.log(`DB connectionRequest Successful ${connection.threadId}`)
}
});
//return connection object
return connection
}
Once I did that I was able to import it into my query on the controller file like so
ControllerFile.js
let connectionRequest = require('../config/connectionRequest')
controllerMethod: (req, res, next) => {
//Establish the connection on this request
connection = connectionRequest()
//Run the query
connection.query("SELECT * FROM table", function (err, result, fields) {
if (err) {
// If an error occurred, send a generic server failure
console.log(`not successful! ${err}`)
connection.destroy();
} else {
//If successful, inform as such
console.log(`Query was successful, ${result}`)
//send json file to end user if using an API
res.json(result)
//destroy the connection thread
connection.destroy();
}
});
},
After a lot of messing around I was able to solve the problem by destroying the connection, waiting (this is the important page) and getting the connection again.
conn = await connPool.getConnection();
// We have error: Can't add new command when connection is in closed state
// I'm attempting to solve it by grabbing a new connection
if (!conn || !conn.connection || conn.connection._closing) {
winston.info('Connection is in a closed state, getting a new connection');
await conn.destroy(); // Toast that guy right now
sleep.sleep(1); // Wait for the connection to be destroyed and try to get a new one, you must wait! otherwise u get the same connection
conn = await connPool.connection.getConnection(); // get a new one
}

Unable to connect to Microsoft SQL Server using Node.js,mssql and express

I am trying to learn Node.js and created a simple project to query the local database. But I get failed to look up an instance error message.
I have checked that the SQL Server services running in services.msc
I have verified TCP/IP is enabled
I have tried with the username and password and without it as well. I connect to localdb in SQL Server Management Studio as (localdb)\v11.0 and below is the screenshot of the properties
What am I doing incorrectly? What should be actual username and password? What should be the servername?
const sql = require('mssql');
// config for your database
const config = {
user: 'mywindows username',
password: 'my windows password',
server: '(localdb)\\v11.0',
database: 'test',
options: {
encrypt: true
}
};
console.log('starting sql');
var connection = new sql.connect(config, function(err) {
console.log(err);
var request = new sql.Request(connection);
request.query('select * from employees', function(err, recordset) {
if(err) // ... error checks
console.log('Database connection error');
console.dir("User Data: "+recordset);
});
});
sql.close();
console.log('ending sql');
});
app.listen(3002, () => {
console.log('Listening on port 3002');})
Below is the error message
{ ConnectionError: Failed to lookup instance on (localdb) -
getaddrinfo ENOTFOUND (localdb)
at Connection.tedious.once.err (C:\Users\vndbsubramaniam\Desktop\React
projects\ReactWithSql\node_modules\mssql\lib\tedious.js:244:17)
at Object.onceWrapper (events.js:285:13)
at Connection.emit (events.js:197:13)
at InstanceLookup.instanceLookup (C:\Users\vndbsubramaniam\Desktop\React
projects\ReactWithSql\node_modules\tedious\lib\connection.js:945:16)
at sender.execute (C:\Users\vndbsubramaniam\Desktop\React projects\ReactWithSql\node_modules\tedious\lib\instance-lookup.js:66:13)
at GetAddrInfoReqWrap.invokeLookupAll [as callback] (C:\Users\vndbsubramaniam\Desktop\React
projects\ReactWithSql\node_modules\tedious\lib\sender.js:43:16)
at GetAddrInfoReqWrap.onlookupall [as oncomplete] (dns.js:70:17) code: 'EINSTLOOKUP', originalError: { ConnectionError: Failed to
lookup instance on (localdb) - getaddrinfo ENOTFOUND (localdb)
at ConnectionError (C:\Users\vndbsubramaniam\Desktop\React projects\ReactWithSql\node_modules\tedious\lib\errors.js:13:12)
at InstanceLookup.instanceLookup (C:\Users\vndbsubramaniam\Desktop\React
projects\ReactWithSql\node_modules\tedious\lib\connection.js:945:32)
at sender.execute (C:\Users\vndbsubramaniam\Desktop\React projects\ReactWithSql\node_modules\tedious\lib\instance-lookup.js:66:13)
at GetAddrInfoReqWrap.invokeLookupAll [as callback] (C:\Users\vndbsubramaniam\Desktop\React
projects\ReactWithSql\node_modules\tedious\lib\sender.js:43:16)
at GetAddrInfoReqWrap.onlookupall [as oncomplete] (dns.js:70:17)
message:
'Failed to lookup instance on (localdb) - getaddrinfo ENOTFOUND (localdb)',
code: 'EINSTLOOKUP' }, name: 'ConnectionError' } Database connection error
After struggling for hours on this one finally found the answer here SQL to Node connection
It seems i have to add msnodesqlv8 package and use add the driver syntax to the config.
app.get('/test', (req, res) => {
const sql = require('mssql/msnodesqlv8');
// config for your database
const config = {
database: 'test',
server: '(localdb)\\v11.0',
driver: 'msnodesqlv8',
options : {
trustedConnection : true
}
};
console.log('starting sql');
const pool = new sql.ConnectionPool(config);
pool.connect().then(() => {
//simple query
pool.request().query('select * from employees', (err, result) => {
if(err) res.send(err)
else{
return res.json({
data : result.recordset
})
}
})
sql.close();
})
console.log('ending sql');
});
you will need msnodesqlv8 driver, which you have to paste it in require as
var sql = require('mssql/msnodesqlv8'),
as well as you will have to include it in driver section in config object.
var config = {
user:"*****",
password:"*****",
database:"*****",
driver: 'msnodesqlv8',
server:"*****",
options: {
trustedConnection : true
}
}

Error: Timed out while waiting for handshake in Lambda logs

The function of SFTP is working locally and it has the correct configuration.
The problem is with the logs of Lambda that complains about the configuration I believe by giving me an Error: Timed out while waiting for a handshake.
const config = {
host: 'ftp.xxxx.at',
port: '22',
username: 'SFTP_xxx',
password: 'xxx9fBcS45',
MD5_Fingerprint: 'xxx:8f:5b:1a',
protocol: "sftp",
algorithms: {
serverHostKey: ['ssh-rsa', 'ssh-dss']
}
};
// get file
// get sftp file
// here ....
const get = () => {
sftp.connect(config).then(() => {
return sftp.get('./EMRFID_201811210903.csv', null, 'utf8', null);
}).then((stream) => {
let body = stream.on('data', (chunk) => {
body += chunk;
})
stream.on('end', () => {
uploadRFIDsToS3(body)
// close connection
sftp.end()
});
}).catch((err) => {
console.log('catch err:', err)
})
};
-
vpc:
securityGroupIds:
- sg-01c29be1d8fbxx59
subnetdIds:
- subnet-007a88d9xxea434d
-
2019-02-18T13:53:51.121Z e688c7bd-24fc-45a1-a565-f2a4c313f846 catch err: { Error: Timed out while waiting for handshake
at Timeout._onTimeout (/var/task/node_modules/ssh2-sftp-client/node_modules/ssh2/lib/client.js:695:19)
at ontimeout (timers.js:482:11)
at tryOnTimeout (timers.js:317:5)
at Timer.listOnTimeout (timers.js:277:5) level: 'client-timeout' }
I added VPC and Security Group in AWS and I still get the same error.
I ran out of ideas of how to fix it.
Increase the time-out value for the lambda function. The option to allocate more memory and time-out are some of the settings for any lambda function in aws
I figure it out.
What was wrong is that Lambda was actually going to another function without getting the connection established.
So what I did is that I added await to the connection and other functions that should not interfere with each other to make to work.
To understand more about await go to this link:
https://javascript.info/async-await

net.Stream is not a constructor - Node Postgres

I'm trying to connect a Node.js app with a PostgreSQL server. It seems that no matter what I use, I end up with the same error:
bundle.js:16177 ERROR: TypeError: net.Stream is not a constructor
at new Connection (bundle.js:10133)
at new Client (bundle.js:9704)
at Object.create (bundle.js:11308)
at Pool._createResource (bundle.js:510)
at Pool.dispense [as _dispense] (bundle.js:498)
at Pool.acquire (bundle.js:573)
at Pool.pool.connect (bundle.js:11359)
at PG.connect (bundle.js:10876)
at bundle.js:1642
At first I was declaring a new pg.Client() like the example in the documentation here, but got the above error discovered that might be a bad idea according to this stack overflow post.
I tried using pg.connect():
var pg = require('pg'); //postgresql dependency
var connectionString = "postgres://postgres:thisissuchagoodpassword#PostgreSQL/localhost:5432/Milestone1DB"
console.log("Initiating...");
//var connectionString = "postgres://postgres:thisissuchagoodpassword#PostgreSQL9.6/localhost:5432/Milestone1DB";
//var client = new pg.Client();
//connect to the database
console.log("Attempting to connect to the database");
pg.connect(function (err, client, done)
{
if(err)
{
console.log("Error connecting to the database.");
throw err;
}
client.query("SELECT DISTINCT state FROM business ORDER BY state", function (err, result)
{
if(err)
{
console.log("Query resulted in an error.");
throw err;
}
console.log(result.rows[0]);
client.end(function (err)
{
if(err)
{
console.log("Error disconnecting from the databse.");
throw err;
}
});
});
});
Here is the pg-promise code that I tried:
var pgp = require('pg-promise');
var cn = {
host: 'localhost', // server name or IP address;
port: 5432,
database: 'Milestone1DB',
user: 'postgres',
password: 'thisissuchagoodpassword'
};
var db = pgp(cn); // database instance;
db.any("select distict state from business order by state;")
.then(data => {
console.log("DATA:", data);
})
.catch(error => {
console.log("ERROR:", error);
});
I must be missing something, but I don't know where to look. Thank you to anyone who can help me figure out what this error means.
Make sure you are not crossing a context boundary that is corrupting the net prototype chain and stripping away methods like Stream(). I ran into a similar unhandled Promise exception w Node 7.5 and pg-live-select. However it was intermittent because of the way the net reference was being passed around. I ended up using V8 inspector and putting a 'debugger' statement directly above line 13 in connection.js to catch the corruption.
node_modules/lib/connection.js:13
this.stream = config.stream || new net.Stream();
^
TypeError: net.Stream is not a constructor
at new Connection (node_modules/pg-live-select/node_modules/pg/lib/connection.js:13:34)
at new Client (node_modules/pg-live-select/node_modules/pg/lib/client.js:26:37)
at Object.create (node_modules/pg-live-select/node_modules/pg/lib/pool.js:27:24)
at Pool._createResource (node_modules/generic-pool/lib/generic-pool.js:325:17)
at Pool.dispense [as _dispense] (node_modules/generic-pool/lib/generic-pool.js:313:12)
at Pool.acquire (node_modules/generic-pool/lib/generic-pool.js:388:8)
at Pool.pool.connect (node_modules/pg-live-select/node_modules/pg/lib/pool.js:78:14)
at PG.connect (node_modules/pg-live-select/node_modules/pg/lib/index.js:49:8)
at LivePg._updateQuery (node_modules/pg-live-select/index.js:295:6)
at node_modules/pg-live-select/index.js:160:14
at Array.forEach (native)
at Timeout.performNextUpdate [as _onTimeout] (node_modules/pg-live-select/index.js:159:23)
at ontimeout (timers.js:365:14)
at tryOnTimeout (timers.js:237:5)
at Timer.listOnTimeout (timers.js:207:5)

Resources