While working on
SOLR-13420 and related tickets I noticed that we presently use the wrapWatch() method to wrap all zookeeper watches. This allows the watch to be processed asynchronously by an executor which is good, but it subtly changes the way zookeeper behaves. Normally zookeeper keeps a Map<String,Set<Watch>> that ensures that if the same watch is registered twice it's only notified once. However, our wrapper breaks this because now, if the same watch is added twice each one gets it's own wrapper with default Object.equals() and thus the two wrapped versions of the Watch aren not .equals() and may co-exist in the Set<Watch>
I do not know of any current cases for which this would cause a problem, but changes I am contemplating for SOLR-13375 are likely to hit this case and at a minimum create wasted re-notifications of the same event and excess watch load in Zk.
Moving the anonymous class wrapping to an explicit inner class and writing hashcode/equals carefully to act as a pass through such that any to wrappers with the same watch object are .equals() should fix this.