etcd_client/rpc/
cluster.rs1use crate::error::Result;
4use crate::intercept::InterceptedChannel;
5use crate::rpc::pb::etcdserverpb::cluster_client::ClusterClient as PbClusterClient;
6use crate::rpc::pb::etcdserverpb::{
7 Member as PbMember, MemberAddRequest as PbMemberAddRequest,
8 MemberAddResponse as PbMemberAddResponse, MemberListRequest as PbMemberListRequest,
9 MemberListResponse as PbMemberListResponse, MemberPromoteRequest as PbMemberPromoteRequest,
10 MemberPromoteResponse as PbMemberPromoteResponse, MemberRemoveRequest as PbMemberRemoveRequest,
11 MemberRemoveResponse as PbMemberRemoveResponse, MemberUpdateRequest as PbMemberUpdateRequest,
12 MemberUpdateResponse as PbMemberUpdateResponse,
13};
14use crate::rpc::ResponseHeader;
15use tonic::{IntoRequest, Request};
16
17#[repr(transparent)]
19#[derive(Clone)]
20pub struct ClusterClient {
21 inner: PbClusterClient<InterceptedChannel>,
22}
23
24impl ClusterClient {
25 #[inline]
27 pub(crate) fn new(channel: InterceptedChannel) -> Self {
28 let inner = PbClusterClient::new(channel);
29 Self { inner }
30 }
31
32 #[inline]
34 pub async fn member_add(
35 &mut self,
36 urls: impl Into<Vec<String>>,
37 options: Option<MemberAddOptions>,
38 ) -> Result<MemberAddResponse> {
39 let resp = self
40 .inner
41 .member_add(options.unwrap_or_default().with_urls(urls))
42 .await?
43 .into_inner();
44
45 Ok(MemberAddResponse::new(resp))
46 }
47
48 #[inline]
50 pub async fn member_remove(&mut self, id: u64) -> Result<MemberRemoveResponse> {
51 let resp = self
52 .inner
53 .member_remove(MemberRemoveOptions::new().with_id(id))
54 .await?
55 .into_inner();
56 Ok(MemberRemoveResponse::new(resp))
57 }
58
59 #[inline]
61 pub async fn member_update(
62 &mut self,
63 id: u64,
64 url: impl Into<Vec<String>>,
65 ) -> Result<MemberUpdateResponse> {
66 let resp = self
67 .inner
68 .member_update(MemberUpdateOptions::new().with_option(id, url))
69 .await?
70 .into_inner();
71 Ok(MemberUpdateResponse::new(resp))
72 }
73
74 #[inline]
76 pub async fn member_list(&mut self) -> Result<MemberListResponse> {
77 let resp = self
78 .inner
79 .member_list(PbMemberListRequest {})
80 .await?
81 .into_inner();
82 Ok(MemberListResponse::new(resp))
83 }
84
85 #[inline]
87 pub async fn member_promote(&mut self, id: u64) -> Result<MemberPromoteResponse> {
88 let resp = self
89 .inner
90 .member_promote(MemberPromoteOptions::new().with_id(id))
91 .await?
92 .into_inner();
93 Ok(MemberPromoteResponse::new(resp))
94 }
95}
96
97#[derive(Debug, Default, Clone)]
99#[repr(transparent)]
100pub struct MemberAddOptions(PbMemberAddRequest);
101
102impl MemberAddOptions {
103 #[inline]
104 fn with_urls(mut self, urls: impl Into<Vec<String>>) -> Self {
105 self.0.peer_ur_ls = urls.into();
106 self
107 }
108
109 #[inline]
111 pub const fn new() -> Self {
112 Self(PbMemberAddRequest {
113 peer_ur_ls: Vec::new(),
114 is_learner: false,
115 })
116 }
117
118 #[inline]
120 pub const fn with_is_learner(mut self) -> Self {
121 self.0.is_learner = true;
122 self
123 }
124}
125
126impl From<MemberAddOptions> for PbMemberAddRequest {
127 #[inline]
128 fn from(options: MemberAddOptions) -> Self {
129 options.0
130 }
131}
132
133impl IntoRequest<PbMemberAddRequest> for MemberAddOptions {
134 #[inline]
135 fn into_request(self) -> Request<PbMemberAddRequest> {
136 Request::new(self.into())
137 }
138}
139
140#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
142#[derive(Debug, Default, Clone)]
143#[repr(transparent)]
144pub struct MemberAddResponse(PbMemberAddResponse);
145
146impl MemberAddResponse {
147 #[inline]
149 const fn new(resp: PbMemberAddResponse) -> Self {
150 Self(resp)
151 }
152
153 #[inline]
155 pub fn header(&self) -> Option<&ResponseHeader> {
156 self.0.header.as_ref().map(From::from)
157 }
158
159 #[inline]
161 pub fn member(&self) -> Option<&Member> {
162 self.0.member.as_ref().map(From::from)
163 }
164
165 #[inline]
167 pub fn take_header(&mut self) -> Option<ResponseHeader> {
168 self.0.header.take().map(ResponseHeader::new)
169 }
170
171 #[inline]
173 pub fn member_list(&self) -> &[Member] {
174 unsafe { &*(self.0.members.as_slice() as *const _ as *const [Member]) }
175 }
176}
177
178#[derive(Debug, Default, Clone)]
180pub struct MemberRemoveOptions(PbMemberRemoveRequest);
182
183impl MemberRemoveOptions {
184 #[inline]
186 fn with_id(mut self, id: u64) -> Self {
187 self.0.id = id;
188 self
189 }
190
191 #[inline]
193 pub const fn new() -> Self {
194 Self(PbMemberRemoveRequest { id: 0 })
195 }
196}
197
198impl From<MemberRemoveOptions> for PbMemberRemoveRequest {
199 #[inline]
200 fn from(options: MemberRemoveOptions) -> Self {
201 options.0
202 }
203}
204
205impl IntoRequest<PbMemberRemoveRequest> for MemberRemoveOptions {
206 #[inline]
207 fn into_request(self) -> Request<PbMemberRemoveRequest> {
208 Request::new(self.into())
209 }
210}
211
212#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
214#[derive(Debug, Default, Clone)]
215#[repr(transparent)]
216pub struct MemberRemoveResponse(PbMemberRemoveResponse);
217
218impl MemberRemoveResponse {
219 #[inline]
221 const fn new(resp: PbMemberRemoveResponse) -> Self {
222 Self(resp)
223 }
224
225 #[inline]
227 pub fn header(&self) -> Option<&ResponseHeader> {
228 self.0.header.as_ref().map(From::from)
229 }
230
231 #[inline]
233 pub fn take_header(&mut self) -> Option<ResponseHeader> {
234 self.0.header.take().map(ResponseHeader::new)
235 }
236
237 #[inline]
239 pub fn members(&self) -> &[Member] {
240 unsafe { &*(self.0.members.as_slice() as *const _ as *const [Member]) }
241 }
242}
243
244#[derive(Debug, Default, Clone)]
246pub struct MemberUpdateOptions(PbMemberUpdateRequest);
248
249impl MemberUpdateOptions {
250 #[inline]
251 fn with_option(mut self, id: u64, url: impl Into<Vec<String>>) -> Self {
252 self.0.id = id;
253 self.0.peer_ur_ls = url.into();
254 self
255 }
256
257 #[inline]
259 pub const fn new() -> Self {
260 Self(PbMemberUpdateRequest {
261 id: 0,
262 peer_ur_ls: Vec::new(),
263 })
264 }
265}
266
267impl From<MemberUpdateOptions> for PbMemberUpdateRequest {
268 #[inline]
269 fn from(options: MemberUpdateOptions) -> Self {
270 options.0
271 }
272}
273
274impl IntoRequest<PbMemberUpdateRequest> for MemberUpdateOptions {
275 #[inline]
276 fn into_request(self) -> Request<PbMemberUpdateRequest> {
277 Request::new(self.into())
278 }
279}
280
281#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
283#[derive(Debug, Default, Clone)]
284#[repr(transparent)]
285pub struct MemberUpdateResponse(PbMemberUpdateResponse);
286
287impl MemberUpdateResponse {
288 #[inline]
290 const fn new(resp: PbMemberUpdateResponse) -> Self {
291 Self(resp)
292 }
293
294 #[inline]
296 pub fn header(&self) -> Option<&ResponseHeader> {
297 self.0.header.as_ref().map(From::from)
298 }
299
300 #[inline]
302 pub fn take_header(&mut self) -> Option<ResponseHeader> {
303 self.0.header.take().map(ResponseHeader::new)
304 }
305
306 #[inline]
308 pub fn members(&self) -> &[Member] {
309 unsafe { &*(self.0.members.as_slice() as *const _ as *const [Member]) }
310 }
311}
312
313#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
315#[derive(Debug, Clone)]
316#[repr(transparent)]
317pub struct MemberListResponse(PbMemberListResponse);
318
319impl MemberListResponse {
320 #[inline]
322 const fn new(resp: PbMemberListResponse) -> Self {
323 Self(resp)
324 }
325
326 #[inline]
328 pub fn header(&self) -> Option<&ResponseHeader> {
329 self.0.header.as_ref().map(From::from)
330 }
331
332 #[inline]
334 pub fn take_header(&mut self) -> Option<ResponseHeader> {
335 self.0.header.take().map(ResponseHeader::new)
336 }
337
338 #[inline]
340 pub fn members(&self) -> &[Member] {
341 unsafe { &*(self.0.members.as_slice() as *const _ as *const [Member]) }
342 }
343}
344
345#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
347#[derive(Debug, Clone, PartialEq)]
348#[repr(transparent)]
349pub struct Member(PbMember);
350
351impl Member {
352 #[inline]
354 pub const fn id(&self) -> u64 {
355 self.0.id
356 }
357
358 #[inline]
360 pub fn name(&self) -> &str {
361 &self.0.name
362 }
363
364 #[inline]
366 pub fn peer_urls(&self) -> &[String] {
367 &self.0.peer_ur_ls
368 }
369
370 #[inline]
372 pub fn client_urls(&self) -> &[String] {
373 &self.0.client_ur_ls
374 }
375
376 #[inline]
378 pub const fn is_learner(&self) -> bool {
379 self.0.is_learner
380 }
381}
382
383impl From<&PbMember> for &Member {
384 #[inline]
385 fn from(src: &PbMember) -> Self {
386 unsafe { &*(src as *const _ as *const Member) }
387 }
388}
389
390#[derive(Debug, Default, Clone)]
392#[repr(transparent)]
393pub struct MemberPromoteOptions(PbMemberPromoteRequest);
394
395impl MemberPromoteOptions {
396 #[inline]
398 fn with_id(mut self, id: u64) -> Self {
399 self.0.id = id;
400 self
401 }
402
403 #[inline]
405 pub const fn new() -> Self {
406 Self(PbMemberPromoteRequest { id: 0 })
407 }
408}
409
410impl From<MemberPromoteOptions> for PbMemberPromoteRequest {
411 #[inline]
412 fn from(options: MemberPromoteOptions) -> Self {
413 options.0
414 }
415}
416
417impl IntoRequest<PbMemberPromoteRequest> for MemberPromoteOptions {
418 #[inline]
419 fn into_request(self) -> Request<PbMemberPromoteRequest> {
420 Request::new(self.into())
421 }
422}
423
424#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
426#[derive(Debug, Default, Clone)]
427#[repr(transparent)]
428pub struct MemberPromoteResponse(PbMemberPromoteResponse);
429
430impl MemberPromoteResponse {
431 #[inline]
433 const fn new(resp: PbMemberPromoteResponse) -> Self {
434 Self(resp)
435 }
436
437 #[inline]
439 pub fn header(&self) -> Option<&ResponseHeader> {
440 self.0.header.as_ref().map(From::from)
441 }
442
443 #[inline]
445 pub fn take_header(&mut self) -> Option<ResponseHeader> {
446 self.0.header.take().map(ResponseHeader::new)
447 }
448
449 #[inline]
451 pub fn members(&self) -> &[Member] {
452 unsafe { &*(self.0.members.as_slice() as *const _ as *const [Member]) }
453 }
454}