Cant connect to database using process.env | Tedious | nodejs - node.js

In tedious config, using process.env.(database details) fails. However if I put the same values by hand, the connect is successful.
I would like to use process.env instead of hard coding my database details.
Database is being hosted on azure.
Here's my code:
const { Connection, Request } = require("tedious");
const dotenv = require("dotenv");
dotenv.config();
// Create connection to database
const config = {
authentication: {
options: {
userName: "process.env.databaseUser",
password: "process.env.databasePassword",
},
type: "default",
},
server: "process.env.databaseUrl",
options: {
database: "process.env.databaseName",
encrypt: true,
},
};
const connection = new Connection(config);
// Attempt to connect and execute queries if connection goes through
connection.on("connect", (err) => {
if (err) {
console.error(err.message);
} else {
queryDatabase();
}
});
async function queryDatabase(query) {
const request = new Request(query, (err, rowCount) => {
if (err) {
console.error(err.message);
} else {
console.log(`${rowCount} row(s) returned`);
}
});
request.on("row", (columns) => {
columns.forEach((column) => {
console.log("%s\t%s", column.metadata.colName, column.value);
});
});
connection.execSql(request);
}
module.exports = {
queryDatabase,
};
terminal output:
Worker 09d76af8-01c2-4cdb-a2c1-d84de5ccfb89 connecting on 127.0.0.1:41165
[5/2/20 7:12:06 AM] Sat, 02 May 2020 07:12:06 GMT tedious deprecated The default value for `config.options.trustServerCertificate` will change from `true` to `false` in the next major version of `tedious`. Set the value to `true` or `false` explicitly to silence this message. at shared/my-db-helper.js:22:20
[5/2/20 7:12:06 AM] Sat, 02 May 2020 07:12:06 GMT tedious deprecated In the next major version of `tedious`, creating a new `Connection` instance will no longer establish a connection to the server automatically. Please use the new `connect` helper function or call the `.connect` method on the newly created `Connection` object to silence this message. at internal/process/next_tick.js:131:7
[5/2/20 7:12:06 AM] Failed to connect to process.env.databaseUrl:1433 - getaddrinfo ENOTFOUND process.env.databaseUrl
[5/2/20 7:12:07 AM] (node:21327) [DEP0064] DeprecationWarning: tls.createSecurePair() is deprecated. Please use tls.Socket instead.
.env file:
NODE_ENV=development
databaseUser=dataReader
databasePassword=***
databaseUrl=***.database.windows.net
databaseName=website
WRITE_FAILED_QUERY_TO_FILE=true
Replacing process.env variables with hard coded strings containing the same info is successful and returns the intended output.

I was putting process.env.(databasedata) in quotes!
process.env is an object.
removed the quotes and everything works.
#MaazSyedAdeeb. ty. Such a blind mistake. It works.

Related

AWS Redis Cluster MOVED Error using redis node library

I have created a Redis MemoryDB cluster with 2 nodes in AWS:
I connect to it using redis node library v4.0.0 like this:
import { createCluster } from 'redis';
(async () => {
const REDIS_USERNAME = 'test-username';
const REDIS_PASSWORD = 'test-pass';
const cluster = createCluster({
rootNodes: [
{
url: `rediss://node1.amazonaws.com:6379`,
},
{
url: `rediss://node2.amazonaws.com:6379`,
},
],
defaults: {
url: `rediss://cluster.amazonaws.com:6379`,
username: REDIS_USERNAME,
password: REDIS_PASSWORD,
}
});
cluster.on('error', (err) => console.log('Redis Cluster Error', err));
await cluster.connect();
console.log('connected to cluster...');
await cluster.set('key', 'value');
const value = await cluster.get('key');
console.log('Value', value);
await cluster.disconnect();
})();
But sometimes I get the error ReplyError: MOVED 12539 rediss://node2.amazonaws.com:6379 and I cannot get the value from the key.
Do you have any idea if there is something wrong with the configuration of the cluster or with the code using redis node library?
Edit:
I tried it with ioredis library and it works, so it's something wrong with the redis library.
Node.js Version: 16
Redis Server Version: 6
I had created an issue to redis library, so it's going to be solved soon with this PR.

