Error: 4 DEADLINE_EXCEEDED: Deadline exceeded on CloudRUN - node.js

I got google express app which deployed in Google CloudRun.
I would like to use some shared data which relevant to all users and loading it to global parameters.
My code is using google secret manager to retrieve some database connection info for retrieving data into global parameters.
When the app is cold, the first user gets error message but initiates async function which loading the data into global parameters, eventually the next calls will be served correctly.
Everything is working fine buy recently I noticed an error when trying to connect to Google secret manager:
Error: 4 DEADLINE_EXCEEDED: Deadline exceeded
at Object.callErrorFromStatus (/usr/src/app/node_modules/#google-cloud/secret-manager/node_modules/#grpc/grpc-js/build/src/call.js:30:26)
at Object.onReceiveStatus (/usr/src/app/node_modules/#google-cloud/secret-manager/node_modules/#grpc/grpc-js/build/src/client.js:175:52)
at Object.onReceiveStatus (/usr/src/app/node_modules/#google-cloud/secret-manager/node_modules/#grpc/grpc-js/build/src/client-interceptors.js:341:141)
at Object.onReceiveStatus (/usr/src/app/node_modules/#google-cloud/secret-manager/node_modules/#grpc/grpc-js/build/src/client-interceptors.js:304:181)
at Http2CallStream.outputStatus (/usr/src/app/node_modules/#google-cloud/secret-manager/node_modules/#grpc/grpc-js/build/src/call-stream.js:116:74)
at Http2CallStream.maybeOutputStatus (/usr/src/app/node_modules/#google-cloud/secret-manager/node_modules/#grpc/grpc-js/build/src/call-stream.js:155:22)
at Http2CallStream.endCall (/usr/src/app/node_modules/#google-cloud/secret-manager/node_modules/#grpc/grpc-js/build/src/call-stream.js:141:18)
at Http2CallStream.cancelWithStatus (/usr/src/app/node_modules/#google-cloud/secret-manager/node_modules/#grpc/grpc-js/build/src/call-stream.js:457:14)
at Timeout.<anonymous> (/usr/src/app/node_modules/#google-cloud/secret-manager/node_modules/#grpc/grpc-js/build/src/deadline-filter.js:59:28)
at listOnTimeout (internal/timers.js:554:17) {
My code is something like that:
const { SecretManagerServiceClient } = require('#google-cloud/secret-manager');
const smClient = new SecretManagerServiceClient();
const express = require('express');
const bodyParser = require('body-parser')
let jsonParser = bodyParser.json()
const pkg = require('./package');
// ============== Express App ========
const app = express();
// Serve the files in /assets at the URI /assets
app.use('/assets', express.static('assets'));
//Params
global.Param1 = null;
global.Param2 = null;
let PgPwd = null;
app.post('/Test', jsonParser, async (req, res) => {
try
{
loadParams();
common.errors_client.report("Params were not loaded");
throw new Error("Params were not loaded");
}
catch (err) {
return res.status(400);
}
}
async function loadParams() {
try {
const promise1 = loadDataFromPostgresqlToParam1();
const promise2 = loadDataFromPostgresqlToParam2();
await Promise.all([promise1, promise2]);
}
catch (err) {
throw new Error(err);
}
}
async function loadDataFromPostgresqlToParam1() {
try {
//=============== PostgresSQL ==================
let pg_client = await getPgClient();
await pg_client.connect()
const resPg = await pg_client.query('select * from tabel1');
await pg_client.end()
let Param1 = JSON.parse(JSON.stringify(resPg));
}
}
async function loadDataFromPostgresqlToParam2() {
try {
//=============== PostgresSQL ==================
let pg_client = await getPgClient();
await pg_client.connect()
const resPg = await pg_client.query('select * from tabel2');
await pg_client.end()
let Param2 = JSON.parse(JSON.stringify(resPg));
}
}
async function getPgClient() {
var ret_client;
if (PgPwd == null) {
await getSecret().then((localPwd) => {
PgPwd = localPwd; // assign to global variable
})
};
ret_client = new Client({
user: process.env.pgUser,
host: process.env.pgHost,
database: process.env.pgDataBase,
password: PgPwd,
port: process.env.pgPort
});
return ret_client;
}
async function getSecret() {
const [version] = await smClient.accessSecretVersion({
name: process.env.pgpwdlocation
});
const pwd = version.payload.data.toString();
return pwd;
}
Not sure what could be the reason for that.
The error is not consistent.

Related

Issue leveraging keycloak-verify to instantiate keyclock object verifier

I'm leveraging this library here (https://www.npmjs.com/package/keycloak-verify)
For some reason.. requiring the class and then trying to instantiate gives me an error
TypeError: Keycloak is not a function
My code is below, I have also tried to print out the Keycloak object from the const and it gives me
{ default: [Function: Keycloak] }
Shouldn't just calling Keycloak() leverage that default function instead of giving me an error?
Thanks!
const Keycloak = require('keycloak-verify');
const run = async() => {
console.log(Keycloak)
const config = { realm: 'users', authServerUrl: 'localhost://8080' };
const keycloak = Keycloak(config);
const accessToken = '12312';
try {
const user = await keycloak.verifyOnline(accessToken);
console.log(user);
} catch(e) {
console.log(e);
}
}
run();
Looking at the compiled index.js it shows
var Keycloak = function Keycloak(config) {
return {
verifyOnline: verifyOnline(config),
verifyOffline: verifyOffline(config)
};
};
var _default = Keycloak;
exports["default"] = _default;

node-media-server: session.reject() not working

I am trying to create an RTMP-server with the npm package: http://github.com/illuspas/Node-Media-Server. So the server works fine but I need to implement authentication in it. I am trying to check the authentication on "prePublish" event. I am querying the database and retrieving the user if the user was found then I want to let the user stream otherwise rejected. But the problem is, it doesn't leave it instead disconnects and then the stream automatically reconnected to it then it disconnects again and the loop goes on. How do I fix this problem?
Here is the code for the event:
const NodeMediaServer = require('node-media-server');
const config = require('./config').rtmp_server;
const db = require('./db');
const nms = new NodeMediaServer(config);
const getStreamKeyFromStreamPath = (path) => {
const parts = path.split('/');
return parts[parts.length - 1];
};
nms.on('prePublish', async (id, StreamPath, args) => {
const session = nms.getSession(id);
try {
const streamKey = getStreamKeyFromStreamPath(StreamPath);
const validStream = (
await db.query('SELECT * FROM public."People" WHERE stream_key = $1', [streamKey])
).rows[0];
console.log(validStream);
if (validStream) {
// do stuff
} else {
session.reject((reason) => {
console.log(reason);
});
}
console.log(
'[NodeEvent on prePublish]',
`id=${id} StreamPath=${StreamPath} args=${JSON.stringify(args)}`
);
} catch (err) {
session.reject();
}
});
module.exports = nms;
Here is the code of the entry point of the server:
require("dotenv").config();
const db = require("./db");
const nms = require("./nms");
// database connection
db.connect()
.then(() => {
console.log("Connected to database");
// start the rtmp server
nms.run();
})
.catch((err) => console.log(err.message));
Here is the db file:
const { Pool } = require('pg');
const connectionString = process.env.PG_CONNECTION_STRING;
const poolOptions = {
host: process.env.PG_HOST,
user: process.env.PG_USER,
port: process.env.PG_PORT,
password: process.env.PG_PASSWORD,
database: process.env.PG_DATABASE,
};
const pool = new Pool(process.env.NODE_ENV === 'production' ? connectionString : poolOptions);
module.exports = pool;
My procedures to solve that problem:
Instead of the async function, I tried to handle the database query using a callback but it didn't work.
Before I was calling session.reject() now I am passing a callback there but the behavior is still the same
If you have any solution for that, please let me know.
Thanks in advance

AWS lambda sending sns message to phone number

I have a lambda function running node.js The function makes database calls and sends a text message via sns. It has the following structure
the functions -> index.js file looks like this
async function sendTextMessage(message, phoneNumber) {
try {
console.log("hitSendFunction");
const sns = new AWS.SNS();
const params = {
Message: message,
MessageStructure: "string",
PhoneNumber: phoneNumber
};
//remember phone number must have +1 before it.
return await sns.publish(params).promise();
} catch (error) {
console.log(error);
}
}
module.exports = {
sendTextMessage
};
that function is than called in the main index.js file:
const database = require("./db");
const { sendTextMessage } = require("./functions");
const AWS = require("aws-sdk");
AWS.config.region = "us-east-1";
exports.handler = async function (event, context) {
try {
console.log("hit");
const result = await database.query("call getTicker()");
const data = result[0][0];
const currentProjectEndDate = new Date(
data.currentProjectEndDate
).getTime();
const now = new Date().getTime();
console.log("data.currentProjectEndDate", data.currentProjectEndDate);
const runningHot =
data.jobsInQueue > 0 && currentProjectEndDate <= now && data.textSent < 1;
if (runningHot) {
const numbers = ["+1435994****"];
for (let i = 0; i < numbers.length; i++) {
let number = numbers[i];
console.log("number", number);
let messageResult = await sendTextMessage(
"The CE Bot is running hot from lambda",
number
);
console.log("messageResult", messageResult);
}
await database.query("call insertIntoTextSent()");
console.log("yes");
}
} catch (error) {
console.log("this was the error", error);
}
The database calls work correctly but the textMessage function just hangs and times out. The lambda function has the following permissions attached to it:
Finally even though I do not think it is needed as the db code is working here is what the db -> index.js file looks like:
const mysql = require("mysql");
const util = require("util");
const awsConfig = {
host: process.env.RDS_HOST,
user: process.env.RDS_USER,
password: process.env.RDS_PASSWORD,
database: process.env.RDS_DATABASE
};
const connection = mysql.createConnection(awsConfig);
connection.query = util.promisify(connection.query.bind(connection));
connection.end = util.promisify(connection.end.bind(connection));
module.exports = connection;
I am not quite sure where I am going wrong here. Can someone point me in the right direction?
You can just send it via sms in sns just type in the phone number

pool.request is not a function

I would like to setup my prepared statements with the mssql module. I created a query file for all user related requests.
const db = require('../databaseManager.js');
module.exports = {
getUserByName: async username => db(async pool => await pool.request()
.input('username', dataTypes.VarChar, username)
.query(`SELECT
*
FROM
person
WHERE
username = #username;`))
};
This approach allows me to require this query file and access the database by executing the query that is needed
const userQueries = require('../database/queries/users.js');
const userQueryResult = await userQueries.getUserByName(username); // call this somewhere in an async function
My database manager handles the database connection and executes the query
const sql = require('mssql');
const config = require('../config/database.js');
const pool = new sql.ConnectionPool(config).connect();
module.exports = async request => {
try {
const result = await request(pool);
return {
result: result.recordSet,
err: null
};
} catch (err) {
return {
result: null,
err
}
}
};
When I run the code I get the following error
UnhandledPromiseRejectionWarning: TypeError: pool.request is not a
function
Does someone know what is wrong with the code?
I think this happens because the pool is not initialized yet... but I used async/await to handle this...
Here is how I made your code work (I did some drastic simplifications):
const sql = require("mssql");
const { TYPES } = require("mssql");
const CONN = "";
(async () => {
const pool = new sql.ConnectionPool(CONN);
const poolConnect = pool.connect();
const getUserByName = async username => {
await poolConnect;
try {
const result = await pool.request()
.input("username", TYPES.VarChar, username)
.query(`SELECT
*
FROM
person
WHERE
username = #username;`);
return {
result: result.recordset,
err: null
};
} catch (err) {
return {
result: null,
err
};
}
};
console.log(await getUserByName("Timur"));
})();
In short, first read this.
You probably smiled when saw that the PR was created just 2 months before your questions and still not reflected in here.
Basically, instead of:
const pool = new sql.ConnectionPool(config).connect();
you do this:
const pool = new sql.ConnectionPool(config);
const poolConnection = pool.connect();
//later, when you need the connection you make the Promise resolve
await poolConnection;

TypeError: contract.test is not a function tronweb nodejs

I am trying to access Tron smart contract which is deployed on the Shasta test network using Tron-Web. I am using node-casiko server Following is my code:
const TronWeb = require('tronweb')
// This provider is optional, you can just use a url for the nodes instead
const HttpProvider = TronWeb.providers.HttpProvider;
const fullNode = 'https://api.shasta.trongrid.io';
const solidityNode = 'https://api.shasta.trongrid.io';
const eventServer = 'https://api.shasta.trongrid.io';
const privateKey = 'my test account private key';
const tronWeb = new TronWeb(
fullNode,
solidityNode,
eventServer,
privateKey
);
module.exports = {
tmp: async function (req, res, next){
try{
var contract = await tronWeb.trx.getContract("TS71i14jzLawbtu4qPDKEsFERSp6CQb93948");
//res.send(contract)
var result = await contract.test().call();
//res.send(result);
}
catch(err){
console.error(err)
}
}
}
When I execute this js file using node having version v10.15.3. I am getting Error as:
TypeError: contract.test is not a function
at tmp (/home/administrator/node-Casiko/models/tronContract.js:25:32)
at process._tickCallback (internal/process/next_tick.js:68:7)
If I print the contract variable it is printing all information about the contract, but it is not calling the contract methods. Can somebody help me with this problem?
Well, I managed to find an answer for self-question. Just change the code as below. It works!!
module.exports = {
tmp: async function (req, res, next){
try{
var contract = await tronWeb.contract()
.at("TS71i14jzLawbtu4qPDKEsFERSp6CQb93948")
var result = await contract.test().call();
}
catch(err){
console.error(err)
}
}

Resources