Keeping Cycle’s Front-End Fast: The Notification Pipeline
Hello! My name is Thomas Pape, and I am the newest member of the Development Team here at Cycle. I have spent the majority of my career working with user interface technologies, from custom game engine libraries, to most recently, React. In my last year of college, I worked as a UI programming intern for a small console games company in Los Angeles. There, I learned the importance of user experience. As the rise of mobile progressed, I continued to foster that experience and transitioned out of games and into new opportunities in mobile and web. During my time outside of games, I learned all I could about iOS, Android, and responsive web development. Over the last decade of coding, debugging, analyzing, and studying, I really have grown an appreciation for how difficult it is to get user experience right.
Although it can be daunting, I love the idea of being ‘new.’ It often means working with fresh and exciting concepts. As it turns out, one of my first tasks would be updating and refactoring functionality in our customer portal. I couldn’t wait to jump in!
Our team is small, and we move fast. On my first day, our CTO - Alex and I sat down to discuss how we would be upgrading the way that we handle application state through Redux and Redux Sagas. They allow us to centralize state management, which has streamlined development of new features. This saves a lot of time when you have a mountain of work and not enough hours in the day to get it all done. Managing state through Redux is the backbone of our frontend, with it we are able to solve the complex problem of dealing with HTTP.
When you make a request from client to server via HTTP, each command is independently executed without any knowledge of the commands before it. These independent requests are the main reason it is difficult using HTTP to implement web apps that require real-time data. In order to resolve these shortcomings, a bi-directional protocol was layered on top, known as WebSockets.
WebSockets address the shortcomings of HTTP by allowing us to open “full-duplex communication channels over a single TCP connection,” [wikipedia]. I like to think of WebSockets as being the distant cousin of classic BSD Sockets. Although they are not related, they do function in similar ways.
From a web browser, you are able to open a 2-way communication session between the browser and a server. With the WebSocket API, “you can send messages to a server and receive event-driven responses without having to poll the server for a reply,” [MDN Web Docs]. This simple concept is what will empower us to maintain the state of our app on the frontend.
Cycle takes a unique approach that keeps things up to date, while, at the same time, minimizing the data transfer between the platform and the portal. Instead of sending full objects any time a change is made, the platform sends what we call “suggestions.” Once a suggestion is received over the websocket, the API consumer then decides whether it should fetch the full object or ignore the change altogether. By utilizing suggestions, the platform is primed to scale to millions of users by minimizing the amount of bandwidth between the various services Cycle implements.
Here is an example of a suggestion pertaining to a SDN Network resource. The topic shows what type of resource and what part of the resource has changed (a network was reconfigured). Information about that resource is then passed through the object, in this example the ID and state of the network. Finally, context information such as which hub, environments and clusters the resource is a part of.
In our implementation, once an update is received, it looks at whether or not a user has viewed the object (i.e. a container). If it exists in cache, the portal will make a decision on whether or not to fetch it. Once it is in cache, we can assume that we have the latest version until a new suggestion is received (or the connection to the websocket is severed).
Of course, that leads to the question “what if the connection is severed?” Once that happens, we can no longer guarantee that our data is up to date, as we have no idea how many suggestions may have been missed. At that point, the data is marked as “stale.” When a connection is re-established, all previously cached data will get re-fetched when requested again, and the Cycle goes on.
The suggestion pattern, coupled with data caching, empowers the frontend to stay up to date without having to fetch any unnecessary data in the background. The client decides when to fetch data based on what is most relevant to the user. This model makes for a highly scalable system without sacrificing the user’s experience. Gone are the days of strictly using REST APIs to manage the state of our web applications, allowing for real-time data management without the overhead of unnecessary server requests.
Great news, Cycle’s entire API is publicly accessible! In addition to the standard REST API, you’ll have access to the same websocket we use on the front end, called the “Notification Pipeline”. You can easily tune in for streaming updates of platform resources. Data caching is just one use case — the websocket can be utilized to accomplish much more. For example, a custom notification system could be set up that alerts when containers shut down or encounter errors. I’m excited to see all the ways our users take advantage of these APIs to fine-tune Cycle for their needs.
See the Cycle API Docs for more details!
Want to check out the API but don’t have a hub deployed? Sign up for a trial and enjoy 90 days of access to the platform on us!