find publisher id when subscriber subscribe to topic in mqtt - node.js

I am using mqtt in my nodejs backed application where there is communication with iot devices and where i am able to publish and subscribe to different topic.every thing is working well i can publish and subscribe to different topic.
I am able to send client id or the publisher id who publish topic in message part which is a repeated task for every publisher.
Is there any way we can know who is publisher while subscribing to topic.
my mqtt client code at nodejs is
var mqtt = require('mqtt')
var url = "http://127.0.0.1:1883";
var client = mqtt.connect(url);
client.on('connect', () => {
console.log('Mqtt client connected to broker');
client.subscribe('status/open');
client.subscribe('status/close');
client.subscribe('sendMsg');
})
client.on('message', (topic, message) => {
console.log('new topic received at controller', topic);
console.log('new messge received at controller', message.toString());
///is there any way to determine who is publishere here
});

No.
This goes against one of the core principals of pub/sub messaging, which is that a publisher shouldn't care who is subscribed to a given topic and a subscriber shouldn't care where the data is coming from, it just subscribes to a topic.
If you want to make it clear you have 2 options.
Use a topic structure that encodes the publisher in the topic and the subscriber uses wildcard topics to receive data from all publishers.
Encode the publisher information into the message payload.

Related

How do messages sent to an Azure Service Bus Topic know which subscription to go to?

I want to implement Azure Service Bus Topic/Subscription. Something like this
I'm looking at the Python implementation in the Azure Docs. What I don't understand, is when the message is sent, how does it know which subscription to go to?
def send_single_message(sender):
# create a Service Bus message
message = ServiceBusMessage("Single Message")
# send the message to the topic
sender.send_messages(message)
print("Sent a single message")
# create a Service Bus client using the connection string
servicebus_client = ServiceBusClient.from_connection_string(conn_str=CONNECTION_STR, logging_enable=True)
with servicebus_client:
# get a Topic Sender object to send messages to the topic
sender = servicebus_client.get_topic_sender(topic_name=TOPIC_NAME)
with sender:
# send one message
send_single_message(sender)
print("Done sending messages")
print("-----------------------")
What I don't understand, is when the message is sent, how does it know
which subscription to go to?
This is accomplished through topic filters. Each message that gets sent to a Topic is "kind of broadcasted" (for the lack of better term) to every Subscription and the Subscription only accepts a message when that message matches one of the filter rules specified for that Subscription.
You can learn more about it here: https://learn.microsoft.com/en-us/azure/service-bus-messaging/topic-filters.

Send SNS notification to all Users that subscribed the topic from Lambda

I have created an E-Commerce IOS app with backend in nodejs (AWS Lambda). When a user signedIn/LoggedIn, the app subscribes a SNS Topic which I have created to send notifications and stores the push token and device ARN in DB.
Now I want to send push notification to all users who have subscribed that SNS Topic, when we added a new item to the store.
Currently, to send notification I am fetching all users from DB and loop through the users to get their push token and send notification to users one by one, which is very costly process, and the API took too much time.
Now I want to do is to hit the SNS topic from Lambda and pass the body of notification to that topic and that SNS topic will send notification to all users who have subscribed the Topic.
I have searched it but can't find any solution.
The code I have done to send notification is
await Promise.all(targetArns.map(async (item, index) => {
const publishNotificationParams = {
"TargetArn": item,
"Message": JSON.stringify({
"default": JSON.stringify({
"category" : title,
"alert" : {
"title" : title,
"body" : 'New product is launced',
"data" : product
},
"badge" : 1,
"sound" : "chime.aiff"
}),
"APNS_SANDBOX": JSON.stringify(params),
"APNS": JSON.stringify(params)
}),
"MessageStructure": "json"
};
var publishTextPromise = sns.publish(publishNotificationParams).promise();
publishTextPromise.then(
function(data) {
console.log(`Message ${publishNotificationParams.Message} sent to the topic ${publishNotificationParams.TargetArn}`);
}).catch(
function(err) {
console.error(err, err.stack);
});
}));
But for this I have to fetch every user from DB get their endpoint ARN and then send notification by iteration.
I want to call SNS topic pass the body of notification and SNS will send notification to every user that has subscribed that SNS topic.
I am doing this because I want to save the cost to fetch every users from DB and then send notification
This is how you could achieve that flow. I think you already have some parts of this implemented.
Create a topic that will be used to fan out the notification to all of your users: https://docs.aws.amazon.com/sns/latest/api/API_CreateTopic.html
Create platform application(s) for the different platforms your app is used on: https://docs.aws.amazon.com/sns/latest/api/API_CreatePlatformApplication.html
When a user signs up for your app, create a platform endpoint for the application corresponding to the user's platform: https://docs.aws.amazon.com/sns/latest/api/API_CreatePlatformEndpoint.html
3.1. If you want to be able to target this user directly, also store this ARN somewhere for direct publishes (as you are doing now).
Now also create a subscription for the topic created in step 1 to the endpoint ARN: https://docs.aws.amazon.com/sns/latest/api/API_Subscribe.html
Publish to the topic created during step 1: https://docs.aws.amazon.com/sns/latest/api/API_Publish.html
SNS will automatically fan out the message to all subscribers (all of your users), so each of them will receive a notification without you iterating over each user.

