Regarding `lastObservedClusterStateStatus` - it's needed because the cluster state status can change and we want to know what the status was when we sampled the cluster state. As it is accessed by multiple threads (potentially) i made it volatile. In general this class is built to used from a single thread at a time from the consumer side (the one using the observer). Only the cluster state listener can be called in parallel. O.w. it will become even more complex.

Regarding `observing`  -  I packaged it + listener + predicate to single wrapper object. It makes things cleaner indeed.