Telegram bot doesn't run on heroku - node.js

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.

Related

Start nestjs project as a Windows service

We used to start Angular and NestJS (based on node.js) projects using Docker containers. This solution was discontinued for various reasons, so we are looking for a way to start these projects at the start of the PC (or on a trigger) and restart the project automatically if a crash occurs.
node-windows
This package builds a Windows service from a node.js project. NestJS being based on node.js, starting it using node.js is done this way (while in the project's folder):
node PATH_TO_PROJECT\node_modules\#nestjs\cli\bin\nest.js start --config .\tsconfig.build.json
The script used:
const svc = new Service({
name: 'Test',
description: 'Test',
script:
'PATH_TO_PROJECT\\node_modules\\#nestjs\\cli\\bin\\nest.js',
scriptOptions: [
'start --watch --config PATH_TO_PROJECT\\tsconfig.build.json',
],
],
execPath: 'C:\\Program Files\\nodejs\\node.exe',
});
svc.on('install', function () {
console.log('installed');
svc.start();
});
svc.install();
The installation works as intended but in a browser, the server cannot be reached.
Questions
Is there a way to use node-windows for a NestJS project?
Is it possible to use an absolute path with the nest cli start command? (e.g nest start --config ABSOLUTE_PATH)
How would you start an Angular project the same way?
Thank you.
am use 'child_process' lib for run command
like this
server.js
const { exec } = require("child_process");
exec("npm run start", (error, stdout, stderr) => {
if (error) {
console.log(`error: ${error.message}`);
return;
}
if (stderr) {
console.log(`stderr: ${stderr}`);
return;
}
console.log(`stdout: ${stdout}`);
});
and use node-windows like this
var Service = require('node-windows').Service;
var serviceDetail = require('./servicename')();
console.log(serviceDetail);
// Create a new service object
var svc = new Service({
name: serviceDetail.name,
description: serviceDetail.detail,
script: './server.js'
});
console.log('start building up service name ' + serviceDetail.name);
// Listen for the "install" event, which indicates the
// process is available as a service.
svc.on('install',function(){
svc.start();
});
svc.install();

Redis Server connection

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

Service not found after install service node-windows

My install service script as below:
install_windows_service.js
require("dotenv").config();
var Service = require("node-windows").Service;
// Create a new service object
var svc = new Service({
name: "STUtility",
description: "The web app with STUtility tools.",
script: process.env.WORKING_DIRECTORY + "index.js",
nodeOptions: ["--harmony", "--max_old_space_size=4096"],
workingDirectory: process.env.WORKING_DIRECTORY,
allowServiceLogon: true,
env: {
name: "NODE_ENV",
value: "production",
},
});
// Listen for the "install" event, which indicates the
// process is available as a service.
svc.on("install", function () {
svc.start();
console.log("install complete.");
console.log("The service exists: ", svc.exists);
});
// Just in case this file is run twice.
svc.on("alreadyinstalled", function () {
console.log("This service is already installed.");
});
// Listen for the "start" event and let us know when the
// process has actually started working.
svc.on("start", function () {
console.log(svc.name + " started!.");
});
svc.on("error", function () {
console.log("Something went wrong.");
});
svc.on("invalidinstallation ", function () {
console.log(" This service is detected but missing require files");
});
svc.install();
In terminal I run command:
node .\install_windows_service.js
Terminal show:
install complete. The service exists: true
But I cannot find out this service on Windows Services.

node-windows impersonate password issue

I'm running a file watcher app as a windows service (W10) with the following code used to install the service:
var Service = require('node-windows').Service;
const config = require('./SHR_modules/config');
// Create a new service object
var svc = new Service({
name:'SmartHR',
description: 'Smart HR file watcher',
script: require('path').join(__dirname,'watcher.js'),
workingDirectory: __dirname
});
// Listen for the "install" event, which indicates the
// process is available as a service.
svc.on('install',function(){
svc.start();
console.log('installed as user: ' + svc.logOnAs.account)
});
svc.on('uninstall',function(){
console.log('Uninstall complete.');
console.log('The service exists: ',svc.exists);
});
svc.logOnAs.domain = config.sqlServerLogin.domain;
svc.logOnAs.account = config.sqlServerLogin.user;
svc.logOnAs.password = config.sqlServerLogin.password;
svc.install();
//svc.uninstall();
Running the code as an administrator and the service does install properly, but it's stopped, so when I try to start it, the message is that the service can't start for the wrong password. Username and domain are correct. If I copy/paste the password into the Services Manager from my config.js, the service starts up and runs from now on.
Why the password (whatever it is) is not passed by that line:
svc.logOnAs.password = config.sqlServerLogin.password;
correctly?
The XML generator function in the winsw.js is missing one line for the service account.
Original code:
if (config.logOnAs) {
xml.push({
serviceaccount: [
{domain: config.logOnAs.domain || 'NT AUTHORITY'},
{user: config.logOnAs.account || 'LocalSystem'},
{password: config.logOnAs.password || ''},
]
});
}
Working code:
if (config.logOnAs) {
xml.push({
serviceaccount: [
{domain: config.logOnAs.domain || 'NT AUTHORITY'},
{user: config.logOnAs.account || 'LocalSystem'},
{password: config.logOnAs.password || ''},
{allowservicelogon: 'true'}
]
});
}
I'll commit that change to the projects git.

Restarting nodejs server on crashing in an electronjs app

I am building an electron app and using nodejs as the backend server within the app.
How can I auto-restart the nodejs server if it encounters a crash?
I am currently using pm2 and using the following code in electron's main.js file
var pm2 = require("pm2");
pm2.connect(function(err) {
if (err) {
console.error(err);
process.exit(2);
}
pm2.start(
{
name: "mydesktopapp",
script: "./server/server.js", // nodejs Script to be run
exec_mode: "cluster",
instances: 1,
max_memory_restart: "5000M", // Optional: Restarts your app if it reaches 5GB
noDaemonMode: true,
watch: true
},
function(err, apps) {
pm2.disconnect(); // Disconnects from PM2
console.error(`Unable to start PM2: ${err}`);
if (err) throw err;
}
);
});
But this does not seem to work, as its throwing the following error:
Unable to start PM2: null
How do you guys handle this?
Thanks

Resources