Redis disconnection crashing node js server as well - javascript

After reading many stack overflow erros im still unable to solve this issue. I have setup a redis server to cache the data from my node js server , it works fine as long as the redis server is running but as soon as i close the redis server the node server crashes. i want the server to keep working even if the redis server is down
heres my code
import Product from '../models/productModel.js'
import User from '../models/userModel.js'
import slugify from 'slugify'
import redis from 'redis'
import mongoose from 'mongoose'
//connection to redis
const redisClient = redis.createClient(6379) //cause for error when redis server is down
export const listAll = async (req, res) => {
try {
const products = await Product.find({})
.limit(parseInt(req.params.count))
.populate('category')
.populate('subs')
.sort([['createdAt', 'desc']])
.exec()
if (products !== null) {
redisClient.setex(req.params.count, 60, JSON.stringify(products))
}
res.json(products)
} catch (err) {
console.log(err)
}
}
here im getting an ECONNREFUSED error when im stopping the redis server. Is there a way for my node server to keep going even when the redis server is stopped because redis servver is just a supporting mechanism and if cache data is unavailable ill anyway get data from db
is there a way to check if redisClient is undefined or null that i could set to check if the redis server is down and then later i can use it to make the request appropriately

According to the doc of node-redis Error Handling, have you try this ?
client.on("error", function(err) {
assert(err instanceof Error);
assert(err instanceof AbortError);
assert(err instanceof AggregateError);
// The set and get are aggregated in here
assert.strictEqual(err.errors.length, 2);
assert.strictEqual(err.code, "NR_CLOSED");
});

Related

SCRAM-SERVER-FIRST-MESSAGE: client password must be a string

