I'm developing a smoke tests app in Go that tests a number of services (Redis, RabbitMQ, Single Sign-On, etc) that are offered in the marketplace of a CloudFoundry installation at one of our customers. These tests produce simple JSON output that signals what went wrong. Now the customer has asked for a dashboard so the entire organization can check on the health of the platform.
I took some time to come up with a good enough design for this and decided on the following:
- The smoke tests app (Golang) pushes its results to RabbitMQ
- An ASP.NET Core app listens to smoke test results and keeps track of state (the results themselves and when they were received)
- A single page written in Elm that receives status updates via SignalR (web sockets)
Since I have never written anything in Elm and my knowledge of SignalR is a little outdated, I decided to start very simple: a SignalR hub that increments an int every five seconds and sends it to all clients. The number that's received by each client is used to update an Elm view model. In the real world, the int will become the JSON document describing the results of the smoke tests and we build a nice view for it, you get the idea.
All source code for this post can be found here.
The server side of things
First of all, what do things look like on the server and how do we build the application? It will be an ASP.NET Core app so we start with:
dotnet new web
dotnet add package Microsoft.AspNetCore.SignalR -v 1.0.0-alpha2-final
We create an empty ASP.NET Core website and add the latest version of SignalR. Next we need to configure SignalR in our
The code speaks for itself, I guess. We add SignalR dependencies to the services collection and configure a hub called
SmokeHub which can be reached from the client via the route
On line 15 you can see I add a
CounterHostedService. A hosted service is an object with a start and a stop method that is managed by the host. This means that when ASP.NET Core starts, it calls the hosted service start method and when ASP.NET Core (gracefully) shuts down, it calls the stop method. In our case, we use it to start a very simple scheduler that increments an integer every five seconds and sends it to all SignalR clients. Here are two posts on implementing your own
The client side of things
First of all, we need the SignalR client library. You can get it via npm. I added it in the
Now let's take a look at the Elm code.
Let's dissect the code:
- Line 6: we have a model, which is an
Intthat we initialize to
- Line 13: we have one message type, which is a counter of int
- Line 17: our view takes our model and returns some very simple html, showing the model value
- Line 22: when we receive an update, we simply return the count
- Line 29: we subscribe to counter updates
If we check the Elm code again, you see at line 1 we declare our module with the keyword
Most of the code speaks for itself. On line 22 we invoke the port in our Elm app to pass the updated counter to Elm. Line 25 is a simple test to assure that we can also send message from the client to the SignalR hub.
For completeness' sake, here is the code for the
Note that the
Send that is called when notifying all clients of a counter update.