Handling subscriptions to missing topics
A client can handle subscription requests for topics that do not exist and can act on those notifications, for example, by creating a topic on demand that matches the request.
Required permissions:
,The client can register itself as a handler for missing topics for any branch of the topic tree. The client is notified of attempts to subscribe to topics that are subordinate to that topic and that do not exist. This enables the client to create the topics and notify Diffusion™ Cloud that the client operation subscribe can proceed.
The missing topic handler is removed when the registering session is closed. If the registering session loses connection, it goes into DISCONNECTED state. When in DISCONNECTED state the handler remains active but cannot pass on the notifications to the client. In this case, cancel or proceed callbacks for these notifications might not function as expected because of timeouts. If the client then closes, these notifications are discarded.
To ensure that missing topic notifications are always received by your solution, you can use multiple clients to register missing topic handlers. Ensure that if any of these clients lose connection they go straight to CLOSED state by setting the reconnection timeout to zero. When the client loses connect it closes straight away, the handler is registered is removed, and further missing topic notifications are routed to a handler registered by another client.
Registering a missing topic notification handler
Register a handler against a branch of the topic tree:
session.topics.addMissingTopicHandler("topic_branch", { // Implement handling code });
-(void)registerAsMissingTopicHandlerForSession:(PTDiffusionSession *const)session { [session.topicControl addMissingTopicHandler:self forTopicPath:@"topic_branch" completionHandler:^(PTDiffusionTopicTreeRegistration *const registration, NSError *const error) { if (registration) { NSLog(@"Registered as missing topic handler."); } else { NSLog(@"Failed to register as missing topic handler. Error: %@", error); } }]; }
TopicControl topicControl = session.feature(TopicControl.class); topicControl.addMissingTopicHandler("topic_branch", new MissingTopicNotificationHandler());
ITopicControl topicControl = session.TopicControl; var missingTopicHandler = new MissingTopicHandler(); topicControl.AddMissingTopicHandler( topic_branch, missingTopicHandler );
MISSING_TOPIC_PARAMS_T handler = { .on_missing_topic = on_missing_topic, .topic_path = topic_branch, .context = NULL }; missing_topic_register_handler(session, handler);
Implementing a missing topic handler
The sample registration code shows default or no-op missing topic handlers being registered. To take the required action when a missing topic notification is received, implement a missing topic handler:
session.topics.addMissingTopicHandler("topic_branch", { onRegister : function(path, close) { console.log("Registered missing topic handler on path: " + path); }, onClose : function(path) { console.log("Missing topic handler on path '" + path + "' has been closed"); }, onError : function(path, error) { console.log("Error on missing topic handler"); }, onMissingTopic : function(notification) { console.log("Received missing topic notification with selector: " + notification.selector); // Action to take in response to the notification, for example, creating a topic. // If the action is successful, you can indicate that by calling proceed notification.proceed(); } });
@implementation MissingTopicHandlerExample (PTDiffusionMissingTopicHandler) -(void)diffusionTopicTreeRegistration:(PTDiffusionTopicTreeRegistration *const)registration hadMissingTopicNotification:(PTDiffusionMissingTopicNotification *const)notification { NSString *const expression = notification.topicSelectorExpression; NSLog(@"Received Missing Topic Notification: %@", expression); // Action to take in response to the notification, for example, creating a topic. // If the action is successful, you can indicate that by calling proceed [notification proceed]; } @end
private final class MissingTopicNotificationHandler implements MissingTopicHandler { /** * @param topicPath * - the path that the handler is active for * @param registeredHandler * - allows the handler to be closed */ @Override public void onActive(String topicPath, RegisteredHandler registeredHandler) { } /** * @param topicPath * - the branch of the topic tree for which the handler was * registered */ @Override public void onClose(String topicPath) { } /** * @param notification * - the missing topic details */ @Override public void onMissingTopic(MissingTopicNotification notification) { // Action to take in response to the notification, for example, creating a topic. // If the action is successful, you can indicate that by calling proceed notification.proceed(); } }
private class MissingTopicHandler : IMissingTopicHandler { private readonly TaskCompletionSource<IRegisteredHandler> onActive = new TaskCompletionSource<IRegisteredHandler>(); private readonly TaskCompletionSource<IMissingTopicNotification> onMissingTopic = new TaskCompletionSource<IMissingTopicNotification>(); private readonly TaskCompletionSource<bool> onClose = new TaskCompletionSource<bool>(); public Task<IRegisteredHandler> OnActiveCalled { get { return onActive.Task; } } public Task<IMissingTopicNotification> OnMissingTopicCalled { get { return onMissingTopic.Task; } } public Task OnCloseCalled { get { return onClose.Task; } } void IMissingTopicHandler.OnMissingTopic( IMissingTopicNotification notification ) { onMissingTopic.SetResult( notification ); } void ITopicTreeHandler.OnActive( string topicPath, IRegisteredHandler registeredHandler ) { onActive.SetResult( registeredHandler ); } void ITopicTreeHandler.OnClose( string topicPath ) { onClose.TrySetResult( false ); } } }
static int on_missing_topic(SESSION_T *session, const SVC_MISSING_TOPIC_REQUEST_T *request, void *context) { printf("Missing topic: %s\n", request->topic_selector); // Action to take in response to the notification, for example, creating a topic. // If the action is successful, you can indicate that by calling proceed missing_topic_proceed(session, (SVC_MISSING_TOPIC_REQUEST_T *) request); return HANDLER_SUCCESS; }
This page last modified: 2020/06/25