HiveMQ

Efficient way to collect client IDs of clients subscribed on a topic

I am developing a HiveMQ plugin which makes use of RESTService and HttpListener . Plugin accepts topic or list of topics as a JSON and returns a clientId (or list of clientIds) of client(-s) subscribed to passed topics.
I am a bit confused on how does BlockingSubscriptionStore::getSubscribers works.
For example there are two clients with client IDs: ClientA & ClientB

  • ClientA subscribed on test/sub/topic (QoS 1)
  • ClientB subscribed on test/# (QoS 1)

Whenever I ask my plugin to get me subscribers of test/# only ClientB is returned. Documentation of getSubscribers method states following:

Returns all MQTT client subscriber identifiers for a given topic, this HiveMQ instance and all other nodes in a HiveMQ cluster. MQTT Wildcards are allowed.

With following description I would expect request for test/# to return both ClientA & ClientB which is obviously not the case here.

However whenever I request subscribers of test/sub/topic both ClientA & ClientB client IDs are returned:
111811230-e6723780-88e7-11eb-9c45-2584cd96e5b2
This makes me to think that multi-level wildcard passed to getSubscribers topic is ignored in terms of logic behind it and rather used as a simple string for matching. So my questions would be:

  1. Is this an expected behaviour?
  2. Is there a way to get the list of client IDs of clients subscribed to topic that contains certain string?
    Or some sort if multi-level wildcard for selecting clients subscribed to topic matching certain pattern. Like, for example, passing test/# to getSubscribers would return clients subscribed to test/sub/topic , test/sub/topic1 .
    I really don’t want to proceed with search of matching topics by iterating via the list of all clients because with hundreds of thousands of clients this might end up hitting performance badly.

I am using HiveMQ 3.4.7 in the example repo, behaviour is the same for v3.4.6 (unfortunately I am limited to versions <4).
HiveMQ SPI v. 3.4.4.

You can easily reproduce behaviour above by checking out repo: GitHub - frankyfish/hivemq-sub-plugin-demo: Demo repository for HiveMQ plugin which accepts MQTT topics list and returns client IDs of subscribed MQTT Clients.
There is a Dockerfile that setups everything.

Copied from my issue on GitHub: SubscriptionStore's getSubscribers doesn't return all topics in case passed topic contains multi-level wildcard · Issue #7 · hivemq/hivemq-spi · GitHub
Thanks in advance!

HI @franky.fish,

Welcome to the HiveMQ Community Forum.

As a side note you are using a very outdated, no longer supported version of HiveMQ.
You can find the current HiveMQ Extension SDK here.

To your question:
The getSubscribers method returns subscribers that have a subscription matching the topic string, it does not return all subscriptions that would match to that topic filter on an MQTT level.

In order to get a list like you suggested you need to get the list of all Subscriptions and build some custom logic to iterate through them and see if they match.

In this example for example you could do a “startsWith(test/)” on the topic filter.

Regards,
Florian

Hello @fraschbi ,
First of all thank you for your answer.

Unfortunately my project is limited to versions <4 at least for the nearest future.

In order to get a list like you suggested you need to get the list of all Subscriptions and build some custom logic to iterate through them and see if they match.

Yeah, I know that such a way is possible however it is list of all Subscriptions thing that bothers me here. I might end up loading hundreds of thousands of object in memory if there are a lot of subscriptions. Unfortunately it looks like there is no other way to do it from the plugin.