Redis Server connection - node.js

I am trying to run my node/express app on AWS EC2 but am getting errors from Redis, it will not connect to the server and I am not sure what the problem is??
Here is the error I get after the command "npm run production"
Is there a special configuration when running Redis remotely vs locally?
Thank you!
ERROR
[ec2-user#ip-000-00-00-00 application-node-app]$ npm run production
> task-manager#1.0.0 production
> env-cmd -f ./config/prod.env nodemon src/index.js
[nodemon] 2.0.6
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `node src/index.js`
server is live on port 3000
Error Error: Redis connection to 127.0.0.1:6379 failed - connect ECONNREFUSED
127.0.0.1:6379
// 9x Redis retry errors, all identical
REDIS CODE
const mongoose = require(`mongoose`)
const redis = require(`redis`)
const util = require(`util`)
const redisUrl = `redis://127.0.0.1:6379`
const client = redis.createClient(redisUrl)
client.hget = util.promisify(client.hget)
const exec = mongoose.Query.prototype.exec
client.on("error", function (err) {
console.log("Error " + err);
});
mongoose.Query.prototype.cache = function(options = {}) {
this.useCache = true
this.hashKey = JSON.stringify(options.key || `default`)
return this
}
mongoose.Query.prototype.exec = async function () {
if (!this.useCache) {
return exec.apply(this, arguments)
}
const key = JSON.stringify(Object.assign({}, this.getQuery(), {
collection: this.mongooseCollection.name
}))
const cacheValue = await client.hget(this.hashKey, key)
if (cacheValue) {
console.log(`cached DATA!`)
const doc = JSON.parse(cacheValue)
return Array.isArray(doc) ? doc.map(d => new this.model(d)) : new this.model(doc)
}
const result = await exec.apply(this, arguments)
client.hset(this.hashKey, key, JSON.stringify(result), `EX`, 10)
return result
}
module.exports = {
clearHash(hashKey) {
client.del(JSON.stringify(hashKey))
}
}

There isn't any change in redis to run it locally or remotely.
What you need to make sure instead is, Do you have connectivity to redis from your EC2 instance.
Worst case you can try installing redis-cli on to the EC2 instance and figure out from there. I believe it might be port forwarding issue or IP Tables issue.
You should of course restart from a fresh EC2 instance once the testing is done.
Edit: One thing I wish to add here though, Even though I said there is no change in redis, make sure that it's bound on 0.0.0.0 and not on 127.0.0.1 and make sure to check the port config

Related

exec node server not terminating

Hello :) I am trying to setup integration tests for my Express web app.
To start the API/backend servers locally, I have two scripts in package.json:
"dev-api": "cross-env BACKEND_HOSTNAME=localhost ts-node-dev --respawn api-index.ts",
"dev-backend-default": "cross-env CUSTOMER_NAME=default BACKEND_HOSTNAME=localhost ts-node-dev --respawn backend-index.ts",
When running integration tests, I start and kill the servers like so:
async function runTests() {
try {
const api = exec("npm run dev-api"); // Start API server
for (const siteVersion of siteVersions) {
const frontend = exec(`npm run dev-backend-${siteVersion}`); // Start correct version of backend server
// Wait for servers to start
let driver = null;
await new Promise((resolve, reject) => {
setTimeout(() => {
driver = initDriver("firefox");
runAllTests(driver).then(((resolve) => {
resolve();
}).bind(null, resolve));
}, 5000, resolve);
});
console.log("Killing frontend server for siteVersion: ", siteVersion);
exec('taskkill /F /T /PID ' + frontend.pid);
}
console.log("Killing API server");
exec('taskkill /F /T /PID ' + api.pid);
} catch (err) {
console.log(err);
}
}
The tests run, I get all the way down to the logging for killing the servers.
However, node is still running after the servers were "killed". And when I try to start up the API server locally, with my dev script in package.json, it tells me:
Error: listen EADDRINUSE: address already in use :::8081
at Server.setupListenHandle [as _listen2] (net.js:1331:16)
at listenInCluster (net.js:1379:12)
at Server.listen (net.js:1465:7)
at Function.listen (C:\Users\s0116213\Documents\Work\DownloadWebsite\node_modules\express\lib\application.js:635:24)
at C:\Users\s0116213\Documents\Work\DownloadWebsite\controllers\apiController.ts:88:6
at Generator.next (<anonymous>)
at C:\Users\s0116213\Documents\Work\DownloadWebsite\controllers\apiController.ts:31:71
at new Promise (<anonymous>)
at __awaiter (C:\Users\s0116213\Documents\Work\DownloadWebsite\controllers\apiController.ts:27:12)
at startApi (C:\Users\s0116213\Documents\Work\DownloadWebsite\controllers\apiController.ts:51:12)
[ERROR] 13:41:29 Error: listen EADDRINUSE: address already in use :::8081
I also tried shutting down the servers with frontend.kill() and api.kill(), but it didn't change anything.
Is there a way to kill node when it's started this way?

