1use crate::caller::{ClientCaller, ClientCallerBuilder};
4pub use crate::rpc::pb::mvccpb::event::EventType;
5
6use crate::error::{Error, Result};
7use crate::intercept::InterceptedChannel;
8use crate::rpc::pb::etcdserverpb::watch_client::WatchClient as PbWatchClient;
9use crate::rpc::pb::etcdserverpb::watch_request::RequestUnion as WatchRequestUnion;
10use crate::rpc::pb::etcdserverpb::{
11 WatchCancelRequest, WatchCreateRequest, WatchProgressRequest, WatchRequest,
12 WatchResponse as PbWatchResponse,
13};
14use crate::rpc::pb::mvccpb::Event as PbEvent;
15use crate::rpc::{KeyRange, KeyValue, ResponseHeader};
16use std::pin::Pin;
17use std::task::{Context, Poll};
18use tokio::sync::mpsc::{channel, Sender};
19use tokio_stream::{wrappers::ReceiverStream, Stream};
20use tonic::Streaming;
21
22type Client = PbWatchClient<InterceptedChannel>;
23
24#[repr(transparent)]
26#[derive(Clone)]
27pub struct WatchClient {
28 inner: ClientCaller<Client>,
29}
30
31impl WatchClient {
32 #[inline]
34 pub(crate) fn new(builder: ClientCallerBuilder) -> Self {
35 Self {
36 inner: builder.build(Client::new),
37 }
38 }
39
40 pub fn max_decoding_message_size(mut self, limit: usize) -> Self {
44 self.inner = self
45 .inner
46 .with(|client| client.max_decoding_message_size(limit));
47 self
48 }
49
50 pub async fn watch(
58 &mut self,
59 key: impl Into<Vec<u8>>,
60 options: Option<WatchOptions>,
61 ) -> Result<WatchStream> {
62 async fn watch_impl(client: &mut Client, options: WatchOptions) -> Result<WatchStream> {
63 let (request_sender, request_receiver) = channel::<WatchRequest>(100);
64 request_sender
65 .send(options.into())
66 .await
67 .map_err(|e| Error::WatchError(e.to_string()))?;
68 let request_stream = ReceiverStream::new(request_receiver);
69 let stream = client.watch(request_stream).await?.into_inner();
70 Ok(WatchStream::new(request_sender, stream))
71 }
72 self.inner
73 .do_call(options.unwrap_or_default().with_key(key), watch_impl)
74 .await
75 }
76}
77
78#[derive(Debug, Default, Clone)]
80pub struct WatchOptions {
81 req: WatchCreateRequest,
82 key_range: KeyRange,
83}
84
85impl WatchOptions {
86 #[inline]
88 pub fn with_key(mut self, key: impl Into<Vec<u8>>) -> Self {
89 self.key_range.with_key(key);
90 self
91 }
92
93 #[inline]
95 pub const fn new() -> Self {
96 Self {
97 req: WatchCreateRequest {
98 key: Vec::new(),
99 range_end: Vec::new(),
100 start_revision: 0,
101 progress_notify: false,
102 filters: Vec::new(),
103 prev_kv: false,
104 watch_id: 0,
105 fragment: false,
106 },
107 key_range: KeyRange::new(),
108 }
109 }
110
111 #[inline]
117 pub fn with_range(mut self, end: impl Into<Vec<u8>>) -> Self {
118 self.key_range.with_range(end);
119 self
120 }
121
122 #[inline]
124 pub fn with_from_key(mut self) -> Self {
125 self.key_range.with_from_key();
126 self
127 }
128
129 #[inline]
131 pub fn with_prefix(mut self) -> Self {
132 self.key_range.with_prefix();
133 self
134 }
135
136 #[inline]
138 pub fn with_all_keys(mut self) -> Self {
139 self.key_range.with_all_keys();
140 self
141 }
142
143 #[inline]
145 pub const fn with_start_revision(mut self, revision: i64) -> Self {
146 self.req.start_revision = revision;
147 self
148 }
149
150 #[inline]
155 pub const fn with_progress_notify(mut self) -> Self {
156 self.req.progress_notify = true;
157 self
158 }
159
160 #[inline]
162 pub fn with_filters(mut self, filters: impl Into<Vec<WatchFilterType>>) -> Self {
163 self.req.filters = filters.into().into_iter().map(|f| f as i32).collect();
164 self
165 }
166
167 #[inline]
170 pub const fn with_prev_key(mut self) -> Self {
171 self.req.prev_kv = true;
172 self
173 }
174
175 #[inline]
181 pub const fn with_watch_id(mut self, watch_id: i64) -> Self {
182 self.req.watch_id = watch_id;
183 self
184 }
185
186 #[inline]
188 pub const fn with_fragment(mut self) -> Self {
189 self.req.fragment = true;
190 self
191 }
192}
193
194impl From<WatchOptions> for WatchCreateRequest {
195 #[inline]
196 fn from(mut options: WatchOptions) -> Self {
197 let (key, range_end) = options.key_range.build();
198 options.req.key = key;
199 options.req.range_end = range_end;
200 options.req
201 }
202}
203
204impl From<WatchOptions> for WatchRequest {
205 #[inline]
206 fn from(options: WatchOptions) -> Self {
207 Self {
208 request_union: Some(WatchRequestUnion::CreateRequest(options.into())),
209 }
210 }
211}
212
213impl From<WatchCancelRequest> for WatchRequest {
214 #[inline]
215 fn from(req: WatchCancelRequest) -> Self {
216 Self {
217 request_union: Some(WatchRequestUnion::CancelRequest(req)),
218 }
219 }
220}
221
222impl From<WatchProgressRequest> for WatchRequest {
223 #[inline]
224 fn from(req: WatchProgressRequest) -> Self {
225 Self {
226 request_union: Some(WatchRequestUnion::ProgressRequest(req)),
227 }
228 }
229}
230
231#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
233#[repr(i32)]
234pub enum WatchFilterType {
235 NoPut = 0,
237 NoDelete = 1,
239}
240
241#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
243#[derive(Debug, Clone)]
244#[repr(transparent)]
245pub struct WatchResponse(PbWatchResponse);
246
247impl WatchResponse {
248 #[inline]
250 const fn new(resp: PbWatchResponse) -> Self {
251 Self(resp)
252 }
253
254 #[inline]
256 pub fn header(&self) -> Option<&ResponseHeader> {
257 self.0.header.as_ref().map(From::from)
258 }
259
260 #[inline]
262 pub fn take_header(&mut self) -> Option<ResponseHeader> {
263 self.0.header.take().map(ResponseHeader::new)
264 }
265
266 #[inline]
268 pub const fn watch_id(&self) -> i64 {
269 self.0.watch_id
270 }
271
272 #[inline]
277 pub const fn created(&self) -> bool {
278 self.0.created
279 }
280
281 #[inline]
284 pub const fn canceled(&self) -> bool {
285 self.0.canceled
286 }
287
288 #[inline]
297 pub const fn compact_revision(&self) -> i64 {
298 self.0.compact_revision
299 }
300
301 #[inline]
303 pub fn cancel_reason(&self) -> &str {
304 &self.0.cancel_reason
305 }
306
307 #[inline]
309 pub fn events(&self) -> &[Event] {
310 unsafe { &*(self.0.events.as_slice() as *const _ as *const [Event]) }
311 }
312}
313
314#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
316#[derive(Debug, Clone)]
317#[repr(transparent)]
318pub struct Event(PbEvent);
319
320impl Event {
321 #[inline]
325 pub fn event_type(&self) -> EventType {
326 match self.0.r#type {
327 0 => EventType::Put,
328 1 => EventType::Delete,
329 i => panic!("unknown event {i}"),
330 }
331 }
332
333 #[inline]
339 pub fn kv(&self) -> Option<&KeyValue> {
340 self.0.kv.as_ref().map(From::from)
341 }
342
343 #[inline]
345 pub fn prev_kv(&self) -> Option<&KeyValue> {
346 self.0.prev_kv.as_ref().map(From::from)
347 }
348}
349
350#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
352#[derive(Debug)]
353pub struct WatchStream {
354 request_sender: WatchRequestSender,
355 response_stream: WatchResponseStream,
356}
357
358#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
365#[derive(Debug)]
366pub struct WatchRequestSender(Sender<WatchRequest>);
367
368#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
375#[derive(Debug)]
376pub struct WatchResponseStream(Streaming<PbWatchResponse>);
377
378impl WatchResponseStream {
379 #[inline]
383 pub async fn message(&mut self) -> Result<Option<WatchResponse>> {
384 self.0
385 .message()
386 .await
387 .map(|resp| resp.map(WatchResponse::new))
388 .map_err(From::from)
389 }
390}
391
392impl WatchStream {
393 #[inline]
395 const fn new(
396 request_sender: Sender<WatchRequest>,
397 response_stream: Streaming<PbWatchResponse>,
398 ) -> Self {
399 Self {
400 request_sender: WatchRequestSender(request_sender),
401 response_stream: WatchResponseStream(response_stream),
402 }
403 }
404
405 #[inline]
407 pub async fn watch(
408 &mut self,
409 key: impl Into<Vec<u8>>,
410 options: Option<WatchOptions>,
411 ) -> Result<()> {
412 self.request_sender.watch(key, options).await
413 }
414
415 #[inline]
417 pub async fn cancel(&mut self, watch_id: i64) -> Result<()> {
418 self.request_sender.cancel(watch_id).await
419 }
420
421 #[inline]
424 pub async fn request_progress(&mut self) -> Result<()> {
425 self.request_sender.request_progress().await
426 }
427
428 #[inline]
430 pub async fn message(&mut self) -> Result<Option<WatchResponse>> {
431 self.response_stream.message().await
432 }
433
434 pub fn split(self) -> (WatchRequestSender, WatchResponseStream) {
436 (self.request_sender, self.response_stream)
437 }
438}
439
440impl WatchRequestSender {
441 #[inline]
443 async fn send(&mut self, req: WatchRequest) -> Result<()> {
444 self.0
445 .send(req)
446 .await
447 .map_err(|e| Error::WatchError(e.to_string()))
448 }
449
450 #[inline]
454 pub async fn watch(
455 &mut self,
456 key: impl Into<Vec<u8>>,
457 options: Option<WatchOptions>,
458 ) -> Result<()> {
459 self.send(options.unwrap_or_default().with_key(key).into())
460 .await
461 }
462
463 #[inline]
468 pub async fn cancel(&mut self, watch_id: i64) -> Result<()> {
469 let req = WatchCancelRequest { watch_id };
470 self.send(req.into()).await
471 }
472
473 #[inline]
479 pub async fn request_progress(&mut self) -> Result<()> {
480 let req = WatchProgressRequest {};
481 self.send(req.into()).await
482 }
483}
484
485impl Stream for WatchResponseStream {
486 type Item = Result<WatchResponse>;
487
488 #[inline]
489 fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
490 Pin::new(&mut self.get_mut().0)
491 .poll_next(cx)
492 .map(|t| match t {
493 Some(Ok(resp)) => Some(Ok(WatchResponse::new(resp))),
494 Some(Err(e)) => Some(Err(From::from(e))),
495 None => None,
496 })
497 }
498}
499
500impl Stream for WatchStream {
501 type Item = Result<WatchResponse>;
502
503 #[inline]
504 fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
505 Pin::new(&mut self.get_mut().response_stream).poll_next(cx)
506 }
507}