Failed to connect to mydb.database.windows.net:1433 in 15000ms (Microsoft Azure SQL Database)

I am able to retrieve data from Microsoft Azure SQL Database using below code: -
const sql = require("mssql");
var config = {
user: "user_name",
password: "Pass#1234",
server: "mydb.database.windows.net",
database: "db_name",
options: {
enableArithAbort: true,
},
stream: true,
};
module.exports = function getQueryResult(query) {
return new Promise((res, rej) => {
sql.connect(config).then((pool) => {
pool.query(query, (err, result) => {
if (err) rej(err);
res(result);
});
});
});
};
I am using getQueryResult function to get the data from database.
Everything is going perfect accept the thing that the below errors occurs in between.
Failed to connect to mydb.database.windows.net:1433 in 15000ms (Microsoft Azure SQL Database)
ConnectionError: Failed to connect to mydb.database.windows.net:1433 read ECONNRESET
ConnectionError: Failed to connect to mydb.database.windows.net:1433 socket hang up
I know this question has been asked before. But I have tried all the solutions. None of the solution was specifically for Microsoft Azure SQL Database so I thought might be there is some problem in database.
Thanks in advance.
Your code is a bit different from mine, my options is enclosed in double quotes. You also can download my sample code, it works for me, I have test it.
Tips:
You need set the rule of Firewalls. Make sure your local or webapp can access dbserver.
My code:
const sql = require('mssql')
const config = {
user: 'username',
password: 'pwd',
server: '***sqlserver.database.windows.net', // You can use 'localhost\\instance' to connect to named instance
database: 'yourdb',
"options": {
"encrypt": true,
"enableArithAbort": true
}
}
const poolPromise = new sql.ConnectionPool(config)
.connect()
.then(pool => {
console.log('Connected to MSSQL')
return pool
})
.catch(err => console.log('Database Connection Failed! Bad Config: ', err))
module.exports = {
sql, poolPromise
}

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
}

CloudSQL connection issues with deployed Bookshelf tutorial app (App Engine/NodeJS)

I deployed my code on app engine with node js (flex environment).
config.json
{
"GCLOUD_PROJECT": "XXXXXX",
"DATA_BACKEND": "cloudsql",
"MYSQL_USER": "XXXX",
"MYSQL_PASSWORD": "XXXXX",
"INSTANCE_CONNECTION_NAME": "XXXXXX:us-central1:XXXXX"
}
model-cloudsql.js
const options = {
user: config.get('MYSQL_USER'),
password: config.get('MYSQL_PASSWORD'),
database: 'XXXXX'
};
if (config.get('INSTANCE_CONNECTION_NAME') && config.get('NODE_ENV') === 'production') {
options.socketPath = `/cloudsql/${config.get('INSTANCE_CONNECTION_NAME')}`;
}
const connection = mysql.createConnection(options);
I am getting below error:
"Cannot enqueue Query after fatal error."
please provides any feedback on it.
It looks like the error "Cannot enqueue Query after fatal error." happens when you try to query a connection that encounter a fatal error during create. If we check out the mysqljs documentation, it recommends connecting with the following:
var mysql = require('mysql');
var connection = mysql.createConnection({
host : 'example.org',
user : 'bob',
password : 'secret'
});
connection.connect(function(err) {
if (err) {
console.error('error connecting: ' + err.stack);
return;
}
console.log('connected as id ' + connection.threadId);
});
As you can see, you need to pass along a callback function to handle any errors that may arise while you are attempting to connect. This callback function will print the error encountered to give you more info on why it failed to connect.
Additionally, you may be interested in this section on handling errors.

Integration tests sporadically timeout on Heroku hobby-dev

