use crate::auth::AuthService;
use crate::channel::Channel;
use crate::error::Result;
use crate::rpc::pb::etcdserverpb::cluster_client::ClusterClient as PbClusterClient;
use crate::rpc::pb::etcdserverpb::{
Member as PbMember, MemberAddRequest as PbMemberAddRequest,
MemberAddResponse as PbMemberAddResponse, MemberListRequest as PbMemberListRequest,
MemberListResponse as PbMemberListResponse, MemberPromoteRequest as PbMemberPromoteRequest,
MemberPromoteResponse as PbMemberPromoteResponse, MemberRemoveRequest as PbMemberRemoveRequest,
MemberRemoveResponse as PbMemberRemoveResponse, MemberUpdateRequest as PbMemberUpdateRequest,
MemberUpdateResponse as PbMemberUpdateResponse,
};
use crate::rpc::ResponseHeader;
use http::HeaderValue;
use std::sync::RwLock;
use std::{string::String, sync::Arc};
use tonic::{IntoRequest, Request};
#[repr(transparent)]
#[derive(Clone)]
pub struct ClusterClient {
inner: PbClusterClient<AuthService<Channel>>,
}
impl ClusterClient {
#[inline]
pub(crate) fn new(channel: Channel, auth_token: Arc<RwLock<Option<HeaderValue>>>) -> Self {
let inner = PbClusterClient::new(AuthService::new(channel, auth_token));
Self { inner }
}
#[inline]
pub async fn member_add(
&mut self,
urls: impl Into<Vec<String>>,
options: Option<MemberAddOptions>,
) -> Result<MemberAddResponse> {
let resp = self
.inner
.member_add(options.unwrap_or_default().with_urls(urls))
.await?
.into_inner();
Ok(MemberAddResponse::new(resp))
}
#[inline]
pub async fn member_remove(&mut self, id: u64) -> Result<MemberRemoveResponse> {
let resp = self
.inner
.member_remove(MemberRemoveOptions::new().with_id(id))
.await?
.into_inner();
Ok(MemberRemoveResponse::new(resp))
}
#[inline]
pub async fn member_update(
&mut self,
id: u64,
url: impl Into<Vec<String>>,
) -> Result<MemberUpdateResponse> {
let resp = self
.inner
.member_update(MemberUpdateOptions::new().with_option(id, url))
.await?
.into_inner();
Ok(MemberUpdateResponse::new(resp))
}
#[inline]
pub async fn member_list(&mut self) -> Result<MemberListResponse> {
let resp = self
.inner
.member_list(PbMemberListRequest {})
.await?
.into_inner();
Ok(MemberListResponse::new(resp))
}
#[inline]
pub async fn member_promote(&mut self, id: u64) -> Result<MemberPromoteResponse> {
let resp = self
.inner
.member_promote(MemberPromoteOptions::new().with_id(id))
.await?
.into_inner();
Ok(MemberPromoteResponse::new(resp))
}
}
#[derive(Debug, Default, Clone)]
#[repr(transparent)]
pub struct MemberAddOptions(PbMemberAddRequest);
impl MemberAddOptions {
#[inline]
fn with_urls(mut self, urls: impl Into<Vec<String>>) -> Self {
self.0.peer_ur_ls = urls.into();
self
}
#[inline]
pub const fn new() -> Self {
Self(PbMemberAddRequest {
peer_ur_ls: Vec::new(),
is_learner: false,
})
}
#[inline]
pub const fn with_is_learner(mut self) -> Self {
self.0.is_learner = true;
self
}
}
impl From<MemberAddOptions> for PbMemberAddRequest {
#[inline]
fn from(options: MemberAddOptions) -> Self {
options.0
}
}
impl IntoRequest<PbMemberAddRequest> for MemberAddOptions {
#[inline]
fn into_request(self) -> Request<PbMemberAddRequest> {
Request::new(self.into())
}
}
#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
#[derive(Debug, Default, Clone)]
#[repr(transparent)]
pub struct MemberAddResponse(PbMemberAddResponse);
impl MemberAddResponse {
#[inline]
const fn new(resp: PbMemberAddResponse) -> Self {
Self(resp)
}
#[inline]
pub fn header(&self) -> Option<&ResponseHeader> {
self.0.header.as_ref().map(From::from)
}
#[inline]
pub fn member(&self) -> Option<&Member> {
self.0.member.as_ref().map(From::from)
}
#[inline]
pub fn take_header(&mut self) -> Option<ResponseHeader> {
self.0.header.take().map(ResponseHeader::new)
}
#[inline]
pub fn member_list(&self) -> &[Member] {
unsafe { &*(self.0.members.as_slice() as *const _ as *const [Member]) }
}
}
#[derive(Debug, Default, Clone)]
pub struct MemberRemoveOptions(PbMemberRemoveRequest);
impl MemberRemoveOptions {
#[inline]
fn with_id(mut self, id: u64) -> Self {
self.0.id = id;
self
}
#[inline]
pub const fn new() -> Self {
Self(PbMemberRemoveRequest { id: 0 })
}
}
impl From<MemberRemoveOptions> for PbMemberRemoveRequest {
#[inline]
fn from(options: MemberRemoveOptions) -> Self {
options.0
}
}
impl IntoRequest<PbMemberRemoveRequest> for MemberRemoveOptions {
#[inline]
fn into_request(self) -> Request<PbMemberRemoveRequest> {
Request::new(self.into())
}
}
#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
#[derive(Debug, Default, Clone)]
#[repr(transparent)]
pub struct MemberRemoveResponse(PbMemberRemoveResponse);
impl MemberRemoveResponse {
#[inline]
const fn new(resp: PbMemberRemoveResponse) -> Self {
Self(resp)
}
#[inline]
pub fn header(&self) -> Option<&ResponseHeader> {
self.0.header.as_ref().map(From::from)
}
#[inline]
pub fn take_header(&mut self) -> Option<ResponseHeader> {
self.0.header.take().map(ResponseHeader::new)
}
#[inline]
pub fn members(&self) -> &[Member] {
unsafe { &*(self.0.members.as_slice() as *const _ as *const [Member]) }
}
}
#[derive(Debug, Default, Clone)]
pub struct MemberUpdateOptions(PbMemberUpdateRequest);
impl MemberUpdateOptions {
#[inline]
fn with_option(mut self, id: u64, url: impl Into<Vec<String>>) -> Self {
self.0.id = id;
self.0.peer_ur_ls = url.into();
self
}
#[inline]
pub const fn new() -> Self {
Self(PbMemberUpdateRequest {
id: 0,
peer_ur_ls: Vec::new(),
})
}
}
impl From<MemberUpdateOptions> for PbMemberUpdateRequest {
#[inline]
fn from(options: MemberUpdateOptions) -> Self {
options.0
}
}
impl IntoRequest<PbMemberUpdateRequest> for MemberUpdateOptions {
#[inline]
fn into_request(self) -> Request<PbMemberUpdateRequest> {
Request::new(self.into())
}
}
#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
#[derive(Debug, Default, Clone)]
#[repr(transparent)]
pub struct MemberUpdateResponse(PbMemberUpdateResponse);
impl MemberUpdateResponse {
#[inline]
const fn new(resp: PbMemberUpdateResponse) -> Self {
Self(resp)
}
#[inline]
pub fn header(&self) -> Option<&ResponseHeader> {
self.0.header.as_ref().map(From::from)
}
#[inline]
pub fn take_header(&mut self) -> Option<ResponseHeader> {
self.0.header.take().map(ResponseHeader::new)
}
#[inline]
pub fn members(&self) -> &[Member] {
unsafe { &*(self.0.members.as_slice() as *const _ as *const [Member]) }
}
}
#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
#[derive(Debug, Clone)]
#[repr(transparent)]
pub struct MemberListResponse(PbMemberListResponse);
impl MemberListResponse {
#[inline]
const fn new(resp: PbMemberListResponse) -> Self {
Self(resp)
}
#[inline]
pub fn header(&self) -> Option<&ResponseHeader> {
self.0.header.as_ref().map(From::from)
}
#[inline]
pub fn take_header(&mut self) -> Option<ResponseHeader> {
self.0.header.take().map(ResponseHeader::new)
}
#[inline]
pub fn members(&self) -> &[Member] {
unsafe { &*(self.0.members.as_slice() as *const _ as *const [Member]) }
}
}
#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
#[derive(Debug, Clone, PartialEq)]
#[repr(transparent)]
pub struct Member(PbMember);
impl Member {
#[inline]
pub const fn id(&self) -> u64 {
self.0.id
}
#[inline]
pub fn name(&self) -> &str {
&self.0.name
}
#[inline]
pub fn peer_urls(&self) -> &[String] {
&self.0.peer_ur_ls
}
#[inline]
pub fn client_urls(&self) -> &[String] {
&self.0.client_ur_ls
}
#[inline]
pub const fn is_learner(&self) -> bool {
self.0.is_learner
}
}
impl From<&PbMember> for &Member {
#[inline]
fn from(src: &PbMember) -> Self {
unsafe { &*(src as *const _ as *const Member) }
}
}
#[derive(Debug, Default, Clone)]
#[repr(transparent)]
pub struct MemberPromoteOptions(PbMemberPromoteRequest);
impl MemberPromoteOptions {
#[inline]
fn with_id(mut self, id: u64) -> Self {
self.0.id = id;
self
}
#[inline]
pub const fn new() -> Self {
Self(PbMemberPromoteRequest { id: 0 })
}
}
impl From<MemberPromoteOptions> for PbMemberPromoteRequest {
#[inline]
fn from(options: MemberPromoteOptions) -> Self {
options.0
}
}
impl IntoRequest<PbMemberPromoteRequest> for MemberPromoteOptions {
#[inline]
fn into_request(self) -> Request<PbMemberPromoteRequest> {
Request::new(self.into())
}
}
#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
#[derive(Debug, Default, Clone)]
#[repr(transparent)]
pub struct MemberPromoteResponse(PbMemberPromoteResponse);
impl MemberPromoteResponse {
#[inline]
const fn new(resp: PbMemberPromoteResponse) -> Self {
Self(resp)
}
#[inline]
pub fn header(&self) -> Option<&ResponseHeader> {
self.0.header.as_ref().map(From::from)
}
#[inline]
pub fn take_header(&mut self) -> Option<ResponseHeader> {
self.0.header.take().map(ResponseHeader::new)
}
#[inline]
pub fn members(&self) -> &[Member] {
unsafe { &*(self.0.members.as_slice() as *const _ as *const [Member]) }
}
}