ISubscription to be passed in CreateFlow method for ITopicEndpoint - solace

I am creating a Flow instance for a ITopicEndpoint, the documentation says that ISubscription should be passed to the createFlow method only if endpoint is of type ISubscriberEndpoint.
From the documentation
subscription Type:
SolaceSystems.Solclient.Messaging.ISubscription Only valid if endpoint
is of type ISubscriberEndpoint.
I am creating a Flow for a ITopicEndpoint so why am I getting the below error. What should i pass for ISubscription?
System.ArgumentException: 'subscription must be non-null when endpoint is of type ITopicEndpoint'
topic = ContextFactory.Instance.CreateDurableTopicEndpointEx(topicName);
flow = session.CreateFlow(flowProps, topic, null, HandleFlowMessageEvent, HandleFlowEvent);

For a durable topic endpoint, if you have multiple subscribers then each would have to register with a unique subscription name so that the broker can maintain a durable connection with the specific subscriber. Even if the subscriber is down for a while and reconnects, it will not loose out on messages in the interim. The broker will push the messages to the subscriber.
You can create a subscriber via the Solace Admin client or via code.
Solace Admin -> Select the VPN -> Choose Endpoint tab -> select Durable Topic Endpoint -> click the + sign to create a subscriber -> ensure that consume is chosen for 'All other Permissions'

Related

MQTT shared subscription

