Notification 2.0 Microservice - Best Practices?

Hey Cumulocity-Community!

I’m currently working on a microservice (python) which purpose it is to listen to specific events using the notification 2.0 API and trigger a second (not easily modifiable) microservices REST-POST-Endpoint on each event. (Firstly, do i even need this trigger-service or is this possible with something like a smart-rule? Secondly…)

Are there any best practices to create and maintain the subscription? Many guides tell me to be careful not to create&keep too many inactive subscriptions. Should the service be able to create subscriptions & tokens by itself (having ROLE_NOTIFICATION_2_ADMIN) and persisting them as tenant options for after a reboot? Alternatively should the subscription be preconfigured manually using the API with a predefined name, which is hardcoded in the service, which then only polls (expiring) tokens? Does the service need to monitor when to re-issue a token?

Any input is appreciated.

Best regards
Yannick

Hi Yannick,

some thoughts on it…

Firstly, do i even need this trigger-service or is this possible with something like a smart-rule? Secondly…)

Currently you can’t achieve your use case via Smart Rules. However, you could definitely look into Apama. The EPL App examples have a sample on how to invoke Microservices (link to docs).
There are other people with more Apama Knowledge here, they could give you additional pointers on how to achieve your use case via Analytics Builder or EPL App.

Are there any best practices to create and maintain the subscription? Many guides tell me to be careful not to create&keep too many inactive subscriptions.

Notification 2.0 allows you to create subscriptions and register subscribers to such subscriptions. If your subscriber loses connection (e.g. due to bad network or service restarts) & the subscription is configured to be persistent, this subscriber will receive all notifications that it missed on its first successful reconnect. To make this possible, the platform has to buffer all data from a subscription for a certain subscriber. So you really have to to use stable subscription and subscriber names in your service, otherwise a) you’ll lose the functionality to get notifications delivered that happened while your service was offline and b) you’re creating lots of orphaned “data buffers” on platform-side that will never be consumed. If you do not need this buffering, you can configure your subscription to be non-persistent.

Worth a note: When you’re not using a subscription anymore, you should not only delete the subscription (this will stop the platform from sending notifications towards your subscriptions), you should also unsubscribe all subscribers of this subscription. This way the platform knows “this subscriber won’t reconnect” and cleans up it’s potential backlog.

Should the service be able to create subscriptions & tokens by itself (having ROLE_NOTIFICATION_2_ADMIN)

Yes. I would implement it within the Service and not create the subscriptions upfront/manually. This way the Service is more portable. Rather than “blindly” creating the subscription, you may want to implement a logic to check if the subscription of name X is existing, if yes re-use it, if not create it.

For hardcoding the subscription name vs. making it configurable via tenant options: I would either hardcode it or use the “settings” property in cumulocity.json. This way you can deploy the service to other tenants (potentially done by other people) without the hidden-knowledge to create specific tenant options upfront.

For tokens: I wouldn’t see a reason to store them as tenant option, you can simply request a new one on service-restart. Just make sure to use the same subscription/subscriber names in your token requests.

Does the service need to monitor when to re-issue a token?

You can set the expiry time when creating your token. I think yes, your service should make sure to re-issue a new token in case yours expired.

Links

1 Like

To backup Korbinians response: I would also not handle the tokens and store them somewhere. The subscriptions itself are handled by Notification 2.0 so you can retrieve them on startup of your service and just re-create new tokens to connect. There is no need to re-use “old” tokens in my opinion and implement some complex management to handle expiration etc.

The Subscriptions can be also removed not only by the token which has been used to connect but by any other token as long as the subscription name matches.

In your service you just need to take care to use a proper subscription name handling, retrieve existing subscriptions and if existing, re-using them, and when not needed anymore to delete them and unsubscribe your subscriber like Korbinian already mentioned.

Btw. Best Practice is also to use shared subscriptions for multiple devices by using the same subscription name where it is desired. That way you have only one subscription for multiple devices also using just one websocket connection to the server. So don’t include any dynamic data in your subscription name like deviceIDs or names but use mainly meaningful static names for all of them and remember them so they don’t get orphaned :wink:

1 Like

Hey Korbinian and Stefan,

thanks for your input, actually an Apama EPL-App was the much simpler and practical solution, nice idea. No need for handling subscriptions or expirations and its even easier to provide it to partners enabling parameters (e.g. which sensor to monitor) just hardcoded in the monitor, which is easy to edit. Also making use of my long-unused Apama-EPL-knowledge i gathered some years ago! :smiley:

But the hints on Notifications 2.0 are still valuable and will be used later. But i still have questions remaining:

When you’re not using a subscription anymore, you should not only delete the subscription (this will stop the platform from sending notifications towards your subscriptions), you should also unsubscribe all subscribers of this subscription.

Is this doable in an automatied way? Does the platform invoke some “on-destroy”-function when the microservice is unsubscribed? And why aren’t subscribers unsubscribed when a subscription is deleted? Shouldn’t this happen at last if the tokens expire?

Rather than “blindly” creating the subscription, you may want to implement a logic to check if the subscription of name X is existing, if yes re-use it, if not create it.

Shouldn’t the platform handle that, implementing the “create subscription”-Endpoint as an “create or return existing”-Endpoint? If not, are there examples of how this is done, because this seems like more effort than it should be.

You can set the expiry time when creating your token. I think yes, your service should make sure to re-issue a new token in case yours expired.

Does the service somehow get notified about an expiring token? Is the socket closed (enabling logic → onClose(){ reissue_token()}) or is there a final message? Or does the service need to keep track of the time itself to close the socket and reissue and reopen the token and socket?

Microservice SDK for Java - Cumulocity IoT documentation You could delete all subscription if the microservice gets unsubscribed by a tenant.
MicroserviceSubscriptionRemovedEvent You have to use the token to do so as currently the service user is already revoked and does not have access to the tenant.

Shouldn’t the platform handle that, implementing the “create subscription”-Endpoint as an “create or return existing”-Endpoint? If not, are there examples of how this is done, because this seems like more effort than it should be.

If the key matches (name, context, sourceId) I think this is already the case. The effort is not too high. Just query for existing subscriptions before creating new ones.

Does the service somehow get notified about an expiring token? Is the socket closed (enabling logic → onClose(){ reissue_token()}) or is there a final message? Or does the service need to keep track of the time itself to close the socket and reissue and reopen the token and socket?

No, the socket has nothing to do with the token. The token is only used for authentication once. If you lose the connection for some reason just create a new token… the connection will never be closed because the token expired etc.

Does the platform invoke some “on-destroy”-function when the microservice is unsubscribed?

I would be careful about such logic because all you know is the service is being “unsubscribed”, your service cannot know the reason. Is it unsubscribed and never meant to come online again? Is it unsubscribed as the service gets updated to a new version? Is the unsubscribe related to a platform upgrade? Or someone just re-subscribes it for debugging purposes?

I would argue if you do not want your subscription to buffer data once your service is offline, you could just set nonPersistent to true when creating the subscription. This way buffering would be deactivated and the service only consumes events when it’s online.