diff --git a/src/Common/ZooKeeper/TestKeeper.cpp b/src/Common/ZooKeeper/TestKeeper.cpp index 4ae26d874fbe527d290e91a91db08d85638b83d8..5f34a60c34e7344f1d1a8a8734d408218ddb9895 100644 --- a/src/Common/ZooKeeper/TestKeeper.cpp +++ b/src/Common/ZooKeeper/TestKeeper.cpp @@ -511,19 +511,30 @@ void TestKeeper::processingThread() if (expired) break; - if (info.watch) - { - auto & watches_type = dynamic_cast(info.request.get()) - ? list_watches - : watches; - - watches_type[info.request->getPath()].emplace_back(std::move(info.watch)); - } ++zxid; info.request->addRootPath(root_path); auto [response, _] = info.request->process(container, zxid); + + if (info.watch) + { + /// To be compatible with real ZooKeeper we add watch if request was successful (i.e. node exists) + /// or if it was exists request which allows to add watches for non existing nodes. + if (response->error == Error::ZOK) + { + auto & watches_type = dynamic_cast(info.request.get()) + ? list_watches + : watches; + + watches_type[info.request->getPath()].emplace_back(std::move(info.watch)); + } + else if (response->error == Error::ZNONODE && dynamic_cast(info.request.get())) + { + watches[info.request->getPath()].emplace_back(std::move(info.watch)); + } + } + if (response->error == Error::ZOK) info.request->processWatches(watches, list_watches);