With a MQTT shared subscription, the message on the subscirbed topic would only be sent to one of the subscribing clients. Then, how the other clients of the group receive the message as they also subscribe to the same topic?
With a MQTT shared subscription, the message on the subscribed topic would only be sent to one of the subscribing clients.
Correct. With a normal (non‑shared) subscription the messages are sent to ALL subscribers; with shared subscriptions they are sent to ONE subscriber.
Prior to the introduction of shared subscriptions it was difficult to handle situations where you want multiple servers (for fault tolerance, load balancing etc) but only want to process each message once. Shared subscriptions provide a simple way of accomplishing this.
Then, how the other clients of the group receive the message as they also subscribe to the same topic?
If they are subscribing to the same shared subscription (with the same ShareName) then only one will receive the message; this is by design. If you want them all to receive the message then don't use a shared subscription. Alternatively you can establish multiple subscriptions (so all subscribers receive the message but only one processes it - but note the "could") as per the spec:
If a Client has a Shared Subscription and a Non‑shared Subscription and a message matches both of them, the Client will receive a copy of the message by virtue of it having the Non‑shared Subscription. A second copy of the message will be delivered to one of the subscribers to the Shared Subscription, and this could result in a second copy being sent to this Client.
There is an interesting bug in Java Paho (1.2.5) client that prevents working with shared topics that contains wildcards (#, +) https://github.com/eclipse/paho.mqtt.java/issues/827
Long story short, this will not work:
mqttClient.subscribe("$shared/group/some_topic/#", 1, (topic, message) -> System.out.println(topic));
instead it's required to use callbacks:
mqttClient.subscribe("$shared/group/some_topic/#", 1);
mqttClient.setCallback(new MqttCallback() {
#Override
public void connectionLost(final Throwable cause) {
}
#Override
public void messageArrived(final String topic, final MqttMessage message) throws Exception {
System.out.println(topic);
}
#Override
public void deliveryComplete(final IMqttDeliveryToken token) {
}
});

Solace - How to create ISubscription instance to be used by Session.CreateFlow method

I am trying to create a subscriber for my durable topic endpoint in solace via .NET APIs.
I have the below method where in I am trying to create a flow for my durable topic endpoint. I don't understand what is the need for ISubscription instance in the Session.CreateFlow method. (https://docs.solace.com/API-Developer-Online-Ref-Documentation/net/html/a548a98a-9134-c167-2517-192a26ceed77.htm)
How do I create an instance of ISubscription and what should it be?
public void Start()
{
//Create a instance of a durable topic endpoint
topic = ContextFactory.Instance.CreateDurableTopicEndpointEx(topicName);
FlowProperties flowProps = new FlowProperties();
flowProps.FlowStartState = false;
if (selector != null)
{
flowProps.Selector = selector;
}
flowProps.AckMode = ackMode == AckMode.ClientAcknowledge ? MessageAckMode.ClientAck : MessageAckMode.AutoAck;
if (windowSize.HasValue)
{
flowProps.WindowSize = windowSize.Value;
}
flow = session.CreateFlow(flowProps, topic, null, HandleFlowMessageEvent, HandleFlowEvent);
flow.Start();
}
I am currently passing it as null and I get the error
subscription must be non-null when endpoint is of type ITopicEndpoint
Secondly, I have a message handler for my flow event and session event, so when a message comes through which handler would it invoke. I would expect that I handle the message in the FlowMessageHandler as I am connecting to a durable topic endpoint. Please can someone shed more light on this?
//session message event handler
session = context.CreateSession(sessionProperties, HandleSessionMessageEvent, HandleSessionEvent);
//Flow message event handler
flow = session.CreateFlow(flowProps, topic, null, HandleFlowMessageEvent, HandleFlowEvent);
For a durable topic endpoint, if you have multiple subscribers then each would have to register with a unique subscription name (you can give any name as you like) so that the broker can maintain a durable connection with the specific subscriber. Even if the subscriber is down for a while and reconnects, it will not lose out on messages in the interim. The broker will push the messages to the subscriber. You can create a subscriber via the Solace Admin client or via code. Solace Admin -> Select the VPN -> Choose Endpoint tab -> select Durable Topic Endpoint -> click the + sign to create a subscriber -> ensure that consume is chosen for 'All other Permissions'.
The messages are sent to the session handler first and then to the flow handler. So you can access the messages from both the handlers.

solace message Id not viewed in solAdmin

I have published a message in the solace interface and got the messageId generated for that.
From SolAdmin, When I inspect the queue, I can able to see one new messages received, but the message id which generated is not same.
TextMessage txtMsg = jmsSession.createTextMessage();
messageID = txtMsg.getJMSMessageID();
The above messageID generated the output as
ID:2eaaf46d-b9ff-4aeb-a385-fbc2e6cced0a:1:1:1-1
But in SolAdmin, the message shows as 5985824677
The "Message ID" that is shown in the endpoints tab of SolAdmin is internal to the Solace Message Broker and is not equivalent to the "JMS Message ID".
You can use it for operations such as deleting some messages via the CLI or SEMP.
For example:
solace(admin/message-spool)# delete-messages queue my_sample_queue message 123456789 to 123456790
There's no way to display the JMS Message ID in SolAdmin.
Instead, you will need to make use of a queue browser to browse messages in the queue.
This can be a custom application that you write, sdkperf (use the -qb and -md flags), or a third party graphical JMS queue browser such as HermesJMS.

How to get solace queue statistics from Solclient API? c#

I am looking to retrieve some Solace queue stats e.g. the current messages spooled count out of the maximum limit for us to set a threshold to stop publishing more messages to the queue.
Also, to subscribe to vpn events to track message discard rates.
By the time we receive errors e.g. MaxMsgUsageExceeded/SpoolOverQuota, it will be too late.
I can't seem to find any of these on SolaceSystems.Solclient.Messaging API
https://docs.solace.com/API-Developer-Online-Ref-Documentation/net/html/7f10bcf6-19f4-beff-0768-ced843e35168.htm
Would be great if someone could help
(using C# for this)
To poll for Solace queue stats from your C# application, you could use legacy SEMP over the message bus to make a SEMP request for the details that you want. Semp (Solace Element Management Protocol) is a request/reply protocol that uses an XML schema to identify all managed objects available in a message broker. Applications can use SEMP to manage and monitor a message broker.
To allow for legacy SEMP to be used over the message bus, as opposed to the management interface, it first needs to be enabled on the Solace PubSub+ message broker at the VPN level.
To publish a SEMP request with the Solace .Net Messaging API, perform the following steps:
Create a Session.
Create the message topic. “#SEMP//SHOW”
ITopic topic = ContextFactory.Instance.CreateTopic( “#SEMP/<router name>/SHOW”);
Create a request message and set its Destination to the topic in Step 2:
IMessage requestMsg = ContextFactory.Instance.CreateMessage();
requestMsg.Destination = topic;
Set the SEMP request string as the binary attachment.
string SOLTR_VERSION = "8_4_0" //change to the message-broker's version
string SEMP_SHOW_QUEUE = "<rpc semp-version=\"soltr/" + SOLTR_VERSION +
"<show><queue><name>queueName</name><detail></detail></queue></show></rpc>";
requestMsg.BinaryAttachment = Encoding.UTF8.GetBytes(SEMP_SHOW_QUEUE);
Call the SendRequest(…) method on Session.
IMessage replyMsg;
ReturnCode rc = session.SendRequest(requestMsg, out replyMsg, timeout);
The SEMP response is returned in replyMsg.
Obtain the binary attachment data from the reply message:
replyMsg.BinaryAttachment
The binary attachment contains the SEMP reply for the command topic in the publish request.
The Solace PubSub+ message broker does raise an event when an egress message is discarded. However, it is only sent out approximately once every 60 seconds for the specified client so it is not possible to get these exact rates.
It is possible for your .NET application to subscribe to VPN-level events over the message-bus. To do this, you must first enable the Solace PubSub+ message broker to publish the events. You can then subscribe to the special topic and receive the events as messages.
The topic to subscribe to is:
#LOG/<level>/VPN/<routerName>/<eventName>/<vpnName>
The different levels can use the * wildcard. For example, if you wish to subscribe to all VPN events of all levels for the VPN apple on router QA-NY1, the topic string would be:
#LOG/*/VPN/QA-NY1/*/apple
SEMP (starting in v2) is a RESTful API for configuring, monitoring, and administering a Solace PubSub+ broker.
1-The swapper page link is SEMP V2 API
2-The Swagger metadata definitions URL is located # http://{solace-sever-url}/SEMP/v2/config/spec
3- From Visual studio, add REST API Client
4-In the configuration dialog pass swagger metadata URL (defined at step 2), for code purpose I choose SolaceSemp as input value parameter for client namespace input.
4 Once you click ok, VS will create the client along with the models under SolaceSemp namespace
5 Start using the client as per following
using SolaceSemp;
using Microsoft.Rest;
var credentials = new BasicAuthenticationCredentials();
credentials.UserName = "place user name";
credentials.Password = "place password";
using (var client = new SolaceSempClient(credentials))
{
var model = client.GetAboutApi();
}

How can a Slack bot detect a direct message vs a message in a channel?

TL;DR: Via the Slack APIs, how can I differentiate between a message in a channel vs a direct message?
I have a working Slack bot using the RTM API, let's call it Edi. And it works great as long as all commands start with "#edi"; e.g. "#edi help". It currently responses to any channel it's a member of and direct messages. However, I'd like to update the bot so that when it's a direct message, there won't be a need to start a command with "#edi"; e.g. "#edi help" in a channel, but "help" in a direct message. I don't see anything specific to differentiate between the two, but I did try using the channel.info endpoint and counting the number of people in "members"; however, this method only works on public channel. For private channels and direct messages, the endpoint returns an "channel_not_found" error.
Thanks in advance.
I talked to James at Slack and he gave me a simply way to determine if a message is a DM or not; if a channel ID begins with a:
C, it's a public channel
D, it's a DM with the user
G, it's either a private channel or multi-person DM
However, these values aren't set in stone and could change at some point, or be added to.
So if that syntax goes away, another way to detect a DM to use both channels.info and groups.info. If they both return “false” for the “ok” field, then you know it’s a DM.
Note:
channels.info is for public channels only
groups.info is for private channels and multi-person DMs only
Bonus info:
Once you detect a that a message is a DM, use either the user ID or channel ID and search for it in the results of im.list; if you find it, then you’ll know it’s a DM to the bot.
“id” from im.list is the channel ID
“user” from im.list is the user ID from the person DM’ing with the bot
You don’t pass in the bot’s user ID, because it’s extracted from the token
FYI as of July 2017, for "message.im" events (via your app's Event Subscriptions), the event payload seems to now return additional fields to detect if the message is coming from your own bot (pasted in here from my logs):
INFO[0012] got Slack message: (bot.SlackMessage) {
SlackEvent: (bot.SlackEvent) {
Type: (string) (len=7) "message",
EventTs: (string) (len=17) "1501076832.063834",
User: (string) ""
},
SubType: (string) (len=11) "bot_message",
Channel: (string) (len=9) "D6CJWD132",
Text: (string) (len=20) "this is my bot reply",
Username: (string) (len=15) "Myapp Local",
BotID: (string) (len=9) "B6DAZKTGG",
Ts: (string) (len=17) "1501076832.063834"
}
Slack have added Conversations API some time ago. You should use it to differentiate between PM/channel instead of relying on prefix.
From Conversations API documentation:
Each channel has a unique-to-the-team ID that begins with a single letter prefix, either C, G, or D. When a channel is shared across teams (see Developing for Shared Channels), the prefix of the channel ID may be changed, e.g. a private channel with ID G0987654321 may become ID C0987654321.
This is one reason you should use the conversations methods instead of the previous API methods! You cannot rely on a private shared channel's unique ID remaining constant during its entire lifetime.
Get conversation info using conversations.info method and check is_im flag. is_im == true means that the conversation is a direct message between two distinguished individuals or a user and a bot.
The info function is also available for private channels with the Slack API method groups.info. This works also for direct message channels with multiple participants, since they are a special form of private channels.
You can use groups.list to get the IDs of all private channels incl. direct message channels with multiple participants.
Note that groups.list will only return private channels, that the user or bot that the access token belongs to has been invited to.

Resources