You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@zookeeper.apache.org by Jonathan Smith <jo...@mail.com> on 2013/01/23 13:12:12 UTC

ZooKeeper Watch triggered multiple times for the same notification – contrary to docs

I have a node that has a children watch on it. Whenever the
NodeChildrenChanged event is received I obtain the children using
getChildren passing in my watcher then iterate through all children
and perform a getData() also passing in my watcher so that I am also
notified of any changes to the data on the children.

E.g.

    public void check() {
        List<String> children =
zkclient.getChildren().usingWatcher(myWatcher).forPath(PATH);
        for (String name : children) {
            byte[] data =
zkclient.getData().usingWatcher(myWatcher).forPath(getPathFromName(name));
            // do stuff
        }
    }


    CuratorWatcher myWatcher = new CuratorWatcher() {
        @Override
        public void process(WatchedEvent event) throws Exception {
            logger.info("received watch event: " + event);
            if (event.getType().equals(EventType.NodeChildrenChanged)
                    || event.getType().equals(EventType.NodeDataChanged)) {
                check();
            }
        }
    };

This means that whenever a child is added/removed, another getData
call will be made with the watcher.

After reading the ZooKeeper documentation I thought it would be fine
to keep setting the watcher since I should only be given the same
watch notification once:

“A watch object, or function/context pair, will only be triggered once
for a given notification. For example, if the same watch object is
registered for an exists and a getData call for the same file and that
file is then deleted, the watch object would only be invoked once with
the deletion notification for the file.”

http://zookeeper.apache.org/doc/trunk/zookeeperProgrammers.html#ch_zkWatches

However I have observed that when a node is deleted I am receiving the
NodeDeleted watch event multiple times:

received watch event: WatchedEvent state:SyncConnected
type:NodeDeleted path:/a/b
received watch event: WatchedEvent state:SyncConnected
type:NodeDeleted path:/a/b
received watch event: WatchedEvent state:SyncConnected
type:NodeDeleted path:/a/b
...

This means the watch is being triggered multiple times unnecessarily.

I am using the Curator framework however I believe this just passes
the watches through and therefore this is a ZooKeeper issue.  I am
using zookeeper server version 3.4.5, zookeeper client 3.3.1,
curator-framework 1.2.2.

Is the documentation wrong / is this a bug or have I misunderstood?

Many thanks,
Jon

Re: ZooKeeper Watch triggered multiple times for the same notification – contrary to docs

Posted by Jonathan Smith <jo...@mail.com>.
Thanks, it looks like this was an issue with Curator that has now been fixed:

https://github.com/Netflix/curator/commit/27550024ad3dcda7c2494f633d0b60cdc2f43ad2

+1.3.2 - xxxxxxxxxxxxxxxx	
+========================
+* MAJOR BUG FIX - Issue 232: ZooKeeper guarantees that "A watch
object, or function/context pair, will only
+be triggered once for a given notification." Curator was breaking
this guarantee by internally creating a
+new Watcher object each time one was needed. This is now fixed and
ZooKeeper's guarantee is restored. Big
+thanks to user barkbay for his persistence and help on this.
+

