lib/z_k/event_handler.rb in zk-0.9.0 vs lib/z_k/event_handler.rb in zk-0.9.1

- old
+ new

@@ -151,29 +151,55 @@ cb.call(hash) end end end + # returns true if there's a pending watch of type for path + # @private + def restricting_new_watches_for?(watch_type, path) + synchronize do + if set = @outstanding_watches[watch_type] + return set.include?(path) + end + end + + false + end + # implements not only setting up the watcher callback, but deduplicating # event delivery. Keeps track of in-flight watcher-type+path requests and # doesn't re-register the watcher with the server until a response has been # fired. This prevents one event delivery to *every* callback per :watch => true # argument. # + # due to somewhat poor design, we destructively modify opts before we yield + # and the client implictly knows this + # # @private def setup_watcher!(watch_type, opts) - return unless opts.delete(:watch) + return yield unless opts.delete(:watch) synchronize do set = @outstanding_watches.fetch(watch_type) path = opts[:path] if set.add?(path) - # this path has no outstanding watchers, let it do its thing - opts[:watcher] = watcher_callback + # if we added the path to the set, blocking further registration of + # watches and an exception is raised then we rollback + begin + # this path has no outstanding watchers, let it do its thing + opts[:watcher] = watcher_callback + + yield opts + rescue Exception + set.delete(path) + raise + end else - # outstanding watch for path and data pair already exists, so ignore -# logger.debug { "outstanding watch request for path #{path.inspect} and watcher type #{watch_type.inspect}, not re-registering" } + # we did not add the path to the set, which means we are not + # responsible for removing a block on further adds if the operation + # fails, therefore, we just yield + yield opts end end end protected