Click here to Skip to main content
15,868,016 members
Articles / Hosted Services / Azure
Article

Broadcast Real-time Updates from Azure Cosmos DB with SignalR Service and Azure Functions

28 Dec 2018CPOL 11.7K   7   3
In this article, we'll look at how we can use Azure Functions and SignalR Service to broadcast real-time document changes in Azure Cosmos DB to clients over WebSockets.

This article is in the Product Showcase section for our sponsors at CodeProject. These articles are intended to provide you with information on products and services that we consider useful and of value to developers.

Azure Cosmos DB has a nifty change feed feature that tracks create and update events on documents in a collection. Applications, including serverless apps built with Azure Functions, can read events from the change feed and listen to new events on the change feed in real-time.

Azure SignalR Service is a managed service that allows applications to broadcast real-time messages to many connected clients over WebSockets and other supported transports.

September 24, 2018 - Azure SignalR Service is now generally available!

In this article, we'll look at how we can use Azure Functions and SignalR Service to broadcast real-time document changes in Azure Cosmos DB to clients over WebSockets.

Overview

Here's how all the pieces fit together.

  1. A document is created or updated in Azure Cosmos DB.
  2. The change or update event is automatically logged in the Azure Cosmos DB change feed.
  3. Using the Azure Cosmos DB trigger, an Azure Function is invoked when the event appears in the change feed.
  4. Using the SignalR Service output binding, the function outputs a message to SignalR Service.
  5. SignalR Service sends the message to all connected clients over WebSockets.

Image 1

The SignalR client SDK is available in JavaScript and .NET Standard. There's also a Java client coming soon. We'll use a simple Vue.js app in a browser for this project. Using the .NET Standard SDK, we can also build desktop apps with .NET Framework and .NET Core or mobile apps with Xamarin to receive messages from SignalR Service.

Connecting Azure Cosmos DB change feed to SignalR Service with Azure Functions

We'll first look at how to implement our Azure Functions using JavaScript, then we'll do the same with C#. Java and Python support in Azure Functions are coming in the future.

The example we'll use is an airline flight pricing database. Each flight is a document in a Azure Cosmos DB collection, and any changes in the data will be reflected in the application in real-time.

Image 2

JavaScript

The complete solution can be found here. The main function we'll look at is OnDocumentsChanged.

In function.json, we define two bindings:

  • Azure Cosmos DB trigger - when a change is detected in the flights collection, the function is executed, passing in the updated document(s) in an argument named updatedFlights.
  • SignalR Service output binding - used by the function to output messages to a SignalR Service hub named flights.
JavaScript
{
  "disabled": false,
  "bindings": [
    {
      "type": "cosmosDBTrigger",
      "name": "updatedFlights",
      "direction": "in",
      "databaseName": "demo",
      "collectionName": "flights",
      "feedPollDelay": 1000
    },
    {
      "type": "signalR",
      "name": "signalRMessages",
      "hubName": "flights",
      "direction": "out"
    }
  ]
}

To use the Azure Cosmos DB and SignalR Service bindings, we need to install them using the Functions Core Tools CLI:

  • func extensions install -p Microsoft.Azure.WebJobs.Extensions.CosmosDB -v 3.0.1
  • func extensions install -p Microsoft.Azure.WebJobs.Extensions.SignalRService -v 1.0.0-preview1-10002

Check the extensions (Azure Cosmos DB, SignalR Service) for the latest versions of these packages. Currently (September 2018), the SignalR Service bindings are in public preview, but the service itself is generally available.

Also ensure that these app settings are configured with the relevant connection strings: AzureWebJobsCosmosDBConnectionString and AzureSignalRConnectionString.

The function itself is very simple. We are simply mapping the array of updated documents into an array of SignalR Service message objects. Our message object instructs SignalR Service to invoke the flightUpdated method on each client with the Azure Cosmos DB document as the argument. A SignalR Service message contains two properties:

  • target - The name of the method to invoke on each client
  • arguments - The arguments to pass to the method
JavaScript
module.exports = function (context, updatedFlights) {
  context.bindings.signalRMessages =
    updatedFlights.map(flight => ({
      target: 'flightUpdated',
      arguments: [flight]
    }));;
  context.done();
};

Skip to the next section to see how to implement the client-side JavaScript.

C#

Take a look at this solution to implement the same thing in C#.

To use the Azure Cosmos DB and SignalR Service bindings, we need to install them via NuGet:

  • dotnet add package Microsoft.Azure.WebJobs.Extensions.CosmosDB --version 3.0.1
  • dotnet add package Microsoft.Azure.WebJobs.Extensions.SignalRService --version 1.0.0-preview1-10002

Check the extensions NuGet packages (Azure Cosmos DB, SignalR Service) for the latest versions. Currently (September 2018), the SignalR Service bindings are in public preview, but the service itself is generally available.

Also ensure that these app settings are configured with each service's connection string: AzureWebJobsCosmosDBConnectionString and AzureSignalRConnectionString.

The function that we want to look at is OnDocumentsChanged:

C#
[FunctionName("OnDocumentsChanged")]
public static async Task Run(
  [CosmosDBTrigger("demo", "flights", ConnectionStringSetting = "AzureWebJobsCosmosDBConnectionString")]
    IEnumerable<object> updatedFlights,
  [SignalR(HubName = "flights")] IAsyncCollector<SignalRMessage> signalRMessages,
  ILogger log)
{
  foreach(var flight in updatedFlights)
  {
    await signalRMessages.AddAsync(new SignalRMessage
    {
      Target = "flightUpdated",
      Arguments = new[] { flight }
    });
  }
}

The CosmosDBTrigger attribute is listening to changes in a collection named flights in a database named demo. When a change occurs, the function is triggered and the list of updated document(s) are available in the updatedFlights parameter.

The function uses the SignalR output binding to output messages to a SignalR Service hub named flights. We'll invoke a method named flightUpdated on each connected client, passing the updated document as the argument. A SignalR Service message contains two properties:

  • Target - The name of the method to invoke on each client
  • Arguments - The arguments to pass to the method

Receiving real-time updates in a browser

Both the JavaScript and C# implementations invoke a flightUpdated method on each client. In the client-side JavaScript, add an event listener for flightUpdated:

JavaScript
connection.on('flightUpdated', flightUpdated)

function flightUpdated(updatedFlight) {
  // update UI
}

To see the body of flightUpdated and the rest of the single page app, take a look at index.html.

And that's all we need to do to broadcast changes in Azure Cosmos DB to clients connected to SignalR Service!

Resources

The source code is on GitHub.

Azure SignalR Service is now generally available. Learn more by reading the docs and try it today!

Check out this episode of On .NET, where we demo this application [19:35].

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionHow does the function know where to get the SignalR(HubName = "flights") Pin
85522-May-19 17:06
85522-May-19 17:06 
How does the function know where to get the SignalR(HubName = "flights")

QuestionError in local.settings.sample Pin
Member 1125915422-Jan-19 11:15
Member 1125915422-Jan-19 11:15 
Praisenice one Pin
Satyaprakash Samantaray1-Jan-19 8:42
Satyaprakash Samantaray1-Jan-19 8:42 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.