Learning WebSub (Part 2) : Building a WebSub `hub` using Ballerina
In my previous article I did a brief introduction to WebSub protocol. In this article we are going to implement a WebSub hub using Ballerina Websubhub standard library. If you need some heads-up on Ballerina language, please go through this article.
The use case we are going to implement is a weather-notification hub. News stations can subscribe to the hub to receive hourly weather updates for a particular location. In this example we will primarily focus on the relationship between the hub and the subscriber.
Following areas will be covered during this implementation:
- Basic WebSub hub implementation using Ballerian language.
- Implement a WebSub subscriber using Ballerina language.
- Integrating a 3rd party API to retrieve weather reports for a location.
- Connecting Apache Kafka message broker as a persistence layer for the WebSub hub implementation.
In this article we will cover first two points and the rest will be covered during the upcoming blog posts.
WebSub Hub Implementation
Ballerina Websubhub standard library provides a thin-API layer to implement WebSub compliant hubs. If we go through the API specification of Websubhub standard library we can easily understand the APIs which needs to be implemented.
In Ballerina language, WebSub hub is designed in the form of listener and a service.
websubhub:Listener
: A listener end-point to whichwebsubhub:Service
could be attached.websubhub:Service
: An API service, which receives WebSub events.
The websubhub:Listener
serves as a wrapper for an HTTP listener, which makes an HTTP endpoint available for subscribers and publishers to send requests to. Each time a request is made to the websubhub:Listener
endpoint, the corresponding API within the websubhub:Service
that is attached to the websubhub:Listener
will be triggered.
Here’s an example of what the basic hub implementation will look like:
Above code will start an HTTP endpoint on port 9000
and attach the websubhub:Service
to /hub
service-path. Publishers and subscribers can send request to hub using http://localhost:9000/hub
URL.
In our example hub implementation, subscribers are subscribed for weather alerts for a particular location. A subscriber can send the location name as the hub.topic
parameter in the subscription request.
Hub should maintain two states.
- Locations to which weather-notifications should be generated.
- News receivers who are subscribed for weather alerts.
Available locations can be managed as a string[]
and the News receivers will be managed as a map<websubhub:VerifiedSubscription>
. News receivers will be assigned an Id which will be derived using hub.topic
and hub.callback
parameters in the subscription request.
With the above constraints our hub implementation will look like this:
Note that in our hub implementation following remote methods has been disabled since they are related to publisher related functionalities.
onRegisterTopic
onDeregisterTopic
onUpdateMessage
To improve the readability of the code we will add following additional utility methods to our implementation.
The hub implementation is able to record the locations and registered news receivers. Now, we want to implement the functionality to periodically send weather alerts to the registered news receivers. In the initial state we will have predefined set of alert templates which would be customized according to location.
Here we have used websubhub:HubClient
to deliver content to the news receivers. A websubhub:HubClient
has a one-to-one mapping to a WebSub subscriber; in this case to a news receiver.
With these changes we can improve the onSubscriptionIntentVerified
remote method in the hub service.
In the implementation I have used several concurrency constructs in Ballerina language. Please refer to this article for more details on Ballerina concurrency.
WebSub Subscriber Implementation
In our example WebSub subscriber represents a news receiver. We can implement a simple subscriber using the following code.
One important thing to be noticed here is that subscriber is another service which exposes an HTTP endpoint.
In websub:SubscriberServiceConfig
annotation we need to provide the target
parameter (which is a tuple). In the target
parameter, first value represents the hub URL and the second value represents the hub.topic
parameter which should be used in the subscription request.
In this article we have discussed how to implement a basic WebSub hub and a subscriber using Ballerina language. In the next article, we will be covering how to integrate 3rd party APIs to retrieve weather notifications.