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(PbMemberListRequest {}, member_list_impl)
104 .await
105 }
106
107 #[inline]
109 pub async fn member_promote(&mut self, id: u64) -> Result<MemberPromoteResponse> {
110 async fn member_promote_impl(
111 client: &mut Client,
112 options: MemberPromoteOptions,
113 ) -> Result<MemberPromoteResponse> {
114 let resp = client.member_promote(options).await?.into_inner();
115 Ok(MemberPromoteResponse::new(resp))
116 }
117 self.inner
118 .do_call(MemberPromoteOptions::new().with_id(id), member_promote_impl)
119 .await
120 }
121}
122
123#[derive(Debug, Default, Clone)]
125#[repr(transparent)]
126pub struct MemberAddOptions(PbMemberAddRequest);
127
128impl MemberAddOptions {
129 #[inline]
130 fn with_urls(mut self, urls: impl Into<Vec<String>>) -> Self {
131 self.0.peer_ur_ls = urls.into();
132 self
133 }
134
135 #[inline]
137 pub const fn new() -> Self {
138 Self(PbMemberAddRequest {
139 peer_ur_ls: Vec::new(),
140 is_learner: false,
141 })
142 }
143
144 #[inline]
146 pub const fn with_is_learner(mut self) -> Self {
147 self.0.is_learner = true;
148 self
149 }
150}
151
152impl From<MemberAddOptions> for PbMemberAddRequest {
153 #[inline]
154 fn from(options: MemberAddOptions) -> Self {
155 options.0
156 }
157}
158
159impl IntoRequest<PbMemberAddRequest> for MemberAddOptions {
160 #[inline]
161 fn into_request(self) -> Request<PbMemberAddRequest> {
162 Request::new(self.into())
163 }
164}
165
166#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
168#[derive(Debug, Default, Clone)]
169#[repr(transparent)]
170pub struct MemberAddResponse(PbMemberAddResponse);
171
172impl MemberAddResponse {
173 #[inline]
175 const fn new(resp: PbMemberAddResponse) -> Self {
176 Self(resp)
177 }
178
179 #[inline]
181 pub fn header(&self) -> Option<&ResponseHeader> {
182 self.0.header.as_ref().map(From::from)
183 }
184
185 #[inline]
187 pub fn member(&self) -> Option<&Member> {
188 self.0.member.as_ref().map(From::from)
189 }
190
191 #[inline]
193 pub fn take_header(&mut self) -> Option<ResponseHeader> {
194 self.0.header.take().map(ResponseHeader::new)
195 }
196
197 #[inline]
199 pub fn member_list(&self) -> &[Member] {
200 unsafe { &*(self.0.members.as_slice() as *const _ as *const [Member]) }
201 }
202}
203
204#[derive(Debug, Default, Clone)]
206pub struct MemberRemoveOptions(PbMemberRemoveRequest);
208
209impl MemberRemoveOptions {
210 #[inline]
212 fn with_id(mut self, id: u64) -> Self {
213 self.0.id = id;
214 self
215 }
216
217 #[inline]
219 pub const fn new() -> Self {
220 Self(PbMemberRemoveRequest { id: 0 })
221 }
222}
223
224impl From<MemberRemoveOptions> for PbMemberRemoveRequest {
225 #[inline]
226 fn from(options: MemberRemoveOptions) -> Self {
227 options.0
228 }
229}
230
231impl IntoRequest<PbMemberRemoveRequest> for MemberRemoveOptions {
232 #[inline]
233 fn into_request(self) -> Request<PbMemberRemoveRequest> {
234 Request::new(self.into())
235 }
236}
237
238#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
240#[derive(Debug, Default, Clone)]
241#[repr(transparent)]
242pub struct MemberRemoveResponse(PbMemberRemoveResponse);
243
244impl MemberRemoveResponse {
245 #[inline]
247 const fn new(resp: PbMemberRemoveResponse) -> Self {
248 Self(resp)
249 }
250
251 #[inline]
253 pub fn header(&self) -> Option<&ResponseHeader> {
254 self.0.header.as_ref().map(From::from)
255 }
256
257 #[inline]
259 pub fn take_header(&mut self) -> Option<ResponseHeader> {
260 self.0.header.take().map(ResponseHeader::new)
261 }
262
263 #[inline]
265 pub fn members(&self) -> &[Member] {
266 unsafe { &*(self.0.members.as_slice() as *const _ as *const [Member]) }
267 }
268}
269
270#[derive(Debug, Default, Clone)]
272pub struct MemberUpdateOptions(PbMemberUpdateRequest);
274
275impl MemberUpdateOptions {
276 #[inline]
277 fn with_option(mut self, id: u64, url: impl Into<Vec<String>>) -> Self {
278 self.0.id = id;
279 self.0.peer_ur_ls = url.into();
280 self
281 }
282
283 #[inline]
285 pub const fn new() -> Self {
286 Self(PbMemberUpdateRequest {
287 id: 0,
288 peer_ur_ls: Vec::new(),
289 })
290 }
291}
292
293impl From<MemberUpdateOptions> for PbMemberUpdateRequest {
294 #[inline]
295 fn from(options: MemberUpdateOptions) -> Self {
296 options.0
297 }
298}
299
300impl IntoRequest<PbMemberUpdateRequest> for MemberUpdateOptions {
301 #[inline]
302 fn into_request(self) -> Request<PbMemberUpdateRequest> {
303 Request::new(self.into())
304 }
305}
306
307#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
309#[derive(Debug, Default, Clone)]
310#[repr(transparent)]
311pub struct MemberUpdateResponse(PbMemberUpdateResponse);
312
313impl MemberUpdateResponse {
314 #[inline]
316 const fn new(resp: PbMemberUpdateResponse) -> Self {
317 Self(resp)
318 }
319
320 #[inline]
322 pub fn header(&self) -> Option<&ResponseHeader> {
323 self.0.header.as_ref().map(From::from)
324 }
325
326 #[inline]
328 pub fn take_header(&mut self) -> Option<ResponseHeader> {
329 self.0.header.take().map(ResponseHeader::new)
330 }
331
332 #[inline]
334 pub fn members(&self) -> &[Member] {
335 unsafe { &*(self.0.members.as_slice() as *const _ as *const [Member]) }
336 }
337}
338
339#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
341#[derive(Debug, Clone)]
342#[repr(transparent)]
343pub struct MemberListResponse(PbMemberListResponse);
344
345impl MemberListResponse {
346 #[inline]
348 const fn new(resp: PbMemberListResponse) -> Self {
349 Self(resp)
350 }
351
352 #[inline]
354 pub fn header(&self) -> Option<&ResponseHeader> {
355 self.0.header.as_ref().map(From::from)
356 }
357
358 #[inline]
360 pub fn take_header(&mut self) -> Option<ResponseHeader> {
361 self.0.header.take().map(ResponseHeader::new)
362 }
363
364 #[inline]
366 pub fn members(&self) -> &[Member] {
367 unsafe { &*(self.0.members.as_slice() as *const _ as *const [Member]) }
368 }
369}
370
371#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
373#[derive(Debug, Clone, PartialEq)]
374#[repr(transparent)]
375pub struct Member(PbMember);
376
377impl Member {
378 #[inline]
380 pub const fn id(&self) -> u64 {
381 self.0.id
382 }
383
384 #[inline]
386 pub fn name(&self) -> &str {
387 &self.0.name
388 }
389
390 #[inline]
392 pub fn peer_urls(&self) -> &[String] {
393 &self.0.peer_ur_ls
394 }
395
396 #[inline]
398 pub fn client_urls(&self) -> &[String] {
399 &self.0.client_ur_ls
400 }
401
402 #[inline]
404 pub const fn is_learner(&self) -> bool {
405 self.0.is_learner
406 }
407}
408
409impl From<&PbMember> for &Member {
410 #[inline]
411 fn from(src: &PbMember) -> Self {
412 unsafe { &*(src as *const _ as *const Member) }
413 }
414}
415
416#[derive(Debug, Default, Clone)]
418#[repr(transparent)]
419pub struct MemberPromoteOptions(PbMemberPromoteRequest);
420
421impl MemberPromoteOptions {
422 #[inline]
424 fn with_id(mut self, id: u64) -> Self {
425 self.0.id = id;
426 self
427 }
428
429 #[inline]
431 pub const fn new() -> Self {
432 Self(PbMemberPromoteRequest { id: 0 })
433 }
434}
435
436impl From<MemberPromoteOptions> for PbMemberPromoteRequest {
437 #[inline]
438 fn from(options: MemberPromoteOptions) -> Self {
439 options.0
440 }
441}
442
443impl IntoRequest<PbMemberPromoteRequest> for MemberPromoteOptions {
444 #[inline]
445 fn into_request(self) -> Request<PbMemberPromoteRequest> {
446 Request::new(self.into())
447 }
448}
449
450#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
452#[derive(Debug, Default, Clone)]
453#[repr(transparent)]
454pub struct MemberPromoteResponse(PbMemberPromoteResponse);
455
456impl MemberPromoteResponse {
457 #[inline]
459 const fn new(resp: PbMemberPromoteResponse) -> Self {
460 Self(resp)
461 }
462
463 #[inline]
465 pub fn header(&self) -> Option<&ResponseHeader> {
466 self.0.header.as_ref().map(From::from)
467 }
468
469 #[inline]
471 pub fn take_header(&mut self) -> Option<ResponseHeader> {
472 self.0.header.take().map(ResponseHeader::new)
473 }
474
475 #[inline]
477 pub fn members(&self) -> &[Member] {
478 unsafe { &*(self.0.members.as_slice() as *const _ as *const [Member]) }
479 }
480}