Google Cloud Platform pub/sub - messages aren't being being delivered to subscriber

I am setting up push notifications for gmail based on the guide provided by google (https://developers.google.com/gmail/api/guides/push). I want to have my node app register a client with .watch(), and then receive emails at a specified endpoint, as described in the documentation.
I have created the pub/sub topic, added gmail as a publisher, added a subscriber, and called watch() in my node app. watch() returns the appropriate { historyId: xxxx, expiration: yyyy } object which, according to google's documentation, means the call succeeded.
handler for receiving email notification on backend:
export const receiveGmailEmail: RequestHandler = async (req, res) => {
log('Received update from google!');
log(JSON.stringify(req.body, null, 2));
return res.status(200);
}
Registering:
const watchRes = await gmailClient.watch();
log('====> Watch Response <=====');
log(JSON.stringify(watchRes, null, 2));
Server log that shows it is registering properly:
====> Watch Response <=====
{
"historyId": "6560",
"expiration": "1562025255689"
}
I never receive messages at the receive endpoint on my node app. According to the server logs, I never actually receive any request when a message is published. The problem appears to be that my messages are undelivered. I have confirmed through the Stackdriver monitor that the pub/sub topic is publishing messages when I send an email to the email address, but if I view the details of the subscription in Stackdriver, it shows an increasing number of undelivered messages.
Any thoughts on why messages in a subscription are sitting around undelivered?
It turns out this wasn't a Google pub/sub issue. Amazon Cloudfront blocks POST requests by default, so I had to edit the caching behavior to enable POST requests. https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/distribution-web-values-specify.html#DownloadDistValuesAllowedHTTPMethods

How to subscribe message from Azure service bus topic subscription to web api?

We have multiple webapi(microservices). To communicate between these micro services we are using Azure service bus Topic\Subscription. How webapi controller can get the message subscription so that api can process the message and insert to database. I don't want to use any azure functions. I want subscribe message in my webapi(micro service directly).
You may create a client for the topic to subscribe the message and set the options to complete after the necessary process is done.
please find the below sample code, where you can read the subscription messages from a topic.
you can use WindowsAzure.ServiceBus -Nuget Package
Sample Code:
using Microsoft.ServiceBus.Messaging;
using Microsoft.ServiceBus;
var con = "your connection string for the topic";
var topic = "your topic name";
var subclient = SubscriptionClient.CreateFromConnectionString(con, topic, "yourSubscriptionName");
OnMessageOptions options = new OnMessageOptions();
options.AutoComplete = false;
client.OnMessage(message =>
{
Console.WriteLine("Message:" + message.GetBody<string>());
message.Complete();
}, options);
you may put it in separate method and use as needful.
To poll you may create a webjob, or you can place the code which triggers the web api, so that it will poll the messages at the same time.

Why use a QueueClient vs MessageFactory?

In Azure Service Bus, you can send a brokered message using QueueClient and MessageFactory. I would like to know why would you want to use one over the other.
Azure Service Bus provides different way to send/receive messages.
You can use the QueueClient to send and receive message to/from a queue.
You can use the TopicClient to send message to a topic
And you can use the SubscriptionClient to receive message from a subscription.
Using MessageSender and MessageReceiver, you create sender and receiver that are entity type invariant:
var factory = MessagingFactory.CreateFromConnectionString("MyConnectionString");
A MessageSender can send messages to both topic or queue:
var sender = factory.CreateMessageSender("Queue ou topic path");
A MessageReceiver ca receive messages from both queue and subscription:
var receiver = factory.CreateMessageReceiver("Queue ou subscription path");
Theses abstractions can give you more flexibility if you need to switch from a queue to a topic or vice versa because you just need to change the path of the service bus entity (This could be in your configuration file) so no code change needed. Using QueueClient, TopicClient, SubscriptionClient, you'll have to change your code if you want to move from a queue to a topic.
So my advice is to always use a MessageReceiver/MessageSender when you have to send/receive message from/to a an Azure ServiceBus queue topic/subscription.
NOTE: This does not apply for Eventhub which has a different implementation.

Resources