etcd_client/rpc/
cluster.rs1use crate::auth::AuthService;
4use crate::channel::Channel;
5use crate::error::Result;
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<Channel>>,
26}
27
28impl ClusterClient {
29 #[inline]
31 pub(crate) fn new(channel: Channel, auth_token: Arc<RwLock<Option<HeaderValue>>>) -> Self {
32 let inner = PbClusterClient::new(AuthService::new(channel, auth_token));
33 Self { inner }
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 let resp = self
44 .inner
45 .member_add(options.unwrap_or_default().with_urls(urls))
46 .await?
47 .into_inner();
48
49 Ok(MemberAddResponse::new(resp))
50 }
51
52 #[inline]
54 pub async fn member_remove(&mut self, id: u64) -> Result<MemberRemoveResponse> {
55 let resp = self
56 .inner
57 .member_remove(MemberRemoveOptions::new().with_id(id))
58 .await?
59 .into_inner();
60 Ok(MemberRemoveResponse::new(resp))
61 }
62
63 #[inline]
65 pub async fn member_update(
66 &mut self,
67 id: u64,
68 url: impl Into<Vec<String>>,
69 ) -> Result<MemberUpdateResponse> {
70 let resp = self
71 .inner
72 .member_update(MemberUpdateOptions::new().with_option(id, url))
73 .await?
74 .into_inner();
75 Ok(MemberUpdateResponse::new(resp))
76 }
77
78 #[inline]
80 pub async fn member_list(&mut self) -> Result<MemberListResponse> {
81 let resp = self
82 .inner
83 .member_list(PbMemberListRequest {})
84 .await?
85 .into_inner();
86 Ok(MemberListResponse::new(resp))
87 }
88
89 #[inline]
91 pub async fn member_promote(&mut self, id: u64) -> Result<MemberPromoteResponse> {
92 let resp = self
93 .inner
94 .member_promote(MemberPromoteOptions::new().with_id(id))
95 .await?
96 .into_inner();
97 Ok(MemberPromoteResponse::new(resp))
98 }
99}
100
101#[derive(Debug, Default, Clone)]
103#[repr(transparent)]
104pub struct MemberAddOptions(PbMemberAddRequest);
105
106impl MemberAddOptions {
107 #[inline]
108 fn with_urls(mut self, urls: impl Into<Vec<String>>) -> Self {
109 self.0.peer_ur_ls = urls.into();
110 self
111 }
112
113 #[inline]
115 pub const fn new() -> Self {
116 Self(PbMemberAddRequest {
117 peer_ur_ls: Vec::new(),
118 is_learner: false,
119 })
120 }
121
122 #[inline]
124 pub const fn with_is_learner(mut self) -> Self {
125 self.0.is_learner = true;
126 self
127 }
128}
129
130impl From<MemberAddOptions> for PbMemberAddRequest {
131 #[inline]
132 fn from(options: MemberAddOptions) -> Self {
133 options.0
134 }
135}
136
137impl IntoRequest<PbMemberAddRequest> for MemberAddOptions {
138 #[inline]
139 fn into_request(self) -> Request<PbMemberAddRequest> {
140 Request::new(self.into())
141 }
142}
143
144#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
146#[derive(Debug, Default, Clone)]
147#[repr(transparent)]
148pub struct MemberAddResponse(PbMemberAddResponse);
149
150impl MemberAddResponse {
151 #[inline]
153 const fn new(resp: PbMemberAddResponse) -> Self {
154 Self(resp)
155 }
156
157 #[inline]
159 pub fn header(&self) -> Option<&ResponseHeader> {
160 self.0.header.as_ref().map(From::from)
161 }
162
163 #[inline]
165 pub fn member(&self) -> Option<&Member> {
166 self.0.member.as_ref().map(From::from)
167 }
168
169 #[inline]
171 pub fn take_header(&mut self) -> Option<ResponseHeader> {
172 self.0.header.take().map(ResponseHeader::new)
173 }
174
175 #[inline]
177 pub fn member_list(&self) -> &[Member] {
178 unsafe { &*(self.0.members.as_slice() as *const _ as *const [Member]) }
179 }
180}
181
182#[derive(Debug, Default, Clone)]
184pub struct MemberRemoveOptions(PbMemberRemoveRequest);
186
187impl MemberRemoveOptions {
188 #[inline]
190 fn with_id(mut self, id: u64) -> Self {
191 self.0.id = id;
192 self
193 }
194
195 #[inline]
197 pub const fn new() -> Self {
198 Self(PbMemberRemoveRequest { id: 0 })
199 }
200}
201
202impl From<MemberRemoveOptions> for PbMemberRemoveRequest {
203 #[inline]
204 fn from(options: MemberRemoveOptions) -> Self {
205 options.0
206 }
207}
208
209impl IntoRequest<PbMemberRemoveRequest> for MemberRemoveOptions {
210 #[inline]
211 fn into_request(self) -> Request<PbMemberRemoveRequest> {
212 Request::new(self.into())
213 }
214}
215
216#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
218#[derive(Debug, Default, Clone)]
219#[repr(transparent)]
220pub struct MemberRemoveResponse(PbMemberRemoveResponse);
221
222impl MemberRemoveResponse {
223 #[inline]
225 const fn new(resp: PbMemberRemoveResponse) -> Self {
226 Self(resp)
227 }
228
229 #[inline]
231 pub fn header(&self) -> Option<&ResponseHeader> {
232 self.0.header.as_ref().map(From::from)
233 }
234
235 #[inline]
237 pub fn take_header(&mut self) -> Option<ResponseHeader> {
238 self.0.header.take().map(ResponseHeader::new)
239 }
240
241 #[inline]
243 pub fn members(&self) -> &[Member] {
244 unsafe { &*(self.0.members.as_slice() as *const _ as *const [Member]) }
245 }
246}
247
248#[derive(Debug, Default, Clone)]
250pub struct MemberUpdateOptions(PbMemberUpdateRequest);
252
253impl MemberUpdateOptions {
254 #[inline]
255 fn with_option(mut self, id: u64, url: impl Into<Vec<String>>) -> Self {
256 self.0.id = id;
257 self.0.peer_ur_ls = url.into();
258 self
259 }
260
261 #[inline]
263 pub const fn new() -> Self {
264 Self(PbMemberUpdateRequest {
265 id: 0,
266 peer_ur_ls: Vec::new(),
267 })
268 }
269}
270
271impl From<MemberUpdateOptions> for PbMemberUpdateRequest {
272 #[inline]
273 fn from(options: MemberUpdateOptions) -> Self {
274 options.0
275 }
276}
277
278impl IntoRequest<PbMemberUpdateRequest> for MemberUpdateOptions {
279 #[inline]
280 fn into_request(self) -> Request<PbMemberUpdateRequest> {
281 Request::new(self.into())
282 }
283}
284
285#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
287#[derive(Debug, Default, Clone)]
288#[repr(transparent)]
289pub struct MemberUpdateResponse(PbMemberUpdateResponse);
290
291impl MemberUpdateResponse {
292 #[inline]
294 const fn new(resp: PbMemberUpdateResponse) -> Self {
295 Self(resp)
296 }
297
298 #[inline]
300 pub fn header(&self) -> Option<&ResponseHeader> {
301 self.0.header.as_ref().map(From::from)
302 }
303
304 #[inline]
306 pub fn take_header(&mut self) -> Option<ResponseHeader> {
307 self.0.header.take().map(ResponseHeader::new)
308 }
309
310 #[inline]
312 pub fn members(&self) -> &[Member] {
313 unsafe { &*(self.0.members.as_slice() as *const _ as *const [Member]) }
314 }
315}
316
317#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
319#[derive(Debug, Clone)]
320#[repr(transparent)]
321pub struct MemberListResponse(PbMemberListResponse);
322
323impl MemberListResponse {
324 #[inline]
326 const fn new(resp: PbMemberListResponse) -> Self {
327 Self(resp)
328 }
329
330 #[inline]
332 pub fn header(&self) -> Option<&ResponseHeader> {
333 self.0.header.as_ref().map(From::from)
334 }
335
336 #[inline]
338 pub fn take_header(&mut self) -> Option<ResponseHeader> {
339 self.0.header.take().map(ResponseHeader::new)
340 }
341
342 #[inline]
344 pub fn members(&self) -> &[Member] {
345 unsafe { &*(self.0.members.as_slice() as *const _ as *const [Member]) }
346 }
347}
348
349#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
351#[derive(Debug, Clone, PartialEq)]
352#[repr(transparent)]
353pub struct Member(PbMember);
354
355impl Member {
356 #[inline]
358 pub const fn id(&self) -> u64 {
359 self.0.id
360 }
361
362 #[inline]
364 pub fn name(&self) -> &str {
365 &self.0.name
366 }
367
368 #[inline]
370 pub fn peer_urls(&self) -> &[String] {
371 &self.0.peer_ur_ls
372 }
373
374 #[inline]
376 pub fn client_urls(&self) -> &[String] {
377 &self.0.client_ur_ls
378 }
379
380 #[inline]
382 pub const fn is_learner(&self) -> bool {
383 self.0.is_learner
384 }
385}
386
387impl From<&PbMember> for &Member {
388 #[inline]
389 fn from(src: &PbMember) -> Self {
390 unsafe { &*(src as *const _ as *const Member) }
391 }
392}
393
394#[derive(Debug, Default, Clone)]
396#[repr(transparent)]
397pub struct MemberPromoteOptions(PbMemberPromoteRequest);
398
399impl MemberPromoteOptions {
400 #[inline]
402 fn with_id(mut self, id: u64) -> Self {
403 self.0.id = id;
404 self
405 }
406
407 #[inline]
409 pub const fn new() -> Self {
410 Self(PbMemberPromoteRequest { id: 0 })
411 }
412}
413
414impl From<MemberPromoteOptions> for PbMemberPromoteRequest {
415 #[inline]
416 fn from(options: MemberPromoteOptions) -> Self {
417 options.0
418 }
419}
420
421impl IntoRequest<PbMemberPromoteRequest> for MemberPromoteOptions {
422 #[inline]
423 fn into_request(self) -> Request<PbMemberPromoteRequest> {
424 Request::new(self.into())
425 }
426}
427
428#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
430#[derive(Debug, Default, Clone)]
431#[repr(transparent)]
432pub struct MemberPromoteResponse(PbMemberPromoteResponse);
433
434impl MemberPromoteResponse {
435 #[inline]
437 const fn new(resp: PbMemberPromoteResponse) -> Self {
438 Self(resp)
439 }
440
441 #[inline]
443 pub fn header(&self) -> Option<&ResponseHeader> {
444 self.0.header.as_ref().map(From::from)
445 }
446
447 #[inline]
449 pub fn take_header(&mut self) -> Option<ResponseHeader> {
450 self.0.header.take().map(ResponseHeader::new)
451 }
452
453 #[inline]
455 pub fn members(&self) -> &[Member] {
456 unsafe { &*(self.0.members.as_slice() as *const _ as *const [Member]) }
457 }
458}