def _get_watcher(self, path, callback=None): """Creates a Watcher object for the supplid path. Creates a Watcher object for the supplied path and returns the object. Triggers callbacks immediately. This is broken into its own function so that it can leverage the @_health_check decorator. This function should never be called from outside of this class. Args: path: A string representing the path to the servers. callback: (optional) reference to function to call if the path changes. Returns: nd_service_registry.Watcher object """ # Ok, so the cache is missing the key. Lets look for it in Zookeeper self.log.debug('[%s] Creating Watcher object...' % path) watcher = Watcher(self._zk, path, watch_children=True, callback=callback) # Always register our dictionary saver callback, in addition to # whatever our user has supplied watcher.add_callback(self._save_watcher_to_dict) return watcher
def _get_watcher(self, path, callback=None): """Creates a Watcher object for the supplid path. Creates a Watcher object for the supplied path and returns the object. Triggers callbacks immediately. This is broken into its own function so that it can leverage the @_health_check decorator. This function should never be called from outside of this class. Args: path: A string representing the path to the servers. callback: (optional) reference to function to call if the path changes. Returns: nd_service_registry.Watcher object """ # Ok, so the cache is missing the key. Lets look for it in Zookeeper log.debug('[%s] Creating Watcher object...' % path) watcher = Watcher(self._zk, path, watch_children=True, callback=callback) # Always register our dictionary saver callback, in addition to # whatever our user has supplied watcher.add_callback(self._save_watcher_to_dict) return watcher
def test_watch_on_nonexistent_path_with_multiple_data_changes(self): path = '%s/nonexistent-path-%s' % (self.sandbox, uuid.uuid4().hex) watch = Watcher(zk=self.zk, path=path) # In order to track the number of callbacks that are registered, # we register a mocked method in the callbacks. callback_checker = mock.Mock() callback_checker.test.return_value = True watch.add_callback(callback_checker.test) # Initially, we expect the data, children count and stat data # to be None because the node doesn't exist. self.assertEquals(None, watch.get()['data']) self.assertEquals(None, watch.get()['stat']) self.assertEquals([], watch.get()['children']) # Now register a child node under the path, and expect the # data to change child_path = '%s/my_child_test' % path self.zk.create(child_path, makepath=True) # Wait until the children list changes def get_children(): return watch.get()['children'] waituntil(get_children, [], timeout=5) # Now verify that the data has been updated in our Watcher self.assertTrue('my_child_test' in watch.get()['children']) # Now make a series of data changes and wait for each one to # take effect before moving on to the next one. def get_data(): return watch.get()['data'] for i in range(1, 5): self.zk.set(path, value=('%s' % i).encode('UTF-8')) waituntil(get_data, {'string_value': '%s' % i}, timeout=5, mode=2) # The right number of calls is 6. There are a few upfront calls when # the Watcher object is initialized, and after that there are a few # calls for the updated node-data when new children are added. The # call count would be MUCH higher (11++) if we were recursively # creating Watches though. self.assertEquals(6, len(callback_checker.test.mock_calls))
def test_watch_on_nonexistent_path_with_multiple_data_changes(self): path = '%s/nonexistent-path-%s' % (self.sandbox, uuid.uuid4().hex) watch = Watcher(zk=self.zk, path=path) # In order to track the number of callbacks that are registered, # we register a mocked method in the callbacks. callback_checker = mock.Mock() callback_checker.test.return_value = True watch.add_callback(callback_checker.test) # Initially, we expect the data, children count and stat data # to be None because the node doesn't exist. self.assertEquals(None, watch.get()['data']) self.assertEquals(None, watch.get()['stat']) self.assertEquals([], watch.get()['children']) # Now register a child node under the path, and expect the # data to change child_path = '%s/my_child_test' % path self.zk.create(child_path, makepath=True) # Wait until the children list changes def get_children(): return watch.get()['children'] waituntil(get_children, [], timeout=5) # Now verify that the data has been updated in our Watcher self.assertTrue('my_child_test' in watch.get()['children']) # Now make a series of data changes and wait for each one to # take effect before moving on to the next one. def get_data(): return watch.get()['data'] for i in xrange(1, 5): self.zk.set(path, value='%s' % i) waituntil(get_data, {'string_value': '%s' % i}, timeout=5, mode=2) # The right number of calls is 6. There are a few upfront calls when # the Watcher object is initialized, and after that there are a few # calls for the updated node-data when new children are added. The # call count would be MUCH higher (11++) if we were recursively # creating Watches though. self.assertEquals(6, len(callback_checker.test.mock_calls))