On 24 January 2013 00:35, Jordan Zimmerman <jo...@jordanzimmerman.com> wrote:
> I agree that the docs are misleading. The watcher triggers once for the event registered. However, watchers can (and will) receive multiple connection-type events (EventType.None). That said, I think Curator recipes should be resilient to this. Please post an issue at the Curator github site: https://github.com/Netflix/curator/issues
>
> -JZ
>
> On Jan 23, 2013, at 4:12 AM, Jonathan Smith <jo...@mail.com> wrote:
>
>> I have a node that has a children watch on it. Whenever the
>> NodeChildrenChanged event is received I obtain the children using
>> getChildren passing in my watcher then iterate through all children
>> and perform a getData() also passing in my watcher so that I am also
>> notified of any changes to the data on the children.
>>
>> E.g.
>>
>>    public void check() {
>>        List<String> children =
>> zkclient.getChildren().usingWatcher(myWatcher).forPath(PATH);
>>        for (String name : children) {
>>            byte[] data =
>> zkclient.getData().usingWatcher(myWatcher).forPath(getPathFromName(name));
>>            // do stuff
>>        }
>>    }
>>
>>
>>    CuratorWatcher myWatcher = new CuratorWatcher() {
>>        @Override
>>        public void process(WatchedEvent event) throws Exception {
>>            logger.info("received watch event: " + event);
>>            if (event.getType().equals(EventType.NodeChildrenChanged)
>>                    || event.getType().equals(EventType.NodeDataChanged)) {
>>                check();
>>            }
>>        }
>>    };
>>
>> This means that whenever a child is added/removed, another getData
>> call will be made with the watcher.
>>
>> After reading the ZooKeeper documentation I thought it would be fine
>> to keep setting the watcher since I should only be given the same
>> watch notification once:
>>
>> “A watch object, or function/context pair, will only be triggered once
>> for a given notification. For example, if the same watch object is
>> registered for an exists and a getData call for the same file and that
>> file is then deleted, the watch object would only be invoked once with
>> the deletion notification for the file.”
>>
>> http://zookeeper.apache.org/doc/trunk/zookeeperProgrammers.html#ch_zkWatches
>>
>> However I have observed that when a node is deleted I am receiving the
>> NodeDeleted watch event multiple times:
>>
>> received watch event: WatchedEvent state:SyncConnected
>> type:NodeDeleted path:/a/b
>> received watch event: WatchedEvent state:SyncConnected
>> type:NodeDeleted path:/a/b
>> received watch event: WatchedEvent state:SyncConnected
>> type:NodeDeleted path:/a/b
>> ...
>>
>> This means the watch is being triggered multiple times unnecessarily.
>>
>> I am using the Curator framework however I believe this just passes
>> the watches through and therefore this is a ZooKeeper issue.  I am
>> using zookeeper server version 3.4.5, zookeeper client 3.3.1,
>> curator-framework 1.2.2.
>>
>> Is the documentation wrong / is this a bug or have I misunderstood?
>>
>> Many thanks,
>> Jon
>

Re: ZooKeeper Watch triggered multiple times for the same notification – contrary to docs

Posted by Jordan Zimmerman <jo...@jordanzimmerman.com>.
I agree that the docs are misleading. The watcher triggers once for the event registered. However, watchers can (and will) receive multiple connection-type events (EventType.None). That said, I think Curator recipes should be resilient to this. Please post an issue at the Curator github site: https://github.com/Netflix/curator/issues

-JZ

On Jan 23, 2013, at 4:12 AM, Jonathan Smith <jo...@mail.com> wrote:

> I have a node that has a children watch on it. Whenever the
> NodeChildrenChanged event is received I obtain the children using
> getChildren passing in my watcher then iterate through all children
> and perform a getData() also passing in my watcher so that I am also
> notified of any changes to the data on the children.
> 
> E.g.
> 
>    public void check() {
>        List<String> children =
> zkclient.getChildren().usingWatcher(myWatcher).forPath(PATH);
>        for (String name : children) {
>            byte[] data =
> zkclient.getData().usingWatcher(myWatcher).forPath(getPathFromName(name));
>            // do stuff
>        }
>    }
> 
> 
>    CuratorWatcher myWatcher = new CuratorWatcher() {
>        @Override
>        public void process(WatchedEvent event) throws Exception {
>            logger.info("received watch event: " + event);
>            if (event.getType().equals(EventType.NodeChildrenChanged)
>                    || event.getType().equals(EventType.NodeDataChanged)) {
>                check();
>            }
>        }
>    };
> 
> This means that whenever a child is added/removed, another getData
> call will be made with the watcher.
> 
> After reading the ZooKeeper documentation I thought it would be fine
> to keep setting the watcher since I should only be given the same
> watch notification once:
> 
> “A watch object, or function/context pair, will only be triggered once
> for a given notification. For example, if the same watch object is
> registered for an exists and a getData call for the same file and that
> file is then deleted, the watch object would only be invoked once with
> the deletion notification for the file.”
> 
> http://zookeeper.apache.org/doc/trunk/zookeeperProgrammers.html#ch_zkWatches
> 
> However I have observed that when a node is deleted I am receiving the
> NodeDeleted watch event multiple times:
> 
> received watch event: WatchedEvent state:SyncConnected
> type:NodeDeleted path:/a/b
> received watch event: WatchedEvent state:SyncConnected
> type:NodeDeleted path:/a/b
> received watch event: WatchedEvent state:SyncConnected
> type:NodeDeleted path:/a/b
> ...
> 
> This means the watch is being triggered multiple times unnecessarily.
> 
> I am using the Curator framework however I believe this just passes
> the watches through and therefore this is a ZooKeeper issue.  I am
> using zookeeper server version 3.4.5, zookeeper client 3.3.1,
> curator-framework 1.2.2.
> 
> Is the documentation wrong / is this a bug or have I misunderstood?
> 
> Many thanks,
> Jon