Skip to content

Commit b45d138

Browse files
committed
feat!: carry zxid of transaction that triggering WatchedEvent
See: * apache/zookeeper#1950 * https://issues.apache.org/jira/browse/ZOOKEEPER-4655
1 parent 3ec27ad commit b45d138

File tree

5 files changed

+82
-40
lines changed

5 files changed

+82
-40
lines changed

src/session/event.rs

+20-3
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,36 @@ pub struct WatcherEvent<'a> {
1616
pub event_type: EventType,
1717
pub session_state: SessionState,
1818
pub path: &'a str,
19+
pub zxid: i64,
1920
}
2021

2122
impl<'a> Ref<'a> for WatcherEvent<'a> {
2223
type Value = WatchedEvent;
2324

2425
fn to_value(&self) -> Self::Value {
25-
WatchedEvent { event_type: self.event_type, session_state: self.session_state, path: self.path.to_owned() }
26+
WatchedEvent {
27+
event_type: self.event_type,
28+
session_state: self.session_state,
29+
path: self.path.to_owned(),
30+
zxid: self.zxid,
31+
}
2632
}
2733
}
2834

2935
impl<'a> ToRef<'a, WatcherEvent<'a>> for WatchedEvent {
3036
fn to_ref(&'a self) -> WatcherEvent<'a> {
31-
WatcherEvent { event_type: self.event_type, session_state: self.session_state, path: &self.path }
37+
WatcherEvent {
38+
event_type: self.event_type,
39+
session_state: self.session_state,
40+
path: &self.path,
41+
zxid: self.zxid,
42+
}
43+
}
44+
}
45+
46+
impl WatcherEvent<'_> {
47+
pub fn with_zxid(self, zxid: i64) -> Self {
48+
Self { zxid, ..self }
3249
}
3350
}
3451

@@ -81,6 +98,6 @@ impl<'a> DeserializableRecord<'a> for WatcherEvent<'a> {
8198
let event_type = EventType::from_server(unsafe { buf.get_unchecked_i32() })?;
8299
let session_state = SessionState::from_server(unsafe { buf.get_unchecked_i32() })?;
83100
let path = record::unmarshal(buf)?;
84-
Ok(WatcherEvent { event_type, session_state, path })
101+
Ok(WatcherEvent { event_type, session_state, path, zxid: WatchedEvent::NO_ZXID })
85102
}
86103
}

src/session/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -210,9 +210,9 @@ impl Session {
210210
}
211211
}
212212

