I have a web site app that generates a simple object with 4 props. It posts to an Azure Serverless Function A. Function A takes the post, and sends it to an Azure PubSub instance running in Azure. I have a second Serverless Function B, which is subscribed to the PubSub. When it gets the original object, it writes it to Cosmos MongoDB. I have a 3rd Serverless Function C which the web site app uses to read the data back from Mongo DB.
I run the web site, Function A, Function C, and of course the PubSub all in Azure.
When I run Function B (the PubSub Listener) inside of Code editor locally, the entire set of apps works perfectly. However when I push Function B up to Azure, Function B is "hearing" the messages from PubSub, but it is failing to write to Mongo. I have included a combined screen shot of the PubSub trace tool, showing a successful session running Function B locally, and under that, is the image of the trace tool showing when I run Function B on Azure. Seems like either [a] I am missing some setting needed to run Fucntion B on Azure, or Function B is allowed to post to Mongo when running locally but nor when running in Azure. For the Function B in Azure I have the CORS setting set to *
Is there an allowed client IP setting somewhere in Cosmos such as MongoDB Atlas has?
here is the Function B code:
module.exports = function(context, req) {
const WebSocket = require('ws');
const { WebPubSubServiceClient } = require('@azure/web-pubsub');
const MongoClient = require('mongodb').MongoClient;
const connect = async () => {
client = await MongoClient.connect('connection string' );
return client;
}
main();
async function main() {
const hub = "kurtpubsub.webpubsub.azure.com";
var connectionString = "Endpoint=https://kurtpubsub.webpubsub.azure.com;AccessKey= key";
let serviceClient = new WebPubSubServiceClient(connectionString, hub);
let token = await serviceClient.getClientAccessToken();
let ws = new WebSocket(token.url);
ws.on('open', () => console.log('connected'));
ws.on('message', data => {
let newRecord = JSON.parse(data);
// got the data, now write to mongo
// have to wait for 2nd promise to get he client object
connect().then( console.log("connected to mongo"))
.then((client) => { writeDB(client, newRecord)});
//console.log(newRecord);
});
}
function writeDB(client, pNewRecord)
{
try {
const database = client.db("restdb");
//context.log("connected to DB successfully");
// Insert a single document
database.collection('restaurants').insertOne(pNewRecord);
//client.close();
} catch (err) {
console.log(err.stack);
client.close(); // Close connection if app is dying
}
}
}
Here is the host.json file:
{
"version": "2.0",
"logging": {
"applicationInsights": {
"samplingSettings": {
"isEnabled": true,
"excludedTypes": "Request"
}
}
},
"extensionBundle": {
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[3.*, 4.0.0)"
}
}
Here is the function.json file:
{
"bindings": [
{
"authLevel": "anonymous",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": [
"get",
"post"
]
},
{
"type": "http",
"direction": "out",
"name": "res"
}
]
}
2
Answers
PramodValavala, answered my problem. "Your function is implemented to start listening when a request is first made. And even once started, the function app would not run forever due to timeouts since there is no active invocation, unless if you are running on a Premium Plan or an App Service Instance.
Instead, you should use the WebPubSub Binding, which lets the functions scale controller to monitor for messages and automatically wake up your function app."
Your function is implemented to start listening when a request is first made. And even once started, the function app would not run forever due to timeouts since there is no active invocation, unless if you are running on a Premium Plan or an App Service Instance.
Instead, you should use the WebPubSub Binding, which lets the functions scale controller to monitor for messages and automatically wake up your function app.
Reposting my answer from here with relevant references.