Telegram bot doesn't run on heroku

Problem
My problem is that when trying to deploy bot on heroku I get r10 error boot timeout, but it works when running locally and I cant seem to find the fix for it
heroku logs
Error R10 (Boot timeout) -> Web process failed to bind to $PORT within 90 seconds of launch
Stopping process with SIGKILL
Process exited with status 137
State changed from starting to crashed
My code
process.env.NTBA_FIX_319 = 1
const TelegramBot = require('node-telegram-bot-api')
require('dotenv').config()
const token = process.env.TOKEN
const myInfo = process.env.INFO
const error = process.env.ERROR
const git = process.env.GIT
const bot = new TelegramBot(token, { polling: true })
bot.on('message', (msg) => {
const chatId = msg.chat.id
const name = msg.chat.first_name
const { text } = msg
if (text === '/start' || text === '/help') {
bot.sendMessage(chatId, `Hi ${name}! These are the commands below:`, {
reply_markup: {
keyboard: [
[
{ text: '/start' },
{ text: '/about' },
{ text: '/links' },
{ text: '/help' },
],
],
resize_keyboard: true,
one_time_keyboard: true,
},
})
} else if (text === '/about') {
bot.sendMessage(chatId, `${myInfo}`)
} else if (text === '/links') {
bot.sendMessage(chatId, `${git}`)
} else {
bot.sendMessage(chatId, `${error}`)
}
})
Dockerfile
FROM node:16.13.2-alpine
WORKDIR /Bot1
ENV PORT 88
COPY package.json /Bot1/package.json
RUN npm install
COPY . .
CMD ["node", "app.js"]
comands to deploy bot
heroku container:push web
heroku container:release web
You have deployed your code as a web process. web processes listen for HTTP requests and must bind to a port provided at runtime shortly after starting up.
Since your bot does not respond to HTTP requests it should not be deployed as a web process. A common name for such processes is worker.
First, remove the web container you have already deployed:
heroku container:rm web
Now, redeploy your code as a worker process:
heroku container:push worker
heroku container:release worker
You may need to scale your dynos after doing this. Something like
heroku ps:scale worker=1
should do the trick.

Can't connect to mongoose on test environment

I have a node application running in docker with mongodb and it works fine on development environment. However, I'm creating some tests with mocha and chai and I can't connect to mongo when I run these tests.
The function I want to test is:
const Interactor = require("interactor");
const Donation = require("../models/donations");
module.exports = class CreateDonation extends Interactor {
async run(context) {
this.context = context;
this.donation = new Donation.Model({
donationId: context.id,
status: context.status,
amount: context.chargeInfo.donatedValue,
donatorEmail: context.donatorInfo.email,
source: context.source,
});
await this.donation.save();
}
rollback() {
Donation.Model.findOneAndRemove({ donationId: this.context.id });
}
};
My test:
/* eslint-disable no-unused-vars */
/* eslint-disable no-undef */
const chai = require("chai");
const chaiHttp = require("chai-http");
const CreateDonation = require("../../interactors/create-donation");
require("../../config/db");
const should = chai.should();
const { expect } = chai;
chai.use(chaiHttp);
describe("CreateDonation", () => {
it("Creates a donation when context passed is correct", async (done) => {
const context = {
id: "123123",
status: "AUTHORIZED",
chargeInfo: {
donatedValue: 25.0,
},
donatorInfo: {
email: "test#example.com",
},
source: "CREDIT_CARD",
};
const result = await CreateDonation.run(context);
console.log(result);
done();
});
});
My db config file:
const mongoose = require("mongoose");
require("dotenv/config");
mongoose
.connect("mongodb://db:27017/donations", {
useNewUrlParser: true,
useUnifiedTopology: true,
reconnectInterval: 5000,
reconnectTries: 50,
})
.then(() => {
console.log("good");
})
.catch((err) => {
console.log(err);
});
mongoose.Promise = global.Promise;
module.exports = mongoose;
The error I get from the test above is:
MongooseServerSelectionError: getaddrinfo ENOTFOUND db
What am I doing wrong? Am I missing to import something?
When you run your services inside docker with a docker compose file, they'll get an hostname based on the name you wrote for the service inside the docker-compose file.
Example:
version: "3.9"
services:
web:
build: .
ports:
- "5000:5000"
redis:
image: "redis:alpine"
In this example, the web service can reach the redis db at the redis hostname.
If you change the service name in this way:
db:
image: "redis:alpine"
The web service must connect to the db host.
So, when you run the compose file, your the db service is reached with the db hostname from you app service. But when you run your tests outside a docker compose, the db hostname isn't available and you need to use localhost because your db is running on your OS directly (or it is running inside a container with the 27017 port mapped on the main host).
If you're using a unix OS, you can solve your problem adding an alias in your /etc/hosts file:
127.0.0.1 localhost db
In this way you can run your tests keeping the db connection string.
Otherwise, and this is the suggested solution, you can use an environment variable to change the connection string at the application startup:
mongoose.connect(process.env.MONGO_URI)
And run it using
MONGO_URI=mongodb://db:27017/donations npm start
Then in the docker compose you can add a fixed environment variable using this code:
environment:
- MONGO_URI=mongodb://db:27017/donations
Just found out that when testing, I need to use "localhost" on my connection string for mongo (I was using the name from docker-compose). So with the URI as "mongodb://localhost:27017/donations" it worked. I don't know why.

