In this post, we will explain how to make use of notifications in the Live Framework. When you subscribe to a specific resource, the Live Framework provides notifications when changes are made to that resource. This allows you to optimize interactions with the Live Operating Environment (both client and cloud) and only retrieve information when something has changed.

We will use JSON as the wire format for all the examples shown here. All the requests made are authenticated with a delegated auth header or user auth header and are in the context of a particular user.

Step 1

The first thing that the application needs to do is to create a notification queue to receive notifications from subscribed resources. A notification queue is in the context of a user and is bounded by a user’s mesh. The queue can only receive notifications for resources that are part of this user’s mesh. The following HTTP request creates the notification queue.

 

Request

HTTP POST	
https://user-ctp.windows.net/V0.1/Mesh/NotificationQueues

{
}

Response

{
 "BaseUri" : "https:\/\/user-ctp.windows.net\/V0.1\/",
 "Categories" : [
     {
         "Label" : "NotificationQueue",
         "Name" : "NotificationQueue",
         "Scheme" : "http:\/\/user.windows.net\/Resource"
     }
 ],
 "Id" : "uuid:3084e6c2-56ac-4563-b67c-af7a7fc019e7;id=18130",
 "LastUpdatedTime" : "\/Date(1237276680000)\/",
 "SelfLink" : "Mesh\/NotificationQueues\/[ID]",
 "Title" : "NotificationQueueResource",
 "ExpirationDuration" : 300,
 "NotificationsLink" : "Mesh\/NotificationQueues\/[ID]\/Notifications",
 "Watermark" : ""
}

The following properties from the preceding code examples are worth noting:

  • ExpirationDuration: This defaults to 300 seconds. If the client does not poll this notification queue (by executing an HTTP PUT request on the queue itself or HTTP GET on the Notifications feed associated with it) one time every 300 seconds, this queue is deleted. This is because notification queues are short-lived and are not persisted in the database.
  • NotificationsLink: This is the link to the feed that will contain notifications for all the subscribed resources. It should be cached by the client application.
  • Watermark: This is an opaque identifier that is used to acknowledge receipt of notifications. More on this property later.

It is important to note that the NotificationQueues feed only supports HTTP POST operations. Each entry within this feed (each NotificationQueue) only supports HTTP PUT operations.

Step 2

When the application has a notification queue in place, it now needs to create a subscription for a resource. For this, the application needs to execute an HTTP POST request on the Subscriptions feed for the resource from the notification queue that the application created.

The following code sample creates a subscription for a mesh object::

Request

HTTP POST	
https://user-ctp.windows.net/V0.1/Mesh/MeshObjects/[ID]/Subscriptions

{
"NotificationQueueLink" : "Mesh/NotificationQueues/[ID]"
}

Response

{
    "BaseUri" : "https:\/\/user-ctp.windows.net\/V0.1\/",
    "Categories" : [
        {
            "Label" : "Subscription",
            "Name" : "Subscription",
            "Scheme" : "http:\/\/user.windows.net\/Resource"
        }
    ],
    "Id" : "urn:uuid:33abe770-0d77-4aaa-a07d-7242b04958c5",
    "LastUpdatedTime" : "\/Date(1237276859000)\/",
    "SelfLink" : "Mesh\/MeshObjects\/[ID]\/Subscriptions\/[ID]",
    "Title" : "SubscriptionResource",
    "ETag" : "171184531853220",
    "NotificationQueueLink" : "Mesh\/NotificationQueues\/[ID]",
    "Timeout" : 3080
}

The following properties from the preceding code examples are of interest:–

  • Etag: It is possible that the mesh object (the subscribed resource in this example) is updated between the time period when the last GET was executed and the creation of this subscription. The client can make use of this Etag value to check if such an update has happened (for which it would not have received any notification) and to get the latest changes.
  • NotificationQueueLink: This is the link to the notification queue where notifications for this resource will be available. This value is the same as what the client application specified in the request body when creating a subscription.
  • Timeout: This is the value in seconds after which this subscription will be lost. In order to keep subscribing to this resource, the client application will have to execute a PUT request on this subscription (with the data in the response as the request body) before that time period. This value is not static, is determined by the server, and is read-only. This is so because notifications and subscriptions are not persisted in the database and the server needs to reclaim unused resources.