Ive read documentation from several pages on SO of this issue, but i havent been able to fix my issue with this particular error.
throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: client password must be a string')
^
Error: SASL: SCRAM-SERVER-FIRST-MESSAGE: client password must be a string
at Object.continueSession (C:\Users\CNFis\Desktop\WulfDevelopments\ThePantry\node_modules\pg\lib\sasl.js:24:11)
at Client._handleAuthSASLContinue (C:\Users\CNFis\Desktop\WulfDevelopments\ThePantry\node_modules\pg\lib\client.js:257:10)
at Connection.emit (events.js:400:28)
at C:\Users\CNFis\Desktop\WulfDevelopments\ThePantry\node_modules\pg\lib\connection.js:114:12
at Parser.parse (C:\Users\CNFis\Desktop\WulfDevelopments\ThePantry\node_modules\pg-protocol\dist\parser.js:40:17)
at Socket.<anonymous> (C:\Users\CNFis\Desktop\WulfDevelopments\ThePantry\node_modules\pg-protocol\dist\index.js:11:42)
at Socket.emit (events.js:400:28)
at addChunk (internal/streams/readable.js:290:12)
at readableAddChunk (internal/streams/readable.js:265:9)
at Socket.Readable.push (internal/streams/readable.js:204:10)
its as if in my connectDB() function its not recognizing the password to the database. I am trying to run a seeder.js script to seed the database with useful information for testing purposes, and if i run npm run server which is a script that just starts a nodemon server, itll connect to the DB just fine. but when i try to run my script to seed data, i am returning this error.
import { Sequelize } from "sequelize";
import colors from "colors";
import dotenv from "dotenv";
dotenv.config();
const user = "postgres";
const host = "localhost";
const database = "thePantry";
const port = "5432";
const connectDB = async () => {
const sequelize = new Sequelize(database, user, process.env.DBPASS, {
host,
port,
dialect: "postgres",
logging: false,
});
try {
await sequelize.authenticate();
console.log("Connection has been established successfully.".bgGreen.black);
} catch (error) {
console.error("Unable to connect to the database:".bgRed.black, error);
}
};
export default connectDB;
above is my connectDB() file, and again, it works when i run the server normally. but i receive this error only when trying to seed the database. Ill post my seeder script below:
import dotenv from "dotenv";
import colors from "colors";
import users from "./data/users.js";
import User from "./models/userModel.js";
import connectDB from "./config/db.js";
dotenv.config();
console.log(process.env.DBPASS);
connectDB();
const importData = async () => {
try {
await User.drop();
await User.sync();
await User.bulkCreate(users);
console.log("Data Imported".green.inverse);
process.exit();
} catch (e) {
console.error(`${e}`.red.inverse);
process.exit(1);
}
};
const destroyData = async () => {
try {
await User.bulkDestroy();
console.log("Data Destroyed".red.inverse);
process.exit();
} catch (e) {
console.error(`${e}`.red.inverse);
process.exit(1);
}
};
if (process.argv[2] === "-d") {
destroyData();
} else {
importData();
}
Add your .env file in your project, I think your .env file is missing in your project folder.
add like this:
So, i may have figured this out by playing around in another project with sequelize, as it turns out, the initial connection to the database in my server.js file, honestly means nothing. Unlike Mongoose where the connection is available across the whole app. its not the same for Sequelize this connection that it creates is only apparent in certain places, for example i was trying the same process in my other project as i am here, except i was trying to read data from my DB using the model that i built with sequelize and i was receiving the same type error, i went into where i defined the model and made a sequelize connection there, and i was then able to read from the database using that object model.
Long story short, to fix the error in this app i have to place a connection to the database in the seeder.js file or i have to place a connection in the User model (this is ideal since ill be using the model in various places) to be able to seed information or read information from the database.
today i have same problem like this, so if you use database with type relational. you must define password from database.
const user = "postgres";
const host = "localhost";
const database = "thePantry";
const password = "yourdatabasepassword"; if null > const password = "";
const port = "5432";
but, if you use database with type non-relational, as long as the attributes are the same, you can immediately run the program as you defined it
I also faced this issue and another solution different from the accepted solution here solved my issue, so I wanted to explain that to this lovely community, too.
Firstly, when I faced the issue, ran my project in debug mode and reached the code below.
let sequelize;
if (config.use_env_variable) {
sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
sequelize = new Sequelize(config.database, config.username, config.password, config);
}
The problem here is actually obvious when I saw first, there is a problem in .env file as mentioned in the solutions above. In my process.env is defined as like as following line: DATABASE_URL=postgres://username:password#IP_adress:port/db_name and my config.js file is in the following format:
module.exports = {
"development": {
"url":"postgres://username:password#IP_adress:port/db_name",
"dialect": "postgres",
}, ...
}
So as a solution, I come with the following fix for the parameters that are inside Sequelize(...). My solution below is totally worked for me and I hope it also works for you too.
let sequelize;
if (config.use_env_variable) {
sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
sequelize = new Sequelize(config.url, config);
}
Finally, the point you need to be careful about what you have written to the config file. That's the most important in this case.
Farewell y'all.
Here is my case. I have postgresql connection url in my enviroment like:
POSTGRES=postgres://postgres:test#localhost:5432/default
But my config getting like:
POSTGRES_DB_HOST=localhost
POSTGRES_DB_PORT=5432
...rest of configs
Now it has resolved.
I faced this issue because I was trying to execute nodemon from a parent folder. Once I changed my pwd, the error was resolved.
For your seeder script, i'm doing something similar but not using Sequilize, just the node-postgres package in an ExpressJS app.
To give context (so you know if this applies to your situation)
I run a separate script for testing, which uses database credentials to test batched emailing. So, I need to access my database (eventually will migrate it to an AWS lambda function).
I need to access my database and run sequential actions, since I'm not spinning up my server, all that 'under the hood' processes that would normally start your connection pool is probably not running. My guess ( I know it's an old post but this may help others).
Try passing your hardcoded password credentials. first on your seeder.js file. (i'm sure you've tried this already).
Try creating a new Pool within your seeder script and pass it your credentials (try hard coding it first to see if it works).
Pool in postgres takes a client config with the following properties (i use this to get mine to work).
const pool = new Pool({
user: '****',
database: '****',
password: '****',
port: 5432,
host: '****',
max: 5,
idleTimeoutMillis: 30000,
connectionTimeoutMillis: 5000,
})
I imagine sequilize will have a similar configuration, so try playing around with that.
Then I just connect to the pool and do everything I'd normally do.
Hope this helps with a bit of the troubleshooting. I had the EXACT same error message earlier. Ultimately I had to restructure my code to 'boot up' the Client/Connection Pool for the database. It sounds like you're not properly 'booting up' your connection so try doing it manually within your seeder script (don't pass process.env.DB_PASSWORD at first).
I saw this error when running a npx sequelize-cli db:... command
and my postgres server wasn't running or able to accept connections.
To fix it, I had to be running: postgres -D /usr/local/var/postgres in the background.

