A real time notification system built using NodeJS and Redis. The motivation for this project is to integrate it into Graphyte
, an ongoing research project under my mentor at The City College of New York.
Graphyte - The Scientific Collaboration Tool
Before diving into Caesium, some context about Graphyte is needed. Graphyte is a platform built by G.L.A.S.S Lab at The City College of New York to allow collaborators in any scientific collaborations to share their source code, data and computational artifacts with one another within a unified-looking environment. It currently consists of the following sub-systems:
- Graphyte Core System (GCS)
- Graphyte-CLI: Command Line Interface using Graphyte
- Kalium: Simple data store
- Aurum: GCS Client for creating unit-test based assessments for learning
- Aurum-cli: Command line interface with the Aurum API
- Aurum-Web: Web based interface for packaging scorm modules
- Aurum-js: JavaScript client library for scorm modules using Aurum
- Repoman: Wrapper for working with different repo-hosts (mercurial, git, scm-manager)
- Canary: Wrapper for input/output data blobs to use (Kalium, EC2, OpenStack)
- Caesium: A real time notification system used for debugging and notifying progress of a job being run
At a high level, Graphyte is currently being used for automated learning through the use of an Learning Management System (Aurum) through the Blackboard client. By creating scorm modules, a student can submit their code to the exercise on Blackboard, where their code is sent through a distributed computing network through the use of Condor
. After the result is returned up through Condor
, GCS
and Aurum
, respectfully, the student recieves a report based on what tests they passed and failed through the unit tests.
Inception of Caesium - The Reactive API
Where does the name Caesium come from? As seen from all other systems in our lab, Caesium also takes its name from chemical names. Caesium is a very reactive element, and therefore it was the perfect name for a system which sends notifications in real time based on a triggered event.
Due to the complexity of Graphyte, it is tough to debug across several web applications working in unison with each other. Sometimes the student’s code does not get saved into the database, and sometimes internal errors occur which can’t always be tracked. To help solve this problem, Caesium can be used to send notifications to the student while their code is being ran inside of the scorm module on Blackboard. On top of this, a progress bar can be displayed which will allow the user to track the progress of their job and to be able to report exactly where an error occurs in the stacktrace.
API Requirements and Roadmap
From my understanding of the task presented to me, I knew that I had to somehow propogate messages to the student. This would require having several connections open at the same time, and the server and client would be constantly checking if there is any new data to be sent. Instead of using a comet
long-polling method (which could potentially cause problems when too many connections are being opened), I decided to use Node.js
due to its evented I/O.
Using Node.js
and socket.io
in conjunction with each other, all that is needed is a middleman to send push notifications. After a little bit of research, I stumbled upon pubsubhubub
, which is short for a hub containing a set of channels which can send and recieve push notifications.Instead of implementing my own version of pubsub
, I used redis
for its rich API which also includes a pubsub
implementation. A simple example of redis’s pubsub is shown below:
By using the redis-python
client combined with node.js
, socket.io
and the redis
client for node.js, we can generate a progress bar which will fill up based on the notifications being sent throughout the execution of the student’s job as it propogates through Graphyte.
The advantage of using this setup is that through the use of Node.js, whenever an event is triggered (in this case, the event is triggered whenever there is a notification to push) it will be published to the user based on the channel they automatically subscribe to. Using Node.js greatly reduces the overhead needed to sustain several connections by the client, and therefore these tools were right for the task.
Node.js Server
After understanding the requirements, it was time to write the Node.js server. The code server.js
is shown below:
Node.js Client
After writing and testing the server, I moved onto writing the client to recieve these messages, index.html
:
The goal here is to fire off events based on reconnection, connection and messages being sent. For now, a channel is created using a two dummy variables. The client is automatically subscribed to this channel, and through the use of our test Python script, whenever a message is sent to that channel, the client’s progress bar will increase by a set amount depending on the execution location of their job.
Current Progress
Now that the code has been written, the process of folding in Caesium into the production machine is underway. Caesium has only been integrated into Aurum, but fortunately it is easy to do pubsub across several sub-systems, as long as a channel name is persisted across the platform. More to come in the future.
Experience
Throughout my time working on this project over the last 7 months, I have learned a wide array of skills with new and unfamiliar technologies. After being exposed to redis and the power it has when coupled with Node.js and Socket.io, I look forward to developing more applications using these technologies.
Aside from learning new technology, I’ve learned to adapt to a large codebase and figure out where and how I can contribute. The biggest learning curve for me was to understand how to structure my code in a way such that it can be folded into any sub-system seamlessly without the need for hard-coded dependencies, a skill that is often hard to develop in school due to a lack of projects with large codebases.