Since we do not get any helpful support from help.heroku.com we make the last try here.
We are developping a classic web app consisting of:
----- ----- ----
|WEB| <----> |API| <----> |DB|
----- ----- ----
We currently are working with the following Heroku Dynos/Datastores
Heroku Postgres: Hobby Basic
Heroku API Dyno: Hobby
Heroku WEB Dyno: Hobby
The tech stack is:
runtime: nodejs (4.4.0)
db: postgres (9.6.1)
testframework: jasminejs (2.5.1)
query builder: knexjs (0.10.0)
We recently moved to from self hosted docker environment to Heroku and configured the Herokus CI pipeline which works fine for unit testing - but not integration testing.
The tests sporadically fails with timeouts (in average every 3rd test of the same commit). This is not stable enough to build up CI/CD.
Here the error messages we get:
**************************************************
* Failures *
**************************************************
1) integration test collections repository create() should return AUTHENTICATION_REQUIRED if user is anonymous
- Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
- Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
2) integration test collections repository create() should return AUTHORIZATION_REQUIRED if user is not space MEMBER
- Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
- Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
- Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
3) integration test collections repository create() should return collection if user is space MEMBER
- Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
- Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
- Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
For testing purposes we configured knex connection pooling to use one connection only:
export default {
client: 'pg',
connection: DB_URL,
pool: {
max: 1,
min: 1
}
};
The typical integration test setup is:
describe('integration test', () => {
describe('collections repository create()', () => {
//////////////////////////////////////////////////////////////////////
//Before the test block is execute all fixtures are loaded into the DB
//////////////////////////////////////////////////////////////////////
beforeAll((callback) => {
seed(path.join(__dirname, 'fixtures'))
.then(callback)
.catch((error) => {
fail(error);
callback();
});
});
////////////////////////////////////////////////////////////////////////
//Truncate all data from the DB before the next test block gets executed
////////////////////////////////////////////////////////////////////////
afterAll(resetDB);
it('should return AUTHENTICATION_REQUIRED if user is anonymous', (callback) => {
testUtils.testAsync({
callback,
catchTest: (error) => {
expect(error).toEqual(jasmine.any(repositoryErrors.AUTHENTICATION_REQUIRED));
},
runAsync: create({ props: { space: { id: 1 } } })
});
});
it('should return AUTHORIZATION_REQUIRED if user is not space MEMBER', (callback) => {
testUtils.testAsync({
callback,
catchTest: (error) => {
expect(error).toEqual(jasmine.any(repositoryErrors.AUTHORIZATION_REQUIRED));
},
runAsync: create({ props: { space: { id: 1 } }, userId: 1 })
});
});
it('should return collection if user is space MEMBER', (callback) => {
testUtils.testAsync({
callback,
runAsync: create({ props: { space: { id: 1 } }, userId: 2 }),
thenTest: (outcome) => {
expect(outcome).toEqual({ id: '1' });
}
});
});
...
seed:
const tableOrder = [
'users',
'guidelines',
'collections',
'spaces',
'details',
'files',
'guidelinesAuthors',
'collectionsUsers',
'spacesUsers',
'guidelinesCollections',
'spacesCollections',
'guidelinesDetails',
'guidelinesFiles',
'comments',
'commentsReplies',
'notifications'
];
export default function seed(path) {
return db.raw('BEGIN;')
.then(() => {
return tableOrder.reduce((promise, table) => {
return promise
.then(() => slurp({ path, table }))
.then(() => {
updateIdSequence(table)
.catch((error) => {
// eslint-disable-next-line no-console
console.log(
`Updating id sequence for table '${table}' failed! Error: `,
error.message
);
});
});
}, Promise.resolve()).then(() => db.raw('COMMIT;'));
})
.catch((error) => {
// eslint-disable-next-line no-console
console.log('SEED DATA FAILED', error);
return db.raw('ROLLBACK;');
});
}
...
resetDB:
export default function resetDB(callback) {
const sql = 'BEGIN; '
+ 'SELECT truncateAllData(); '
+ 'SELECT restartSequences(); '
+ 'COMMIT;';
return db.raw(sql)
.then(callback)
.catch((error) => {
// eslint-disable-next-line no-console
console.log('TRUNCATE TABLES FAILED', error);
return db.raw('ROLLBACK;');
});
}
Until now, these test have been running on local machines (Linux/Mac) and Codeship without any problem.
After almost two weeks of trying to get this work we made zero progress on this issue. I can't see anything wrong with this configuration and I start to belive Heroku has a serious issue with the datastores...
Has anybody experienced similar issues on Heroku?
Any idea what we can try else to get this work?

Resources