By Doug Tidwell
Tutorial: Reactica architecture
This is the third of a four-part interactive tutorial on reactive programming and Vert.x. The tutorial can be viewed in full at developers.redhat.com/coderland/reactive/.
The reactive system built in this exercise represents data about the Reactica roller coaster at Coderland, an imaginary theme park that showcases modern technologies and techniques. The Reactica system contains multiple components that use Red Hat AMQ, Red Hat Data Grid, and the Vert.x event bus to pass data asynchronously. The end result is a web UI that calculates the current wait time for the coaster based on the number of people in line, the length of the ride, and how many people can ride at once.
The web UI also displays a list of users. That includes park guests who are still in line, guests who are currently on the ride, and a few of the guests who have already ridden the coaster. The entire display is driven by a sophisticated infrastructure that illustrates the power and flexibility of reactive programming.
Your assignment: Build the web UI that shows Coderland guests how long they'll have to wait before experiencing the awesomeness of the Reactica roller coaster.
- The Reactica roller coaster: github.com/reactica/rhte-demo
- A Vert.x starter application: github.com/redhat-developer-demos/vertx-starter
- Reactica Part 1: An introduction to reactive programming and Vert.x
- Reactica Part 2: Building a reactive system
- Reactica Part 3: A reactive system in action
The following is a Coderland presentation about our latest attraction, the Reactica roller coaster.
Hello! This is Doug Tidwell for Coderland. In this video, we'll go through the Reactica architecture. We'll start by looking at the components that produce the data that drives the entire system, then we'll look at the components that consume that data, and ultimately generate the web UI that is the whole point of this exercise.
As we get going, we assume you've cloned or forked the Reactica repo, available at the URL on your screen. [https://github.com/reactica/rhte-demo]
We'll discuss everything in terms of this diagram. There are five components. In the upper left, there's the component that generates User and Ride objects. The new objects are sent as events to the AMQ broker. In the lower left, there's the Event Store component that takes data from AMQ and stores it in the data grid. In the lower right are the Queue Length Estimate and Current Waiting Line components. Those consume data from the data grid and generate the data consumed by the Billboard UI component in the upper right.
As we get started, let me say that we're not going to do a deep dive into the code here. The article that accompanies this video does that, and of course, you can always look at the code itself to see exactly how things are written.
So, let's look at the main data producers on the left side of the diagram. The Users and Rides component, as we said, generates User and Ride objects. Those objects are the heart of the domain model that Reactica uses. They're passed as JSON data in an Event object.
For the objects themselves, a User has a name and a state. The state of a user goes from IN_QUEUE to ON_RIDE to COMPLETED_RIDE. The User object also has data about when they got in line and when they got off the ride. A Ride object represents a single round-trip of the coaster. When a Ride's status changes to IN_PROGRESS, some number of Users have their state changed to ON_RIDE. When the Ride's status changes to COMPLETED, those Users have their state changed to COMPLETED_RIDE.
The Event Store component makes sure that all of the User objects end up in the Data Grid. The Users and Rides and Event Store components on the left side of the diagram create that data that drives everything else in the system.
Now we'll look at the right side of the diagram. The Queue Length Estimate and Current Waiting Line components are consumers of the data in the data grid. They also produce data that is consumed by the Billboard UI component. It's important to remember that in a reactive system, a given component can be both a producer and a consumer.
The Queue Length Estimator uses a periodic query that runs every ten seconds. It looks at the number of users in line, how long the ride takes, and the number of users who can ride at the same time. So if there are 20 people in line, the ride takes a minute, and ten people can ride at once, the 21st person in line will have to wait roughly three minutes. The next two rides that leave the station will carry the first 20 people in line, so the new person at the back of the line will have to wait for the third ride. If there were only 19 people in line, the new guest can get on the second ride, so their wait time is only two minutes.
Which brings us to the continuous query used by the Current Waiting Line component. A periodic query, as you would expect, queries the data grid periodically. A continuous query, if you're not familiar with the term, sounds like, well, something that queries the data grid continuously. But that's not how it works. The query runs once when we set it up, then the Current Waiting Line component becomes an observer of the data in the data grid. When we run that first query, we ask for all the users that are currently in line or on the ride, along with no more than ten users who have completed the ride. (We show a few completed users, but there's no point in listing all of them.)
When we set up the query, we get the results of the query right away. The best thing about the continuous query is that whenever any data that matches the query is created, or any existing data that matches the query changes, the data grid sends the new data to the Current Waiting Line component. Again, we're basically registering that component as an Observer; the data grid tells us whatever we need to know. It's a great architecture for dealing with asynchronous data in a reactive system.
The last component, and the one that ultimately does the work we set out to do, is the Billboard UI. It subscribes to two queues at the AMQ message broker. One queue is data sent by the Current Waiting Line component; the other is sent by the Queue Length Estimate. Anytime any new data about the current line or wait time is sent to AMQ, the Billboard component receives that data and updates its display. (We'll look at the web UI in the next video.)
So that's the architecture of Reactica. Remember our earlier definition: Reactive programming is programming with asynchronous data streams. The components of the system produce and consume data independently, but the system as a whole creates the web UI that shows the current state of all the data we care about.
Thanks so much for watching, and be sure to keep going with the next video. As always, let us hear from you if you have any questions, suggestions, or even PRs. We're firstname.lastname@example.org.
For Coderland, this is Doug Tidwell, saying May all your bugs be shallow. Cheers.