Can't connect to Socket.io Error: xhr poll error

Hi i'm using Homestead with a laravel application.
I can't get the client to receive the data on from the server...
My socket.js:
var server = require('http').Server();
var io = require('socket.io')(server);
var Redis = require('ioredis');
var redis = new Redis();
redis.subscribe('test-channel');
redis.on('message', function (channel, message) {
message = JSON.parse(message);
io.emit(channel + ':' + message.event, message.data);
});
/*Booting Up the Server : port 3000 */
server.listen(3000 , function(){
console.log('The Server Is Running');
});
This is listening to port 3000 which is working.
Console output:
vagrant#homestead:~/code/chatting-app$ nodemon -L socket.js
[nodemon] 1.11.0
[nodemon] to restart at any time, enter `rs`
[nodemon] watching: *.*
[nodemon] starting `node socket.js`
The Server Is Running
On the client side i'm also listening to port 3000.
i use a piece of code to display the error:
function checkSocketIoConnect(url, timeout) {
return new Promise(function(resolve, reject) {
var errAlready = false;
timeout = timeout || 5000;
var socket = io(url, {reconnection: false, timeout: timeout});
// success
socket.on("connect", function() {
clearTimeout(timer);
resolve();
socket.close();
});
// set our own timeout in case the socket ends some other way than what we are listening for
var timer = setTimeout(function() {
timer = null;
error("local timeout");
}, timeout);
// common error handler
function error(data) {
if (timer) {
clearTimeout(timer);
timer = null;
}
if (!errAlready) {
errAlready = true;
reject(data);
socket.disconnect();
}
}
// errors
socket.on("connect_error", error);
socket.on("connect_timeout", error);
socket.on("error", error);
socket.on("disconnect", error);
});
}
checkSocketIoConnect("http://192.168.10.10:3000").then(function() {
console.log('succes');
}, function(reason) {
console.log(reason);
});
But this displays the following error:
Error: xhr poll error
Stacktrace:
[14]</n.prototype.onError#https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.3.7/socket.io.min.js:1:24221
[17]</</o.prototype.doPoll/<#https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.3.7/socket.io.min.js:1:29697
[9]</n.prototype.emit#https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.3.7/socket.io.min.js:1:13388
[17]</</i.prototype.onError#https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.3.7/socket.io.min.js:1:31004
i don't know what to do?! I tried everything i can think of.
My homestead.Yaml file:
Any help is appreciated...
IT WAS ADBLOCKER
Disabled adblocker for this page and it works now.
Stupid.........

Mongoose hangs and I don't have any connection errors

I am working on my ubuntu, and this always hangs :
router.route('/articles')
// get all the articles (accessed at GET http://localhost:8080/api/articles)
.get(function(req, res) {
Article.find().sort('-created_at').exec(function(err, articles) {
if (err)
res.send(err);
res.json(articles);
});
});
but not just this one, it seems to be the same with all my collections, but I can see them fine in mongo shell or Robomongo.
I don't think it is a connection error because I don't have any :
// database
var mongoose = require('mongoose');
console.log(config.database);
mongoose.set('debug', true);
mongoose.connect('mongodb://localhost:27017/test', function(err) {
if (err) {
console.err(err);
} else {
console.log('Connected');
}
});
mongoose.connection.on('error', function(err) {
if (err) {
console.err(err);
} else {
console.log('Connected');
}
});
Dont know if it's relevant but I have warnings when using the mongo shell :
2015-09-08T19:07:12.200+0100 I CONTROL [initandlisten]
2015-09-08T19:07:12.200+0100 I CONTROL [initandlisten] ** WARNING: soft rlimits too low. rlimits set to 31125 processes, 64000 files. Number of processes should be at least 32000 : 0.5 times number of files.
I am very surprised because it worked just a few days ago, I am starting to think I may have a problem with my system.
FYI my full project on github : https://github.com/mael-jarnole/website
I have been struggling with this issue the whole afternoon, and could'nt get anything done.
console
---------$ nodemon server.js
8 Sep 19:26:19 - [nodemon] v1.4.1
8 Sep 19:26:19 - [nodemon] to restart at any time, enter `rs`
8 Sep 19:26:19 - [nodemon] watching: *.*
8 Sep 19:26:19 - [nodemon] starting `node server.js`
mongodb://localhost:27017/test
Listening on: 8080
css file written on disk successfully !
Connected
Something is happening with the API.

Resources