An in-depth exploration of Hot and Cold Observables in Reactive Extensions, their characteristics, differences, and practical examples using Clojure.
Reactive Extensions (Rx) provide a powerful framework to work with asynchronous data streams. Observables are at the heart of Rx, acting as data emitters that can be processed using a variety of operators. However, observables can behave differently depending on whether they are “Hot” or “Cold”. Understanding these differences is crucial for designing efficient and effective reactive systems.
Using manifold.stream to simulate a cold observable:
1(require '[manifold.stream :as s])
2
3(defn cold-observable []
4 (let [stream (s/stream)]
5 (dotimes [i 5]
6 (Thread/sleep 1000)
7 (s/put! stream i))
8 stream))
9
10(let [stream (cold-observable)]
11 (s/consume println stream))
Explanation: In this example, a new stream is created for each call to cold-observable. Each subscriber receives the full sequence of numbers from 0 to 4, sequentially emitted.
Using manifold/deferred to simulate a hot observable:
1(require '[manifold.stream :as s])
2
3(def stream (s/stream))
4
5(defn hot-observable []
6 (dotimes [i 5]
7 (Thread/sleep 1000)
8 (s/put! stream i)))
9
10(future (hot-observable))
11(s/consume println stream)
Explanation: In the hot observable example, the hot-observable function continuously emits data to a shared stream. Subscribers may join in at any point and only see future emissions.
sequenceDiagram
participant C as Cold Observable
participant H as Hot Observable
participant O1 as Observer 1
participant O2 as Observer 2
Note over C,H: Observable not started
rect rgb(220, 220, 255)
O1->>+C: Subscribe
C->>O1: Emit data sequence
end
rect rgb(255, 220, 220)
H->>+H: Start emitting data
Note right of H: Active before subscribers
O2->>+H: Subscribe
H->>O2: Emit missed sequence\nstart receiving data
end
Explanation: This sequence diagram shows how Cold and Hot Observables operate. In the Cold Observable, data generation only begins on subscription. In contrast, the Hot Observable continuously emits data even before any subscription.
Understanding Hot and Cold Observables is critical in reactive programming, especially in systems that demand high concurrency and real-time data processing. Cold Observables provide independent data streams for each observer, ensuring fresh data sets, while Hot Observables share a common data stream, suitable for real-time and live data scenarios. With the practical examples in Clojure and their implementation nuances explained, this article provides a foundation for effectively using Rx patterns in modern applications.