When polling for notifications, the client application should do an HTTP GET request on the Notifications feed under NotificationQueue (provided by the subscription resource as NotificationQueueLink). The Subscriptions feed only supports an HTTP POST operation and each subscription (entry within the subscriptions feed) only supports an HTTP PUT operation.

Step 3

Executing HTTP GET requests on notifications for the notification queue results in the following code example. You can see that this is an empty feed with no entries because no change has been made to the subscribed resource (i.e., the mesh object in this case).

Request

HTTP GET	
https://user-ctp.windows.net/V0.1/Mesh
/NotificationQueues/[ID]/Notifications

Response

{
    "BaseUri" : "https:\/\/user-ctp.windows.net\/V0.1\/",
    "Entries" : [
        
    ],
    "SelfLink" : "Mesh\/NotificationQueues\/[ID]\/Notifications",
    "Title" : "Notifications"
}

Step 4

In order to demonstrate how notifications are generated, we will make changes to the mesh object by updating its summary property. This change should generate a notification under notifications for the notification queue that is associated with this mesh object.

Request

HTTP PUT	
https://user-ctp.windows.net/V0.1/Mesh/MeshObjects/[ID]

{
    "Id" : "urn:uuid:8d9e425a-52ea-4645-be8f-cc20d5de7446",
    "Title" : "Images",
    "Summary" : "This is a test update"
}

Response

{
    "AuthorProfileLink" : "email-nguptadev@hotmail.com\/Profiles",
    "Authors" : [
        {
            "Name" : "Nishant Gupta",
            "Uri" : "email-nguptadev@hotmail.com\/Profiles",
            "Email" : "nguptadev@hotmail.com"
        }
    ],
    "BaseUri" : "https:\/\/user-ctp.windows.net\/V0.1\/",
    "Categories" : [
        {
            "Label" : "MeshObject",
            "Name" : "MeshObject",
            "Scheme" : "http:\/\/user.windows.net\/Resource"
        }
    ],
    "Id" : "urn:uuid:8d9e425a-52ea-4645-be8f-cc20d5de7446",
    "LastUpdatedTime" : "\/Date(1237277073000)\/",
    "PublishDate" : "\/Date(1233431971000)\/",
    "SelfLink" : "Mesh\/MeshObjects\/[ID]",
    "Summary" : "This is a test update",
    "Title" : "Images",
    "ActivitiesLink" : "Mesh\/MeshObjects\/[ID]\/Activities",
    "DataFeedsLink" : "Mesh\/MeshObjects\/[ID]\/DataFeeds",
    "MappingsLink" : "Mesh\/MeshObjects\/[ID]\/Mappings",
    "MembersLink" : "Mesh\/MeshObjects\/[ID]\/Members",
    "NewsFeedLink" : "Mesh\/MeshObjects\/[ID]\/News",
    "SubscriptionLink" : "Mesh\/MeshObjects\/[ID]\/Subscriptions"
}

Step 5

We will now do a GET request on notifications to look for any notifications that may have been generated for this change.

Request

HTTP GET	
https://user-ctp.windows.net/V0.1/Mesh
/NotificationQueues/[ID]/Notifications

Response

{
   "BaseUri" : "https:\/\/user-ctp.windows.net\/V0.1\/",
   "Entries" : [
     {
       "BaseUri" : "https:\/\/user-ctp.windows.net\/V0.1\/",
       "Categories" : [
           {
               "Label" : "Notification",
               "Name" : "Notification",
               "Scheme" : "http:\/\/user.windows.net\/Resource"
            }
       ],
       "Id" : "urn:uuid:4f9e630c-c9d0-49eb-9e40-519f0de29f81",
       "LastUpdatedTime" : "\/Date(1237278069000)\/",
       "PublishDate" : "\/Date(1237278061000)\/",
       "SelfLink" : "Mesh\/NotificationQueues\/[ID]\/Notifications\/1",
       "Title" : "Title",
       "ResourceLink" : "Mesh\/MeshObjects\/[ID]",
       "Type" : 0,
       "Watermark" : "1.823.0"
     }
    ],
    "SelfLink" : "Mesh\/NotificationQueues\/[ID]\/Notifications",
    "Title" : "Notifications"
}

