As part of a project for work, I needed to design an architecture for a system that could handle an infinite stream of asynchronous "events" (basically, actions triggered by end-users that my system needed to respond to). Since we were anticipating a high volume of events, it was important that the system be able to operate in a multi-threaded environment. Additionally, we wanted the system to be modular and extensible so that as functionality was added or modified (for example, adding a new consumer of events, or replacing an existing persistent storage mechanism with another one), the architecture would remain unchanged.
With these objectives in mind, I opted to treat the processing of events as a pipeline. Events would enter the pipeline (asynchronously), and would undergo a series of transformations, essentially extracting pieces of information that were relevant to downstream consumers. Finally, consumers could subscribe to "sub-streams" of interest, where they would be notified of events that were of interest to them. Once I'd settled on a pipeline as the right model for data flow through the system, I needed to find a suitable programming framework that would allow me to construct the pipeline, provide the right contracts for transformers and consumers, and, ideally, allow me to abstract away the pesky concurrency issue.
Based on what my team had learned from other groups at IBM, we adopted the Reactive framework for managing these asynchronous streams of events. In particular, we chose the RxJava implementation of the framework. It provides a great deal of functionality right out of the box for working with asynchronous streams, with many built-in operators for manipulating streams. That being said, we did encounter some pitfalls along the way, and on several occasions discovered that some erratic behavior we were observing in the system was caused by RxJava. Well, more accurately, it was caused by our misunderstanding of certain Rx concepts, or failure to read the documentation and examples carefully enough.
I won't go into any great detail about the specific problems we ran into. But I will say that going from single-threaded to multi-threaded will introduce many edge-cases that are difficult to anticipate, even with a nice framework like Reactive abstracting away the nitty gritty details. I'll also say that I found I needed to look around many places on the interwebs to learn what I needed to know about how to effectively leverage RxJava. Over the course of time, I compiled a list of specific resources that I found valuable while learning Rx, and I thought it would be a shame to let it just die on my computer. So, with that in mind, here is my list of RxJava-related resources that I encourage you to check out while you're learning the ropes:
- http://blog.danlew.net/2014/09/15/grokking-rxjava-part-1/
- https://gist.github.com/staltz/868e7e9bc2a7b8c1f754
- http://docs.couchbase.com/developer/java-2.0/observables.html
- http://blog.danlew.net/2015/03/02/dont-break-the-chain/
- http://rxmarbles.com/
- https://github.com/benjchristensen/learnrxjava
- http://akarnokd.blogspot.com/2015/06/subjects-part-1.html
- http://tomstechnicalblog.blogspot.com/2015/11/rxjava-achieving-parallelization.html
- http://tomstechnicalblog.blogspot.com/2016/02/rxjava-understanding-observeon-and.html