NodeJS with socket.io and postgres LISTEN

I'm trying to get my frontend to watch for events whenever a certain table on my postgres db is altered.
The Postgres events fire perfectly and I'm able to relay them to through the Socker.io connection, but I'm having reliability issues. I'm getting (node:26) UnhandledPromiseRejectionWarning: Error: Client was closed and is not queryable errors on my server and often events are not emitted and caught by Socket. I'm assume it has to do with the way I connect to Socket / db clients.
pg config:
const {Pool} = require('pg');
const production = process.env.NODE_ENV === 'production';
const connectionString = `postgresql://${process.env.DB_USER}:${process.env.DB_PASSWORD}#${process.env.DB_HOST}:${process.env.DB_PORT}/${process.env.DB_DATABASE}`
const pool = new Pool({
connectionString: process.env.CONNECTION_STRING ? process.env.CONNECTION_STRING : connectionString,
ssl: production,
connectionTimeoutMillis : 5000,
idleTimeoutMillis : 30000
});
index.js
io.of("/marketDetails").on('connect', (socket) => {
pool.connect((err, client, release) => {
if (err) {
console.log(err);
return;
}
client.query('LISTEN update_table');
client.on('notification', async(data) => {
console.log("notified of table change")
handleDBEvent(socket, data);
})
socket.on("disconnect", () => {
client.query('UNLISTEN update_table');
})
release();
})
});
I get notified on certain table changes but very inconsistently.
You are immediately releaseing the database client that you acquired, before any notifications can happen, and you're getting the error message every time the socket disconnects and you try to run the UNLISTEN command on the released client whose connection was closed after 30s.
Instead, use
socket.on("disconnect", async () => {
try {
await client.query('UNLISTEN update_table');
} finally {
release();
}
});
Btw I would recommend not to acquire a new database connection for each socket.io client, the database is far too valuable for that. Instead, create a single client for your app (you might not even need a pool), have it listen to the update_table events (maybe only when sockets are connected), and then broadcast each event to all currently-connected sockets.

websocket connection closes upon writing to file

so i am connecting a client to a server using websockets (ws). i successfully send msgs to the server and send it back to the client.Problem is when I try to write the received message to a file the server disconnects the client. The message is successfully written but i end up disconnecting client. Looks like something about the write functions disconnect my client. I am using fs.writFile(), I already tried fs.createWriteStream(). Reading the file however does not disconnect it.
const http = require('http');
const WebSocket = require('ws')
const fs = require('fs');
let counts = [0,0]
const server = http.createServer((req,res)=>{
console.log(' Received request for ' + request.url);
});
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection',(ws)=>{
console.log("serving...")
ws.on('message',(message)=>{
console.log("Received:"+message)
if(message ==='1'){
counts[0]=parseInt(counts[0])+1
fs.writeFile('votecnts.txt',`${counts[0].toString()} ${counts[1].toString()}`,(err) =>{
if(err) throw err
})
}
else if (message==='2'){
counts[1]=parseInt(counts[1])+1
fs.writeFile('votecnts.txt',`${counts[0].toString()} ${counts[1].toString()}`,(err) =>{
if(err) throw err
})
}
else{console.log(typeof(message))}
ws.send("cand_one: "+counts[0].toString()+"\n cand_two: "+counts[1].toString())
})
ws.on('close',function(){
console.log("lost client")
})
})
So I figured it out. I was running both server and client on localhost while developing. And therefore the file directories are the same. I later found out that it is impossible to write to file in javascript at the client side because of security reasons. So all I did was to change the url of the server to a remote machine and I was able to write to file using server code. specifically with the writeFile() function in the code above. I actually did not have to touch my code. It was just about configuration and set up.

