etcd_client/rpc/
cluster.rs1use crate::caller::{ClientCaller, ClientCallerBuilder};
4use crate::error::Result;
5use crate::intercept::InterceptedChannel;
6use crate::rpc::pb::etcdserverpb::cluster_client::ClusterClient as PbClusterClient;
7use crate::rpc::pb::etcdserverpb::{
8 Member as PbMember, MemberAddRequest as PbMemberAddRequest,
9 MemberAddResponse as PbMemberAddResponse, MemberListRequest as PbMemberListRequest,
10 MemberListResponse as PbMemberListResponse, MemberPromoteRequest as PbMemberPromoteRequest,
11 MemberPromoteResponse as PbMemberPromoteResponse, MemberRemoveRequest as PbMemberRemoveRequest,
12 MemberRemoveResponse as PbMemberRemoveResponse, MemberUpdateRequest as PbMemberUpdateRequest,
13 MemberUpdateResponse as PbMemberUpdateResponse,
14};
15use crate::rpc::ResponseHeader;
16use tonic::{IntoRequest, Request};
17
18type Client = PbClusterClient<InterceptedChannel>;
19
20#[repr(transparent)]
22#[derive(Clone)]
23pub struct ClusterClient {
24 inner: ClientCaller<Client>,
25}
26
27impl ClusterClient {
28 #[inline]
30 pub(crate) fn new(builder: ClientCallerBuilder) -> Self {
31 Self {
32 inner: builder.build(Client::new),
33 }
34 }
35
36 #[inline]
38 pub async fn member_add(
39 &mut self,
40 urls: impl Into<Vec<String>>,
41 options: Option<MemberAddOptions>,
42 ) -> Result<MemberAddResponse> {
43 async fn member_add_impl(
44 client: &mut Client,
45 options: MemberAddOptions,
46 ) -> Result<MemberAddResponse> {
47 let resp = client.member_add(options).await?.into_inner();
48 Ok(MemberAddResponse::new(resp))
49 }
50 self.inner
51 .do_call(options.unwrap_or_default().with_urls(urls), member_add_impl)
52 .await
53 }
54
55 #[inline]
57 pub async fn member_remove(&mut self, id: u64) -> Result<MemberRemoveResponse> {
58 async fn member_remove_impl(
59 client: &mut Client,
60 options: MemberRemoveOptions,
61 ) -> Result<MemberRemoveResponse> {
62 let resp = client.member_remove(options).await?.into_inner();
63 Ok(MemberRemoveResponse::new(resp))
64 }
65 self.inner
66 .do_call(MemberRemoveOptions::new().with_id(id), member_remove_impl)
67 .await
68 }
69
70 #[inline]
72 pub async fn member_update(
73 &mut self,
74 id: u64,
75 url: impl Into<Vec<String>>,
76 ) -> Result<MemberUpdateResponse> {
77 async fn member_update_impl(
78 client: &mut Client,
79 options: MemberUpdateOptions,
80 ) -> Result<MemberUpdateResponse> {
81 let resp = client.member_update(options).await?.into_inner();
82 Ok(MemberUpdateResponse::new(resp))
83 }
84 self.inner
85 .do_call(
86 MemberUpdateOptions::new().with_option(id, url),
87 member_update_impl,
88 )
89 .await
90 }
91
92 #[inline]
94 pub async fn member_list(&mut self) -> Result<MemberListResponse> {
95 async fn member_list_impl(
96 client: &mut Client,
97 options: PbMemberListRequest,
98 ) -> Result<MemberListResponse> {
99 let resp = client.member_list(options).await?.into_inner();
100 Ok(MemberListResponse::new(resp))
101 }
102 self.inner
103 .do_call(
104 PbMemberListRequest {
105 linearizable: false,
106 },
107 member_list_impl,
108 )
109 .await
110 }
111
112 #[inline]
114 pub async fn member_promote(&mut self, id: u64) -> Result<MemberPromoteResponse> {
115 async fn member_promote_impl(
116 client: &mut Client,
117 options: MemberPromoteOptions,
118 ) -> Result<MemberPromoteResponse> {
119 let resp = client.member_promote(options).await?.into_inner();
120 Ok(MemberPromoteResponse::new(resp))
121 }
122 self.inner
123 .do_call(MemberPromoteOptions::new().with_id(id), member_promote_impl)
124 .await
125 }
126}
127
128#[derive(Debug, Default, Clone)]
130#[repr(transparent)]
131pub struct MemberAddOptions(PbMemberAddRequest);
132
133impl MemberAddOptions {
134 #[inline]
135 fn with_urls(mut self, urls: impl Into<Vec<String>>) -> Self {
136 self.0.peer_ur_ls = urls.into();
137 self
138 }
139
140 #[inline]
142 pub const fn new() -> Self {
143 Self(PbMemberAddRequest {
144 peer_ur_ls: Vec::new(),
145 is_learner: false,
146 })
147 }
148
149 #[inline]
151 pub const fn with_is_learner(mut self) -> Self {
152 self.0.is_learner = true;
153 self
154 }
155}
156
157impl From<MemberAddOptions> for PbMemberAddRequest {
158 #[inline]
159 fn from(options: MemberAddOptions) -> Self {
160 options.0
161 }
162}
163
164impl IntoRequest<PbMemberAddRequest> for MemberAddOptions {
165 #[inline]
166 fn into_request(self) -> Request<PbMemberAddRequest> {
167 Request::new(self.into())
168 }
169}
170
171#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
173#[derive(Debug, Default, Clone)]
174#[repr(transparent)]
175pub struct MemberAddResponse(PbMemberAddResponse);
176
177impl MemberAddResponse {
178 #[inline]
180 const fn new(resp: PbMemberAddResponse) -> Self {
181 Self(resp)
182 }
183
184 #[inline]
186 pub fn header(&self) -> Option<&ResponseHeader> {
187 self.0.header.as_ref().map(From::from)
188 }
189
190 #[inline]
192 pub fn member(&self) -> Option<&Member> {
193 self.0.member.as_ref().map(From::from)
194 }
195
196 #[inline]
198 pub fn take_header(&mut self) -> Option<ResponseHeader> {
199 self.0.header.take().map(ResponseHeader::new)
200 }
201
202 #[inline]
204 pub fn member_list(&self) -> &[Member] {
205 unsafe { &*(self.0.members.as_slice() as *const _ as *const [Member]) }
206 }
207}
208
209#[derive(Debug, Default, Clone)]
211pub struct MemberRemoveOptions(PbMemberRemoveRequest);
213
214impl MemberRemoveOptions {
215 #[inline]
217 fn with_id(mut self, id: u64) -> Self {
218 self.0.id = id;
219 self
220 }
221
222 #[inline]
224 pub const fn new() -> Self {
225 Self(PbMemberRemoveRequest { id: 0 })
226 }
227}
228
229impl From<MemberRemoveOptions> for PbMemberRemoveRequest {
230 #[inline]
231 fn from(options: MemberRemoveOptions) -> Self {
232 options.0
233 }
234}
235
236impl IntoRequest<PbMemberRemoveRequest> for MemberRemoveOptions {
237 #[inline]
238 fn into_request(self) -> Request<PbMemberRemoveRequest> {
239 Request::new(self.into())
240 }
241}
242
243#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
245#[derive(Debug, Default, Clone)]
246#[repr(transparent)]
247pub struct MemberRemoveResponse(PbMemberRemoveResponse);
248
249impl MemberRemoveResponse {
250 #[inline]
252 const fn new(resp: PbMemberRemoveResponse) -> Self {
253 Self(resp)
254 }
255
256 #[inline]
258 pub fn header(&self) -> Option<&ResponseHeader> {
259 self.0.header.as_ref().map(From::from)
260 }
261
262 #[inline]
264 pub fn take_header(&mut self) -> Option<ResponseHeader> {
265 self.0.header.take().map(ResponseHeader::new)
266 }
267
268 #[inline]
270 pub fn members(&self) -> &[Member] {
271 unsafe { &*(self.0.members.as_slice() as *const _ as *const [Member]) }
272 }
273}
274
275#[derive(Debug, Default, Clone)]
277pub struct MemberUpdateOptions(PbMemberUpdateRequest);
279
280impl MemberUpdateOptions {
281 #[inline]
282 fn with_option(mut self, id: u64, url: impl Into<Vec<String>>) -> Self {
283 self.0.id = id;
284 self.0.peer_ur_ls = url.into();
285 self
286 }
287
288 #[inline]
290 pub const fn new() -> Self {
291 Self(PbMemberUpdateRequest {
292 id: 0,
293 peer_ur_ls: Vec::new(),
294 })
295 }
296}
297
298impl From<MemberUpdateOptions> for PbMemberUpdateRequest {
299 #[inline]
300 fn from(options: MemberUpdateOptions) -> Self {
301 options.0
302 }
303}
304
305impl IntoRequest<PbMemberUpdateRequest> for MemberUpdateOptions {
306 #[inline]
307 fn into_request(self) -> Request<PbMemberUpdateRequest> {
308 Request::new(self.into())
309 }
310}
311
312#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
314#[derive(Debug, Default, Clone)]
315#[repr(transparent)]
316pub struct MemberUpdateResponse(PbMemberUpdateResponse);
317
318impl MemberUpdateResponse {
319 #[inline]
321 const fn new(resp: PbMemberUpdateResponse) -> Self {
322 Self(resp)
323 }
324
325 #[inline]
327 pub fn header(&self) -> Option<&ResponseHeader> {
328 self.0.header.as_ref().map(From::from)
329 }
330
331 #[inline]
333 pub fn take_header(&mut self) -> Option<ResponseHeader> {
334 self.0.header.take().map(ResponseHeader::new)
335 }
336
337 #[inline]
339 pub fn members(&self) -> &[Member] {
340 unsafe { &*(self.0.members.as_slice() as *const _ as *const [Member]) }
341 }
342}
343
344#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
346#[derive(Debug, Clone)]
347#[repr(transparent)]
348pub struct MemberListResponse(PbMemberListResponse);
349
350impl MemberListResponse {
351 #[inline]
353 const fn new(resp: PbMemberListResponse) -> Self {
354 Self(resp)
355 }
356
357 #[inline]
359 pub fn header(&self) -> Option<&ResponseHeader> {
360 self.0.header.as_ref().map(From::from)
361 }
362
363 #[inline]
365 pub fn take_header(&mut self) -> Option<ResponseHeader> {
366 self.0.header.take().map(ResponseHeader::new)
367 }
368
369 #[inline]
371 pub fn members(&self) -> &[Member] {
372 unsafe { &*(self.0.members.as_slice() as *const _ as *const [Member]) }
373 }
374}
375
376#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
378#[derive(Debug, Clone, PartialEq)]
379#[repr(transparent)]
380pub struct Member(PbMember);
381
382impl Member {
383 #[inline]
385 pub const fn id(&self) -> u64 {
386 self.0.id
387 }
388
389 #[inline]
391 pub fn name(&self) -> &str {
392 &self.0.name
393 }
394
395 #[inline]
397 pub fn peer_urls(&self) -> &[String] {
398 &self.0.peer_ur_ls
399 }
400
401 #[inline]
403 pub fn client_urls(&self) -> &[String] {
404 &self.0.client_ur_ls
405 }
406
407 #[inline]
409 pub const fn is_learner(&self) -> bool {
410 self.0.is_learner
411 }
412}
413
414impl From<&PbMember> for &Member {
415 #[inline]
416 fn from(src: &PbMember) -> Self {
417 unsafe { &*(src as *const _ as *const Member) }
418 }
419}
420
421#[derive(Debug, Default, Clone)]
423#[repr(transparent)]
424pub struct MemberPromoteOptions(PbMemberPromoteRequest);
425
426impl MemberPromoteOptions {
427 #[inline]
429 fn with_id(mut self, id: u64) -> Self {
430 self.0.id = id;
431 self
432 }
433
434 #[inline]
436 pub const fn new() -> Self {
437 Self(PbMemberPromoteRequest { id: 0 })
438 }
439}
440
441impl From<MemberPromoteOptions> for PbMemberPromoteRequest {
442 #[inline]
443 fn from(options: MemberPromoteOptions) -> Self {
444 options.0
445 }
446}
447
448impl IntoRequest<PbMemberPromoteRequest> for MemberPromoteOptions {
449 #[inline]
450 fn into_request(self) -> Request<PbMemberPromoteRequest> {
451 Request::new(self.into())
452 }
453}
454
455#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
457#[derive(Debug, Default, Clone)]
458#[repr(transparent)]
459pub struct MemberPromoteResponse(PbMemberPromoteResponse);
460
461impl MemberPromoteResponse {
462 #[inline]
464 const fn new(resp: PbMemberPromoteResponse) -> Self {
465 Self(resp)
466 }
467
468 #[inline]
470 pub fn header(&self) -> Option<&ResponseHeader> {
471 self.0.header.as_ref().map(From::from)
472 }
473
474 #[inline]
476 pub fn take_header(&mut self) -> Option<ResponseHeader> {
477 self.0.header.take().map(ResponseHeader::new)
478 }
479
480 #[inline]
482 pub fn members(&self) -> &[Member] {
483 unsafe { &*(self.0.members.as_slice() as *const _ as *const [Member]) }
484 }
485}