As you can see, there is a single entry (notification) generated.

The properties of interest in this example:

  • ResourceLink – This specifies the resource for which this notification has been generated. The client application can then do a GET request on this resource with the last Etag received to get the changes.
  • Type – This specifies the type of notification that has been generated. The possible values are
    • 0 – Resource changed. This is the most common value for type. This signifies that the resource (identified by resource link) has changed.
    • 1 – All subscriptions lost. Subscriptions can be lost for various reasons, such as: notification queue timed out, notifications overflow for this notification queue, or service crash/restart (because notifications are not persisted in database). In this case, you need to renew the notification queue by generating a PUT request with a watermark value for this notification (see the following step for details) and then re-subscribe to all the resources. Please note that when you renew the notification queue, the self-link now received for the notification queue is different from the previous one (because the old queue was lost). You need to use this new link when subscribing to resources.
    • 2 – Subscription lost for the resource identified by the resource link. The loss could be due to a service restart/crash. When this happens, the client needs to re-subscribe to the resource in order to receive further notifications for this resource.
  • Watermark – This is an opaque identifier associated with this notification. Because notifications and notification queues are not persisted in the database, the number of notifications that can be retained in memory for a given notification queue are limited. The clients are encouraged to acknowledge the receipt of notifications that they have read by doing a PUT request on Mesh/NotificationQueues/<ID> with the watermark value of the last notification in the feed. This will remove all the acknowledged notifications up to the notification with the watermark specified and will free up resources. Failure to do so will result in loss of notifications when the limit on the number of notifications allowed per queue is reached. In an ideal case, every non-empty GET on notifications should be followed by a PUT request on the notification queue with the last read watermark value.

Step 6

We will renew the notification queue and delete the stale notifications by doing a PUT request on the notification queue.

Request

HTTP PUT	
https://user-ctp.windows.net/V0.1/Mesh/NotificationQueues/[ID]
{
 "BaseUri" : "https:\/\/user-ctp.windows.net\/V0.1\/",
 "Categories" : [
     {
         "Label" : "NotificationQueue",
         "Name" : "NotificationQueue",
         "Scheme" : "http:\/\/user.windows.net\/Resource"
     }
 ],
 "Id" : "uuid:3084e6c2-56ac-4563-b67c-af7a7fc019e7;id=18130",
 "LastUpdatedTime" : "\/Date(1237276680000)\/",
 "SelfLink" : "Mesh\/NotificationQueues\/[ID]",
 "Title" : "NotificationQueueResource",
 "ExpirationDuration" : 300,
 "NotificationsLink" : "Mesh\/NotificationQueues\/[ID]\/Notifications",
 "Watermark" : "1.823.0"
}

A subsequent GET request on the notifications will appear as follows. Note that there are no more entries (notifications) because we deleted the stale entry by providing the watermark value in the PUT request on notification queue.

 

Request

HTTP GET	
https://user-ctp.windows.net/V0.1/Mesh/NotificationQueues/[ID]/Notifications

Response

{
    "BaseUri" : "https:\/\/user-ctp.windows.net\/V0.1\/",
    "Entries" : [
        
    ],
    "SelfLink" : "Mesh\/NotificationQueues\/[ID]\/Notifications",
    "Title" : "Notifications"
}

It is important to note that you can also renew the notification queue by doing an HTTP GET on notifications. This will, however, not remove the acknowledged notifications from the queue.

Take-away Points

  1. Notifications and subscriptions allow for efficient polling to check for updates on the resource without actually doing a GET request on the resource itself.
  2. The client application can create a single notification queue and use it for subscribing to multiple resources.
  3. The default life span for notification queue is 300 seconds from the last PUT request. The client application should renew it by doing an HTTP PUT on the notification queue or HTTP GET on the notifications feed within that duration. If there are acknowledged notifications that need to be removed, the client should specify the watermark value corresponding to the last such notification. The polling interval chosen by the client should be determined based on the client’s need for responsiveness and the TTL of the queue.
  4. Subscriptions to resources timeout after a period. In order for the client application to continue subscribing to the resource, it should renew it by doing a PUT request within the timeout duration.
  5. Watermarks should be treated as opaque identifiers. No assumptions should be made on their format.

--Live Services Team