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]
285 pub const fn canceled(&self) -> bool {
286 self.0.canceled
287 }
288
289 #[inline]
298 pub const fn compact_revision(&self) -> i64 {
299 self.0.compact_revision
300 }
301
302 #[inline]
304 pub fn cancel_reason(&self) -> &str {
305 &self.0.cancel_reason
306 }
307
308 #[inline]
310 pub fn events(&self) -> &[Event] {
311 unsafe { &*(self.0.events.as_slice() as *const _ as *const [Event]) }
312 }
313}
314
315#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
317#[derive(Debug, Clone)]
318#[repr(transparent)]
319pub struct Event(PbEvent);
320
321impl Event {
322 #[inline]
326 pub fn event_type(&self) -> EventType {
327 match self.0.r#type {
328 0 => EventType::Put,
329 1 => EventType::Delete,
330 i => panic!("unknown event {i}"),
331 }
332 }
333
334 #[inline]
340 pub fn kv(&self) -> Option<&KeyValue> {
341 self.0.kv.as_ref().map(From::from)
342 }
343
344 #[inline]
346 pub fn prev_kv(&self) -> Option<&KeyValue> {
347 self.0.prev_kv.as_ref().map(From::from)
348 }
349}
350
351#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
353#[derive(Debug)]
354pub struct WatchStream {
355 request_sender: WatchRequestSender,
356 response_stream: WatchResponseStream,
357}
358
359#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
366#[derive(Debug)]
367pub struct WatchRequestSender(Sender<WatchRequest>);
368
369#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
376#[derive(Debug)]
377pub struct WatchResponseStream(Streaming<PbWatchResponse>);
378
379impl WatchResponseStream {
380 #[inline]
384 pub async fn message(&mut self) -> Result<Option<WatchResponse>> {
385 self.0
386 .message()
387 .await
388 .map(|resp| resp.map(WatchResponse::new))
389 .map_err(From::from)
390 }
391}
392
393impl WatchStream {
394 #[inline]
396 const fn new(
397 request_sender: Sender<WatchRequest>,
398 response_stream: Streaming<PbWatchResponse>,
399 ) -> Self {
400 Self {
401 request_sender: WatchRequestSender(request_sender),
402 response_stream: WatchResponseStream(response_stream),
403 }
404 }
405
406 #[inline]
408 pub async fn watch(
409 &mut self,
410 key: impl Into<Vec<u8>>,
411 options: Option<WatchOptions>,
412 ) -> Result<()> {
413 self.request_sender.watch(key, options).await
414 }
415
416 #[inline]
418 pub async fn cancel(&mut self, watch_id: i64) -> Result<()> {
419 self.request_sender.cancel(watch_id).await
420 }
421
422 #[inline]
425 pub async fn request_progress(&mut self) -> Result<()> {
426 self.request_sender.request_progress().await
427 }
428
429 #[inline]
431 pub async fn message(&mut self) -> Result<Option<WatchResponse>> {
432 self.response_stream.message().await
433 }
434
435 pub fn split(self) -> (WatchRequestSender, WatchResponseStream) {
437 (self.request_sender, self.response_stream)
438 }
439}
440
441impl WatchRequestSender {
442 #[inline]
444 async fn send(&mut self, req: WatchRequest) -> Result<()> {
445 self.0
446 .send(req)
447 .await
448 .map_err(|e| Error::WatchError(e.to_string()))
449 }
450
451 #[inline]
455 pub async fn watch(
456 &mut self,
457 key: impl Into<Vec<u8>>,
458 options: Option<WatchOptions>,
459 ) -> Result<()> {
460 self.send(options.unwrap_or_default().with_key(key).into())
461 .await
462 }
463
464 #[inline]
469 pub async fn cancel(&mut self, watch_id: i64) -> Result<()> {
470 let req = WatchCancelRequest { watch_id };
471 self.send(req.into()).await
472 }
473
474 #[inline]
480 pub async fn request_progress(&mut self) -> Result<()> {
481 let req = WatchProgressRequest {};
482 self.send(req.into()).await
483 }
484}
485
486impl Stream for WatchResponseStream {
487 type Item = Result<WatchResponse>;
488
489 #[inline]
490 fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
491 Pin::new(&mut self.get_mut().0)
492 .poll_next(cx)
493 .map(|t| match t {
494 Some(Ok(resp)) => Some(Ok(WatchResponse::new(resp))),
495 Some(Err(e)) => Some(Err(From::from(e))),
496 None => None,
497 })
498 }
499}
500
501impl Stream for WatchStream {
502 type Item = Result<WatchResponse>;
503
504 #[inline]
505 fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
506 Pin::new(&mut self.get_mut().response_stream).poll_next(cx)
507 }
508}