213-
fn handle_notification(&mut self, mut body: &[u8], depot: &mut Depot) -> Result<(), Error> {
213+
fn handle_notification(&mut self, zxid: i64, mut body: &[u8], depot: &mut Depot) -> Result<(), Error> {
214214
let event = record::unmarshal_entity::<WatcherEvent>(&"watch notification", &mut body)?;
215-
self.watch_manager.dispatch_server_event(event, depot);
215+
self.watch_manager.dispatch_server_event(event.with_zxid(zxid), depot);
216216
Ok(())
217217
}
218218

@@ -281,7 +281,7 @@ impl Session {
281281
return Err(Error::AuthFailed);
282282
}
283283
if header.xid == PredefinedXid::Notification.into() {
284-
self.handle_notification(body, depot)?;
284+
self.handle_notification(header.zxid, body, depot)?;
285285
return Ok(());
286286
} else if header.xid == PredefinedXid::Ping.into() {
287287
depot.pop_ping()?;

src/session/types.rs

+27
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ impl SessionState {
6868

6969
/// WatchedEvent represents update to watched node or session.
7070
#[derive(Clone, Debug, PartialEq, Eq)]
71+
#[non_exhaustive]
7172
pub struct WatchedEvent {
7273
pub event_type: EventType,
7374

@@ -79,9 +80,35 @@ pub struct WatchedEvent {
7980

8081
/// Node path from chroot. Empty if this is a state event.
8182
pub path: String,
83+
84+
/// `zxid` of the transaction that triggered this node event, [WatchedEvent::NO_ZXID] for session event.
85+
///
86+
/// # Notable behaviors
87+
/// * This feature was shipped in 3.9.0, `zxid` wil be [WatchedEvent::NO_ZXID] for earlier versions. See [ZOOKEEPER-4655].
88+
/// * It is possible to receive multiple events with same `zxid` and even same `path` due to [MultiWriter]. See [ZOOKEEPER-4695].
89+
///
90+
/// [ZOOKEEPER-4655]: https://issues.apache.org/jira/browse/ZOOKEEPER-4655
91+
/// [ZOOKEEPER-4695]: https://issues.apache.org/jira/browse/ZOOKEEPER-4695
92+
pub zxid: i64,
8293
}
8394

8495
impl WatchedEvent {
96+
pub const NO_ZXID: i64 = -1;
97+
98+
pub fn new(event: EventType, path: impl Into<String>) -> Self {
99+
debug_assert_ne!(event, EventType::Session);
100+
Self { event_type: event, session_state: SessionState::SyncConnected, path: path.into(), zxid: Self::NO_ZXID }
101+
}
102+
103+
pub fn with_zxid(self, zxid: i64) -> Self {
104+
debug_assert_ne!(self.event_type, EventType::Session);
105+
Self { zxid, ..self }
106+
}
107+
108+
pub fn new_session(state: SessionState) -> Self {
109+
Self { event_type: EventType::Session, session_state: state, path: Default::default(), zxid: Self::NO_ZXID }
110+
}
111+
85112
pub(crate) fn drain_root_path(&mut self, root: &str) {
86113
if self.event_type != EventType::Session && !root.is_empty() {
87114
util::drain_root_path(&mut self.path, root).unwrap();

src/session/watch.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use super::request::{Operation, SessionOperation, StateReceiver, StateResponser}
99
use super::types::{EventType, SessionState, WatchMode, WatchedEvent};
1010
use crate::error::Error;
1111
use crate::proto::{ErrorCode, OpCode, SetWatchesRequest};
12-
use crate::util::Ref;
12+
use crate::util::{Ref, ToRef};
1313

1414
const SET_WATCHES_MAX_BYTES: usize = 128 * 1024;
1515

@@ -320,7 +320,8 @@ impl WatchManager {
320320
}
321321

322322
pub fn dispatch_session_state(&mut self, state: SessionState) {
323-
let event = WatcherEvent { event_type: EventType::Session, session_state: state, path: Default::default() };
323+
let _event = WatchedEvent::new_session(state);
324+
let event = _event.to_ref();
324325
self.watches.values_mut().for_each(|watch| {
325326
watch.send(&event, &mut self.watching_paths);
326327
});

tests/zookeeper.rs

+29-32
Original file line numberDiff line numberDiff line change
@@ -1224,56 +1224,53 @@ async fn test_watcher_coexist_on_same_path() {
12241224
let mut persistent_watcher = client.watch("/a", zk::AddWatchMode::Persistent).await.unwrap();
12251225
let mut recursive_watcher = client.watch("/a", zk::AddWatchMode::PersistentRecursive).await.unwrap();
12261226

1227-
client.create("/a", &vec![], PERSISTENT_OPEN).await.unwrap();
1227+
let (stat, _) = client.create("/a", &vec![], PERSISTENT_OPEN).await.unwrap();
12281228

1229-
let event = exist_watcher.changed().await;
1230-
assert_that!(event.event_type).is_equal_to(zk::EventType::NodeCreated);
1231-
assert_that!(event.path).is_same_string_to("/a");
1232-
1233-
assert_that!(persistent_watcher.changed().await).is_equal_to(&event);
1234-
assert_that!(recursive_watcher.changed().await).is_equal_to(&event);
1229+
let expected = zk::WatchedEvent::new(zk::EventType::NodeCreated, "/a".to_string()).with_zxid(stat.czxid);
1230+
assert_that!(exist_watcher.changed().await).is_equal_to(&expected);
1231+
assert_that!(persistent_watcher.changed().await).is_equal_to(&expected);
1232+
assert_that!(recursive_watcher.changed().await).is_equal_to(&expected);
12351233

12361234
let (_, _, data_watcher) = client.get_and_watch_data("/a").await.unwrap();
12371235
let (_, _, child_watcher) = client.get_and_watch_children("/a").await.unwrap();
12381236
let (_, exist_watcher) = client.check_and_watch_stat("/a").await.unwrap();
12391237

1240-
client.create("/a/b", &vec![], PERSISTENT_OPEN).await.unwrap();
1241-
let event = child_watcher.changed().await;
1242-
assert_that!(event.event_type).is_equal_to(zk::EventType::NodeChildrenChanged);
1243-
assert_that!(event.path).is_same_string_to("/a");
1244-
assert_that!(persistent_watcher.changed().await).is_equal_to(&event);
1238+
let (stat, _) = client.create("/a/b", &vec![], PERSISTENT_OPEN).await.unwrap();
1239+
let expected = zk::WatchedEvent::new(zk::EventType::NodeChildrenChanged, "/a".to_string()).with_zxid(stat.czxid);
1240+
assert_that!(child_watcher.changed().await).is_equal_to(&expected);
1241+
assert_that!(persistent_watcher.changed().await).is_equal_to(&expected);
12451242

1246-
let event = recursive_watcher.changed().await;
1247-
assert_that!(event.event_type).is_equal_to(zk::EventType::NodeCreated);
1248-
assert_that!(event.path).is_same_string_to("/a/b");
1243+
let expected = zk::WatchedEvent::new(zk::EventType::NodeCreated, "/a/b".to_string()).with_zxid(stat.czxid);
1244+
assert_that!(recursive_watcher.changed().await).is_equal_to(&expected);
12491245

12501246
let (_, _, child_watcher) = client.get_and_watch_children("/a").await.unwrap();
12511247

12521248
client.delete("/a/b", None).await.unwrap();
1253-
let event = child_watcher.changed().await;
1254-
assert_that!(event.event_type).is_equal_to(zk::EventType::NodeChildrenChanged);
1255-
assert_that!(event.path).is_same_string_to("/a");
1256-
assert_that!(persistent_watcher.changed().await).is_equal_to(&event);
1249+
let stat = client.check_stat("/a").await.unwrap().unwrap();
1250+
1251+
let expected = zk::WatchedEvent::new(zk::EventType::NodeChildrenChanged, "/a".to_string()).with_zxid(stat.pzxid);
1252+
assert_that!(child_watcher.changed().await).is_equal_to(&expected);
1253+
assert_that!(persistent_watcher.changed().await).is_equal_to(&expected);
12571254

1258-
let event = recursive_watcher.changed().await;
1259-
assert_that!(event.event_type).is_equal_to(zk::EventType::NodeDeleted);
1260-
assert_that!(event.path).is_same_string_to("/a/b");
1255+
let expected = zk::WatchedEvent::new(zk::EventType::NodeDeleted, "/a/b".to_string()).with_zxid(stat.pzxid);
1256+
assert_that!(recursive_watcher.changed().await).is_equal_to(&expected);
12611257

12621258
let (_, _, child_watcher) = client.get_and_watch_children("/a").await.unwrap();
12631259

12641260
client.delete("/a", None).await.unwrap();
1265-
let event = child_watcher.changed().await;
1266-
assert_that!(event.event_type).is_equal_to(zk::EventType::NodeDeleted);
1267-
assert_that!(event.path).is_same_string_to("/a");
1268-
assert_that!(data_watcher.changed().await).is_equal_to(&event);
1269-
assert_that!(exist_watcher.changed().await).is_equal_to(&event);
1270-
assert_that!(persistent_watcher.changed().await).is_equal_to(&event);
1271-
assert_that!(recursive_watcher.changed().await).is_equal_to(&event);
1261+
let stat = client.check_stat("/").await.unwrap().unwrap();
1262+
let expected = zk::WatchedEvent::new(zk::EventType::NodeDeleted, "/a".to_string()).with_zxid(stat.pzxid);
1263+
assert_that!(child_watcher.changed().await).is_equal_to(&expected);
1264+
assert_that!(data_watcher.changed().await).is_equal_to(&expected);
1265+
assert_that!(exist_watcher.changed().await).is_equal_to(&expected);
1266+
assert_that!(persistent_watcher.changed().await).is_equal_to(&expected);
1267+
assert_that!(recursive_watcher.changed().await).is_equal_to(&expected);
12721268

12731269
// persistent ones still exist
1274-
client.create("/a", &vec![], PERSISTENT_OPEN).await.unwrap();
1275-
let event = persistent_watcher.changed().await;
1276-
assert_that!(recursive_watcher.changed().await).is_equal_to(&event);
1270+
let (stat, _) = client.create("/a", &vec![], PERSISTENT_OPEN).await.unwrap();
1271+
let expected = zk::WatchedEvent::new(zk::EventType::NodeCreated, "/a".to_string()).with_zxid(stat.mzxid);
1272+
assert_that!(persistent_watcher.changed().await).is_equal_to(&expected);
1273+
assert_that!(recursive_watcher.changed().await).is_equal_to(&expected);
12771274
}
12781275

12791276
#[test_log::test(tokio::test)]

0 commit comments

Comments
 (0)