etcd_client/rpc/
cluster.rs1use crate::auth::AuthService;
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 http::HeaderValue;
17use std::sync::RwLock;
18use std::{string::String, sync::Arc};
19use tonic::{IntoRequest, Request};
20
21#[repr(transparent)]
23#[derive(Clone)]
24pub struct ClusterClient {
25 inner: PbClusterClient<AuthService<InterceptedChannel>>,
26}
27
28impl ClusterClient {
29 #[inline]
31 pub(crate) fn new(
32 channel: InterceptedChannel,
33 auth_token: Arc<RwLock<Option<HeaderValue>>>,
34 ) -> Self {
35 let inner = PbClusterClient::new(AuthService::new(channel, auth_token));
36 Self { inner }
37 }
38
39 #[inline]
41 pub async fn member_add(
42 &mut self,
43 urls: impl Into<Vec<String>>,
44 options: Option<MemberAddOptions>,
45 ) -> Result<MemberAddResponse> {
46 let resp = self
47 .inner
48 .member_add(options.unwrap_or_default().with_urls(urls))
49 .await?
50 .into_inner();
51
52 Ok(MemberAddResponse::new(resp))
53 }
54
55 #[inline]
57 pub async fn member_remove(&mut self, id: u64) -> Result<MemberRemoveResponse> {
58 let resp = self
59 .inner
60 .member_remove(MemberRemoveOptions::new().with_id(id))
61 .await?
62 .into_inner();
63 Ok(MemberRemoveResponse::new(resp))
64 }
65
66 #[inline]
68 pub async fn member_update(
69 &mut self,
70 id: u64,
71 url: impl Into<Vec<String>>,
72 ) -> Result<MemberUpdateResponse> {
73 let resp = self
74 .inner
75 .member_update(MemberUpdateOptions::new().with_option(id, url))
76 .await?
77 .into_inner();
78 Ok(MemberUpdateResponse::new(resp))
79 }
80
81 #[inline]
83 pub async fn member_list(&mut self) -> Result<MemberListResponse> {
84 let resp = self
85 .inner
86 .member_list(PbMemberListRequest {})
87 .await?
88 .into_inner();
89 Ok(MemberListResponse::new(resp))
90 }
91
92 #[inline]
94 pub async fn member_promote(&mut self, id: u64) -> Result<MemberPromoteResponse> {
95 let resp = self
96 .inner
97 .member_promote(MemberPromoteOptions::new().with_id(id))
98 .await?
99 .into_inner();
100 Ok(MemberPromoteResponse::new(resp))
101 }
102}
103
104#[derive(Debug, Default, Clone)]
106#[repr(transparent)]
107pub struct MemberAddOptions(PbMemberAddRequest);
108
109impl MemberAddOptions {
110 #[inline]
111 fn with_urls(mut self, urls: impl Into<Vec<String>>) -> Self {
112 self.0.peer_ur_ls = urls.into();
113 self
114 }
115
116 #[inline]
118 pub const fn new() -> Self {
119 Self(PbMemberAddRequest {
120 peer_ur_ls: Vec::new(),
121 is_learner: false,
122 })
123 }
124
125 #[inline]
127 pub const fn with_is_learner(mut self) -> Self {
128 self.0.is_learner = true;
129 self
130 }
131}
132
133impl From<MemberAddOptions> for PbMemberAddRequest {
134 #[inline]
135 fn from(options: MemberAddOptions) -> Self {
136 options.0
137 }
138}
139
140impl IntoRequest<PbMemberAddRequest> for MemberAddOptions {
141 #[inline]
142 fn into_request(self) -> Request<PbMemberAddRequest> {
143 Request::new(self.into())
144 }
145}
146
147#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
149#[derive(Debug, Default, Clone)]
150#[repr(transparent)]
151pub struct MemberAddResponse(PbMemberAddResponse);
152
153impl MemberAddResponse {
154 #[inline]
156 const fn new(resp: PbMemberAddResponse) -> Self {
157 Self(resp)
158 }
159
160 #[inline]
162 pub fn header(&self) -> Option<&ResponseHeader> {
163 self.0.header.as_ref().map(From::from)
164 }
165
166 #[inline]
168 pub fn member(&self) -> Option<&Member> {
169 self.0.member.as_ref().map(From::from)
170 }
171
172 #[inline]
174 pub fn take_header(&mut self) -> Option<ResponseHeader> {
175 self.0.header.take().map(ResponseHeader::new)
176 }
177
178 #[inline]
180 pub fn member_list(&self) -> &[Member] {
181 unsafe { &*(self.0.members.as_slice() as *const _ as *const [Member]) }
182 }
183}
184
185#[derive(Debug, Default, Clone)]
187pub struct MemberRemoveOptions(PbMemberRemoveRequest);
189
190impl MemberRemoveOptions {
191 #[inline]
193 fn with_id(mut self, id: u64) -> Self {
194 self.0.id = id;
195 self
196 }
197
198 #[inline]
200 pub const fn new() -> Self {
201 Self(PbMemberRemoveRequest { id: 0 })
202 }
203}
204
205impl From<MemberRemoveOptions> for PbMemberRemoveRequest {
206 #[inline]
207 fn from(options: MemberRemoveOptions) -> Self {
208 options.0
209 }
210}
211
212impl IntoRequest<PbMemberRemoveRequest> for MemberRemoveOptions {
213 #[inline]
214 fn into_request(self) -> Request<PbMemberRemoveRequest> {
215 Request::new(self.into())
216 }
217}
218
219#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
221#[derive(Debug, Default, Clone)]
222#[repr(transparent)]
223pub struct MemberRemoveResponse(PbMemberRemoveResponse);
224
225impl MemberRemoveResponse {
226 #[inline]
228 const fn new(resp: PbMemberRemoveResponse) -> Self {
229 Self(resp)
230 }
231
232 #[inline]
234 pub fn header(&self) -> Option<&ResponseHeader> {
235 self.0.header.as_ref().map(From::from)
236 }
237
238 #[inline]
240 pub fn take_header(&mut self) -> Option<ResponseHeader> {
241 self.0.header.take().map(ResponseHeader::new)
242 }
243
244 #[inline]
246 pub fn members(&self) -> &[Member] {
247 unsafe { &*(self.0.members.as_slice() as *const _ as *const [Member]) }
248 }
249}
250
251#[derive(Debug, Default, Clone)]
253pub struct MemberUpdateOptions(PbMemberUpdateRequest);
255
256impl MemberUpdateOptions {
257 #[inline]
258 fn with_option(mut self, id: u64, url: impl Into<Vec<String>>) -> Self {
259 self.0.id = id;
260 self.0.peer_ur_ls = url.into();
261 self
262 }
263
264 #[inline]
266 pub const fn new() -> Self {
267 Self(PbMemberUpdateRequest {
268 id: 0,
269 peer_ur_ls: Vec::new(),
270 })
271 }
272}
273
274impl From<MemberUpdateOptions> for PbMemberUpdateRequest {
275 #[inline]
276 fn from(options: MemberUpdateOptions) -> Self {
277 options.0
278 }
279}
280
281impl IntoRequest<PbMemberUpdateRequest> for MemberUpdateOptions {
282 #[inline]
283 fn into_request(self) -> Request<PbMemberUpdateRequest> {
284 Request::new(self.into())
285 }
286}
287
288#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
290#[derive(Debug, Default, Clone)]
291#[repr(transparent)]
292pub struct MemberUpdateResponse(PbMemberUpdateResponse);
293
294impl MemberUpdateResponse {
295 #[inline]
297 const fn new(resp: PbMemberUpdateResponse) -> Self {
298 Self(resp)
299 }
300
301 #[inline]
303 pub fn header(&self) -> Option<&ResponseHeader> {
304 self.0.header.as_ref().map(From::from)
305 }
306
307 #[inline]
309 pub fn take_header(&mut self) -> Option<ResponseHeader> {
310 self.0.header.take().map(ResponseHeader::new)
311 }
312
313 #[inline]
315 pub fn members(&self) -> &[Member] {
316 unsafe { &*(self.0.members.as_slice() as *const _ as *const [Member]) }
317 }
318}
319
320#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
322#[derive(Debug, Clone)]
323#[repr(transparent)]
324pub struct MemberListResponse(PbMemberListResponse);
325
326impl MemberListResponse {
327 #[inline]
329 const fn new(resp: PbMemberListResponse) -> Self {
330 Self(resp)
331 }
332
333 #[inline]
335 pub fn header(&self) -> Option<&ResponseHeader> {
336 self.0.header.as_ref().map(From::from)
337 }
338
339 #[inline]
341 pub fn take_header(&mut self) -> Option<ResponseHeader> {
342 self.0.header.take().map(ResponseHeader::new)
343 }
344
345 #[inline]
347 pub fn members(&self) -> &[Member] {
348 unsafe { &*(self.0.members.as_slice() as *const _ as *const [Member]) }
349 }
350}
351
352#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
354#[derive(Debug, Clone, PartialEq)]
355#[repr(transparent)]
356pub struct Member(PbMember);
357
358impl Member {
359 #[inline]
361 pub const fn id(&self) -> u64 {
362 self.0.id
363 }
364
365 #[inline]
367 pub fn name(&self) -> &str {
368 &self.0.name
369 }
370
371 #[inline]
373 pub fn peer_urls(&self) -> &[String] {
374 &self.0.peer_ur_ls
375 }
376
377 #[inline]
379 pub fn client_urls(&self) -> &[String] {
380 &self.0.client_ur_ls
381 }
382
383 #[inline]
385 pub const fn is_learner(&self) -> bool {
386 self.0.is_learner
387 }
388}
389
390impl From<&PbMember> for &Member {
391 #[inline]
392 fn from(src: &PbMember) -> Self {
393 unsafe { &*(src as *const _ as *const Member) }
394 }
395}
396
397#[derive(Debug, Default, Clone)]
399#[repr(transparent)]
400pub struct MemberPromoteOptions(PbMemberPromoteRequest);
401
402impl MemberPromoteOptions {
403 #[inline]
405 fn with_id(mut self, id: u64) -> Self {
406 self.0.id = id;
407 self
408 }
409
410 #[inline]
412 pub const fn new() -> Self {
413 Self(PbMemberPromoteRequest { id: 0 })
414 }
415}
416
417impl From<MemberPromoteOptions> for PbMemberPromoteRequest {
418 #[inline]
419 fn from(options: MemberPromoteOptions) -> Self {
420 options.0
421 }
422}
423
424impl IntoRequest<PbMemberPromoteRequest> for MemberPromoteOptions {
425 #[inline]
426 fn into_request(self) -> Request<PbMemberPromoteRequest> {
427 Request::new(self.into())
428 }
429}
430
431#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
433#[derive(Debug, Default, Clone)]
434#[repr(transparent)]
435pub struct MemberPromoteResponse(PbMemberPromoteResponse);
436
437impl MemberPromoteResponse {
438 #[inline]
440 const fn new(resp: PbMemberPromoteResponse) -> Self {
441 Self(resp)
442 }
443
444 #[inline]
446 pub fn header(&self) -> Option<&ResponseHeader> {
447 self.0.header.as_ref().map(From::from)
448 }
449
450 #[inline]
452 pub fn take_header(&mut self) -> Option<ResponseHeader> {
453 self.0.header.take().map(ResponseHeader::new)
454 }
455
456 #[inline]
458 pub fn members(&self) -> &[Member] {
459 unsafe { &*(self.0.members.as_slice() as *const _ as *const [Member]) }
460 }
461}