Trying to connect node.js to a mongodb, getting successful response but no connection

I have been following online instructions to set up a mongodb database using mongoose on node.js. I have managed to get the mongodb running and listening on port 27017, however when I run my connection code in node.js I get a successful response even when the mongo.db isn't running and I don't see any updates on the mongo.db to say it has received any data.
I have tried quite a few different examples from the internet but can't get any of them to work.
So I have my MongoDB saying:
2019-03-26T12:00:46.039+0000 I NETWORK [initandlisten] waiting for connections on port 27017
This is the basic code I am trying to get to work as my original API wasn't working:
//sample.js
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/test', function(err){
if(!err) console.log('Successfully Connected');
console.log(mongoose.connection.host);
console.log(mongoose.connection.port);
});
I receive this response when I run
node sample.js
Successfully Connected
localhost
27017
But I receive this response even when my mongo.db has been shut down, so I think there is some error, I'm not sure how to check if they are connecting properly.
this works for me. try to set some debugging to find out what is happening.
mongoose.set('debug', true);
mongoose.connect("mongodb://localhost:27017/test", {useNewUrlParser: true})
.then(() => {
console.log('connected to the db');
})
.catch(err => {
console.log('connection failed ' + err);
});
I think you have to check the API to connect.
https://mongoosejs.com/docs/connections.html
Second parameter is option and third is callback - but u seem to have passed callback as second param - also, check what are you getting as response
mongoose.connect(uri, options, function(error) {
// Check error in initial connection. There is no 2nd param to the callback.
});
// Or using promises
mongoose.connect(uri, options).then(
() => { /** ready to use. The `mongoose.connect()` promise resolves to undefined. */ },
err => { /** handle initial connection error */ }
);

Express.js cannot connect to mongodb

Im on OS x. Im running an express.js app. This is what I have in app.js:
var express = require('express');
var mongoose = require('mongoose');
var cn = 'mongodb://localhost/test';
mongoose.connect(cn, function(error) {
console.log("inside?");
console.log(res);
});
console.log("outside");
If I open a terminal a write:
mongo
then I see this:
MongoDB shell version v3.4.3
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.4.3
Server has startup warnings:
2017-04-13T16:25:17.440+0200 I CONTROL [initandlisten]
2017-04-13T16:25:17.440+0200 I CONTROL [initandlisten] ** WARNING: Access control is not enabled for the database.
2017-04-13T16:25:17.440+0200 I CONTROL [initandlisten] ** Read and write access to data and configuration is unrestricted.
2017-04-13T16:25:17.440+0200 I CONTROL [initandlisten]
> show dbs
admin 0.000GB
local 0.000GB
test 0.000GB
When I run
node app.js
The only thing I see in the terminal is:
outside
So it never goes inside "connect"? I have a callback because I realized that when I tried to communicate with database the code hangs up. I dont get any error message but it seems I never can query mongodb from express. What is wrong? I have tried several different connection string, for example 127.0.0.1 or even 127.0.0.1:27017 but no luck.
nothing wrong your code, you will get reponse after outside because node.js is not blocking the next code execution, once callback return the value you will get the output. its working for me.
var express = require('express');
var mongoose = require('mongoose');
var cn = 'mongodb://localhost/test';
mongoose.connect(cn, function(error) {
console.log("inside?");
console.log(error);
});
console.log("outside");
output console:
outside
inside?
undefined
Using 'async' or putting the connection initialization part inside a promise will make sure that the execution gets blocked till the connection has been made.
await mongoose.connect(cn, function(error) {
console.log("inside?");
console.log(res);
});
If you're using await make sure the function has the async keyword.
Using a promise:
return new Promise((resolve, reject) => {
mongoose.connection.on('open', () => {
debug('Connection successfully made');
resolve();
});
mongoose.connection.on('error', () => {
debug('Error occurred');
reject();
});
});

Categories

Resources