1use crate::caller::{CallOptions, ClientCaller, ClientCallerBuilder};
4#[cfg(feature = "raw-channel")]
5use crate::channel::Channel;
6use crate::error::{Error, Result};
7use crate::intercept::{InterceptedChannel, Interceptor};
8#[cfg(feature = "tls-openssl")]
9use crate::openssl_tls::{OpenSslClientConfig, OpenSslConnector};
10use crate::rpc::auth::Permission;
11use crate::rpc::auth::{AuthClient, AuthDisableResponse, AuthEnableResponse};
12use crate::rpc::auth::{
13 RoleAddResponse, RoleDeleteResponse, RoleGetResponse, RoleGrantPermissionResponse,
14 RoleListResponse, RoleRevokePermissionOptions, RoleRevokePermissionResponse, UserAddOptions,
15 UserAddResponse, UserChangePasswordResponse, UserDeleteResponse, UserGetResponse,
16 UserGrantRoleResponse, UserListResponse, UserRevokeRoleResponse,
17};
18use crate::rpc::cluster::{
19 ClusterClient, MemberAddOptions, MemberAddResponse, MemberListResponse, MemberPromoteResponse,
20 MemberRemoveResponse, MemberUpdateResponse,
21};
22use crate::rpc::election::{
23 CampaignResponse, ElectionClient, LeaderResponse, ObserveStream, ProclaimOptions,
24 ProclaimResponse, ResignOptions, ResignResponse,
25};
26use crate::rpc::kv::{
27 CompactionOptions, CompactionResponse, DeleteOptions, DeleteResponse, GetOptions, GetResponse,
28 KvClient, PutOptions, PutResponse, Txn, TxnResponse,
29};
30use crate::rpc::lease::{
31 LeaseClient, LeaseGrantOptions, LeaseGrantResponse, LeaseKeepAliveStream, LeaseKeeper,
32 LeaseLeasesResponse, LeaseRevokeResponse, LeaseTimeToLiveOptions, LeaseTimeToLiveResponse,
33};
34use crate::rpc::lock::{LockClient, LockOptions, LockResponse, UnlockResponse};
35use crate::rpc::maintenance::{
36 AlarmAction, AlarmOptions, AlarmResponse, AlarmType, DefragmentResponse, HashKvResponse,
37 HashResponse, MaintenanceClient, MoveLeaderResponse, SnapshotStreaming, StatusResponse,
38};
39use crate::rpc::watch::{WatchClient, WatchOptions, WatchStream};
40#[cfg(feature = "tls-openssl")]
41use crate::OpenSslResult;
42#[cfg(feature = "_tls")]
43use crate::TlsOptions;
44use http::uri::Uri;
45use tonic::metadata::{Ascii, MetadataValue};
46
47use std::str::FromStr;
48use std::sync::{Arc, RwLock};
49use std::time::Duration;
50use tokio::sync::mpsc::Sender;
51
52use tonic::transport::{channel::Change, Endpoint};
53
54const HTTP_PREFIX: &str = "http://";
55const HTTPS_PREFIX: &str = "https://";
56
57pub(crate) type AuthToken = Arc<RwLock<Option<MetadataValue<Ascii>>>>;
58
59#[derive(Clone)]
61pub struct Client {
62 kv: KvClient,
63 watch: WatchClient,
64 lease: LeaseClient,
65 lock: LockClient,
66 auth: AuthClient,
67 maintenance: MaintenanceClient,
68 cluster: ClusterClient,
69 election: ElectionClient,
70 options: ConnectOptions,
73 tx: Option<Sender<Change<Uri, Endpoint>>>,
74 client_caller: ClientCaller<()>,
75}
76
77impl Client {
78 pub async fn connect<E: AsRef<str>, S: AsRef<[E]>>(
80 endpoints: S,
81 options: Option<ConnectOptions>,
82 ) -> Result<Self> {
83 #[cfg(not(feature = "tls-openssl"))]
84 let make_balanced_channel = crate::channel::Tonic;
85 #[cfg(feature = "tls-openssl")]
86 let make_balanced_channel = crate::channel::Openssl {
87 conn: options
88 .clone()
89 .and_then(|o| o.otls)
90 .unwrap_or_else(OpenSslConnector::create_default)?,
91 };
92 Self::connect_with_balanced_channel(endpoints, options, make_balanced_channel).await
93 }
94
95 pub async fn connect_with_balanced_channel<E: AsRef<str>, S: AsRef<[E]>, MBC>(
97 endpoints: S,
98 options: Option<ConnectOptions>,
99 make_balanced_channel: MBC,
100 ) -> Result<Self>
101 where
102 MBC: crate::channel::BalancedChannelBuilder,
103 crate::error::Error: From<MBC::Error>,
104 {
105 let options = options.unwrap_or_default();
106 let endpoints = {
107 let mut eps = Vec::new();
108 for e in endpoints.as_ref() {
109 let channel = Self::build_endpoint(e.as_ref(), &options)?;
110 eps.push(channel);
111 }
112 eps
113 };
114
115 if endpoints.is_empty() {
116 return Err(Error::InvalidArgs(String::from("empty endpoints")));
117 }
118
119 let auth_token = Arc::new(RwLock::new(None));
120
121 let (channel, tx) = make_balanced_channel.balanced_channel(64)?;
123 let channel = InterceptedChannel::new(
124 channel,
125 Interceptor {
126 require_leader: options.require_leader,
127 auth_token: auth_token.clone(),
128 },
129 );
130 for endpoint in endpoints {
131 tx.send(Change::Insert(endpoint.uri().clone(), endpoint))
134 .await
135 .map_err(|_| {
136 Error::Internal("failed to insert endpoint into the balanced channel".into())
137 })?;
138 }
139
140 let client = Self::build_client(channel, Some(tx), auth_token, options);
141 client.refresh_token().await?;
142 Ok(client)
143 }
144
145 #[cfg(feature = "raw-channel")]
146 pub async fn from_channel(channel: Channel, options: Option<ConnectOptions>) -> Result<Self> {
148 let options = options.unwrap_or_default();
149 let auth_token = Arc::new(RwLock::new(None));
150 let channel = InterceptedChannel::new(
151 channel,
152 Interceptor {
153 require_leader: options.require_leader,
154 auth_token: auth_token.clone(),
155 },
156 );
157
158 let client = Self::build_client(channel, None, auth_token, options);
159 client.refresh_token().await?;
160 Ok(client)
161 }
162
163 fn build_endpoint(url: &str, options: &ConnectOptions) -> Result<Endpoint> {
164 use tonic::transport::Channel as TonicChannel;
165 let mut endpoint = if url.starts_with(HTTP_PREFIX) {
166 #[cfg(feature = "_tls")]
167 if options.tls.is_some() {
168 return Err(Error::InvalidArgs(String::from(
169 "TLS options are only supported with HTTPS URLs",
170 )));
171 }
172
173 TonicChannel::builder(url.parse()?)
174 } else if url.starts_with(HTTPS_PREFIX) {
175 #[cfg(not(any(feature = "_tls", feature = "tls-openssl")))]
176 return Err(Error::InvalidArgs(String::from(
177 "HTTPS URLs are only supported with one of the features \"tls\", \"tls-ring\" or \"tls-aws-lc\"",
178 )));
179
180 #[cfg(all(feature = "tls-openssl", not(feature = "_tls")))]
181 {
182 TonicChannel::builder(url.parse()?)
183 }
184
185 #[cfg(feature = "_tls")]
186 {
187 let tls = options.tls.clone().unwrap_or_default();
188 TonicChannel::builder(url.parse()?).tls_config(tls)?
189 }
190 } else {
191 #[cfg(feature = "_tls")]
192 {
193 let tls = options.tls.clone();
194
195 match tls {
196 Some(tls) => {
197 let e = HTTPS_PREFIX.to_owned() + url;
198 TonicChannel::builder(e.parse()?).tls_config(tls)?
199 }
200 None => {
201 let e = HTTP_PREFIX.to_owned() + url;
202 TonicChannel::builder(e.parse()?)
203 }
204 }
205 }
206
207 #[cfg(all(feature = "tls-openssl", not(feature = "_tls")))]
208 {
209 let pfx = if options.otls.as_ref().is_some() {
210 HTTPS_PREFIX
211 } else {
212 HTTP_PREFIX
213 };
214 let e = pfx.to_owned() + url;
215 TonicChannel::builder(e.parse()?)
216 }
217
218 #[cfg(all(not(feature = "_tls"), not(feature = "tls-openssl")))]
219 {
220 let e = HTTP_PREFIX.to_owned() + url;
221 TonicChannel::builder(e.parse()?)
222 }
223 };
224
225 if let Some((interval, timeout)) = options.keep_alive {
226 endpoint = endpoint
227 .keep_alive_while_idle(options.keep_alive_while_idle)
228 .http2_keep_alive_interval(interval)
229 .keep_alive_timeout(timeout);
230 }
231
232 if let Some(timeout) = options.timeout {
233 endpoint = endpoint.timeout(timeout);
234 }
235
236 if let Some(timeout) = options.connect_timeout {
237 endpoint = endpoint.connect_timeout(timeout);
238 }
239
240 if let Some(tcp_keepalive) = options.tcp_keepalive {
241 endpoint = endpoint.tcp_keepalive(Some(tcp_keepalive));
242 }
243
244 Ok(endpoint)
245 }
246
247 fn build_client(
248 channel: InterceptedChannel,
249 tx: Option<Sender<Change<Uri, Endpoint>>>,
250 auth_token: Arc<RwLock<Option<MetadataValue<Ascii>>>>,
251 options: ConnectOptions,
252 ) -> Self {
253 let auth = AuthClient::new(channel.clone());
254 let builder =
255 ClientCallerBuilder::new((&options).into(), auth_token, auth.clone(), channel);
256
257 let kv = KvClient::new(builder.clone());
258 let watch = WatchClient::new(builder.clone());
259 let lease = LeaseClient::new(builder.clone());
260 let lock = LockClient::new(builder.clone());
261 let cluster = ClusterClient::new(builder.clone());
262 let maintenance = MaintenanceClient::new(builder.clone());
263 let election = ElectionClient::new(builder.clone());
264
265 Self {
266 kv,
267 watch,
268 lease,
269 lock,
270 auth,
271 maintenance,
272 cluster,
273 election,
274 options,
275 tx,
276 client_caller: builder.build(|_| ()),
277 }
278 }
279
280 #[inline]
291 pub async fn add_endpoint<E: AsRef<str>>(&self, endpoint: E) -> Result<()> {
292 let endpoint = Self::build_endpoint(endpoint.as_ref(), &self.options)?;
293 let Some(tx) = &self.tx else {
294 return Err(Error::EndpointsNotManaged);
295 };
296 tx.send(Change::Insert(endpoint.uri().clone(), endpoint))
297 .await
298 .map_err(|e| Error::EndpointError(format!("failed to add endpoint because of {e}")))
299 }
300
301 #[inline]
307 pub async fn remove_endpoint<E: AsRef<str>>(&self, endpoint: E) -> Result<()> {
308 let uri = http::Uri::from_str(endpoint.as_ref())?;
309 let Some(tx) = &self.tx else {
310 return Err(Error::EndpointsNotManaged);
311 };
312 tx.send(Change::Remove(uri))
313 .await
314 .map_err(|e| Error::EndpointError(format!("failed to remove endpoint because of {e}")))
315 }
316
317 #[inline]
319 pub fn kv_client(&self) -> KvClient {
320 self.kv.clone()
321 }
322
323 #[inline]
325 pub fn watch_client(&self) -> WatchClient {
326 self.watch.clone()
327 }
328
329 #[inline]
331 pub fn lease_client(&self) -> LeaseClient {
332 self.lease.clone()
333 }
334
335 #[inline]
337 pub fn auth_client(&self) -> AuthClient {
338 self.auth.clone()
339 }
340
341 #[inline]
343 pub fn maintenance_client(&self) -> MaintenanceClient {
344 self.maintenance.clone()
345 }
346
347 #[inline]
349 pub fn cluster_client(&self) -> ClusterClient {
350 self.cluster.clone()
351 }
352
353 #[inline]
355 pub fn lock_client(&self) -> LockClient {
356 self.lock.clone()
357 }
358
359 #[inline]
361 pub fn election_client(&self) -> ElectionClient {
362 self.election.clone()
363 }
364
365 #[inline]
369 pub async fn put(
370 &mut self,
371 key: impl Into<Vec<u8>>,
372 value: impl Into<Vec<u8>>,
373 options: Option<PutOptions>,
374 ) -> Result<PutResponse> {
375 self.kv.put(key, value, options).await
376 }
377
378 #[inline]
380 pub async fn get(
381 &mut self,
382 key: impl Into<Vec<u8>>,
383 options: Option<GetOptions>,
384 ) -> Result<GetResponse> {
385 self.kv.get(key, options).await
386 }
387
388 #[inline]
390 pub async fn delete(
391 &mut self,
392 key: impl Into<Vec<u8>>,
393 options: Option<DeleteOptions>,
394 ) -> Result<DeleteResponse> {
395 self.kv.delete(key, options).await
396 }
397
398 #[inline]
402 pub async fn compact(
403 &mut self,
404 revision: i64,
405 options: Option<CompactionOptions>,
406 ) -> Result<CompactionResponse> {
407 self.kv.compact(revision, options).await
408 }
409
410 #[inline]
415 pub async fn txn(&mut self, txn: Txn) -> Result<TxnResponse> {
416 self.kv.txn(txn).await
417 }
418
419 #[inline]
424 pub async fn watch(
425 &mut self,
426 key: impl Into<Vec<u8>>,
427 options: Option<WatchOptions>,
428 ) -> Result<WatchStream> {
429 self.watch.watch(key, options).await
430 }
431
432 #[inline]
436 pub async fn lease_grant(
437 &mut self,
438 ttl: i64,
439 options: Option<LeaseGrantOptions>,
440 ) -> Result<LeaseGrantResponse> {
441 self.lease.grant(ttl, options).await
442 }
443
444 #[inline]
446 pub async fn lease_revoke(&mut self, id: i64) -> Result<LeaseRevokeResponse> {
447 self.lease.revoke(id).await
448 }
449
450 #[inline]
453 pub async fn lease_keep_alive(
454 &mut self,
455 id: i64,
456 ) -> Result<(LeaseKeeper, LeaseKeepAliveStream)> {
457 self.lease.keep_alive(id).await
458 }
459
460 #[inline]
462 pub async fn lease_time_to_live(
463 &mut self,
464 id: i64,
465 options: Option<LeaseTimeToLiveOptions>,
466 ) -> Result<LeaseTimeToLiveResponse> {
467 self.lease.time_to_live(id, options).await
468 }
469
470 #[inline]
472 pub async fn leases(&mut self) -> Result<LeaseLeasesResponse> {
473 self.lease.leases().await
474 }
475
476 #[inline]
483 pub async fn lock(
484 &mut self,
485 name: impl Into<Vec<u8>>,
486 options: Option<LockOptions>,
487 ) -> Result<LockResponse> {
488 self.lock.lock(name, options).await
489 }
490
491 #[inline]
495 pub async fn unlock(&mut self, key: impl Into<Vec<u8>>) -> Result<UnlockResponse> {
496 self.lock.unlock(key).await
497 }
498
499 #[inline]
501 pub async fn auth_enable(&mut self) -> Result<AuthEnableResponse> {
502 self.auth.auth_enable().await
503 }
504
505 #[inline]
507 pub async fn auth_disable(&mut self) -> Result<AuthDisableResponse> {
508 self.auth.auth_disable().await
509 }
510
511 #[inline]
513 pub async fn role_add(&mut self, name: impl Into<String>) -> Result<RoleAddResponse> {
514 self.auth.role_add(name).await
515 }
516
517 #[inline]
519 pub async fn role_delete(&mut self, name: impl Into<String>) -> Result<RoleDeleteResponse> {
520 self.auth.role_delete(name).await
521 }
522
523 #[inline]
525 pub async fn role_get(&mut self, name: impl Into<String>) -> Result<RoleGetResponse> {
526 self.auth.role_get(name).await
527 }
528
529 #[inline]
531 pub async fn role_list(&mut self) -> Result<RoleListResponse> {
532 self.auth.role_list().await
533 }
534
535 #[inline]
537 pub async fn role_grant_permission(
538 &mut self,
539 name: impl Into<String>,
540 perm: Permission,
541 ) -> Result<RoleGrantPermissionResponse> {
542 self.auth.role_grant_permission(name, perm).await
543 }
544
545 #[inline]
547 pub async fn role_revoke_permission(
548 &mut self,
549 name: impl Into<String>,
550 key: impl Into<Vec<u8>>,
551 options: Option<RoleRevokePermissionOptions>,
552 ) -> Result<RoleRevokePermissionResponse> {
553 self.auth.role_revoke_permission(name, key, options).await
554 }
555
556 #[inline]
558 pub async fn user_add(
559 &mut self,
560 name: impl Into<String>,
561 password: impl Into<String>,
562 options: Option<UserAddOptions>,
563 ) -> Result<UserAddResponse> {
564 self.auth.user_add(name, password, options).await
565 }
566
567 #[inline]
569 pub async fn user_get(&mut self, name: impl Into<String>) -> Result<UserGetResponse> {
570 self.auth.user_get(name).await
571 }
572
573 #[inline]
575 pub async fn user_list(&mut self) -> Result<UserListResponse> {
576 self.auth.user_list().await
577 }
578
579 #[inline]
581 pub async fn user_delete(&mut self, name: impl Into<String>) -> Result<UserDeleteResponse> {
582 self.auth.user_delete(name).await
583 }
584
585 #[inline]
587 pub async fn user_change_password(
588 &mut self,
589 name: impl Into<String>,
590 password: impl Into<String>,
591 ) -> Result<UserChangePasswordResponse> {
592 self.auth.user_change_password(name, password).await
593 }
594
595 #[inline]
597 pub async fn user_grant_role(
598 &mut self,
599 user: impl Into<String>,
600 role: impl Into<String>,
601 ) -> Result<UserGrantRoleResponse> {
602 self.auth.user_grant_role(user, role).await
603 }
604
605 #[inline]
607 pub async fn user_revoke_role(
608 &mut self,
609 user: impl Into<String>,
610 role: impl Into<String>,
611 ) -> Result<UserRevokeRoleResponse> {
612 self.auth.user_revoke_role(user, role).await
613 }
614
615 #[inline]
617 pub async fn alarm(
618 &mut self,
619 alarm_action: AlarmAction,
620 alarm_type: AlarmType,
621 options: Option<AlarmOptions>,
622 ) -> Result<AlarmResponse> {
623 self.maintenance
624 .alarm(alarm_action, alarm_type, options)
625 .await
626 }
627
628 #[inline]
630 pub async fn status(&mut self) -> Result<StatusResponse> {
631 self.maintenance.status().await
632 }
633
634 #[inline]
636 pub async fn defragment(&mut self) -> Result<DefragmentResponse> {
637 self.maintenance.defragment().await
638 }
639
640 #[inline]
644 pub async fn hash(&mut self) -> Result<HashResponse> {
645 self.maintenance.hash().await
646 }
647
648 #[inline]
651 pub async fn hash_kv(&mut self, revision: i64) -> Result<HashKvResponse> {
652 self.maintenance.hash_kv(revision).await
653 }
654
655 #[inline]
657 pub async fn snapshot(&mut self) -> Result<SnapshotStreaming> {
658 self.maintenance.snapshot().await
659 }
660
661 #[inline]
663 pub async fn member_add<E: AsRef<str>, S: AsRef<[E]>>(
664 &mut self,
665 urls: S,
666 options: Option<MemberAddOptions>,
667 ) -> Result<MemberAddResponse> {
668 let mut eps = Vec::new();
669 for e in urls.as_ref() {
670 let e = e.as_ref();
671 let url = if e.starts_with(HTTP_PREFIX) || e.starts_with(HTTPS_PREFIX) {
672 e.to_string()
673 } else {
674 HTTP_PREFIX.to_owned() + e
675 };
676 eps.push(url);
677 }
678
679 self.cluster.member_add(eps, options).await
680 }
681
682 #[inline]
684 pub async fn member_remove(&mut self, id: u64) -> Result<MemberRemoveResponse> {
685 self.cluster.member_remove(id).await
686 }
687
688 #[inline]
690 pub async fn member_update(
691 &mut self,
692 id: u64,
693 url: impl Into<Vec<String>>,
694 ) -> Result<MemberUpdateResponse> {
695 self.cluster.member_update(id, url).await
696 }
697
698 #[inline]
700 pub async fn member_promote(&mut self, id: u64) -> Result<MemberPromoteResponse> {
701 self.cluster.member_promote(id).await
702 }
703
704 #[inline]
706 pub async fn member_list(&mut self) -> Result<MemberListResponse> {
707 self.cluster.member_list().await
708 }
709
710 #[inline]
712 pub async fn move_leader(&mut self, target_id: u64) -> Result<MoveLeaderResponse> {
713 self.maintenance.move_leader(target_id).await
714 }
715
716 #[inline]
720 pub async fn campaign(
721 &mut self,
722 name: impl Into<Vec<u8>>,
723 value: impl Into<Vec<u8>>,
724 lease: i64,
725 ) -> Result<CampaignResponse> {
726 self.election.campaign(name, value, lease).await
727 }
728
729 #[inline]
731 pub async fn proclaim(
732 &mut self,
733 value: impl Into<Vec<u8>>,
734 options: Option<ProclaimOptions>,
735 ) -> Result<ProclaimResponse> {
736 self.election.proclaim(value, options).await
737 }
738
739 #[inline]
741 pub async fn leader(&mut self, name: impl Into<Vec<u8>>) -> Result<LeaderResponse> {
742 self.election.leader(name).await
743 }
744
745 #[inline]
748 pub async fn observe(&mut self, name: impl Into<Vec<u8>>) -> Result<ObserveStream> {
749 self.election.observe(name).await
750 }
751
752 #[inline]
754 pub async fn resign(&mut self, option: Option<ResignOptions>) -> Result<ResignResponse> {
755 self.election.resign(option).await
756 }
757
758 pub async fn refresh_token(&self) -> Result<()> {
760 self.client_caller.refresh_token().await
761 }
762
763 pub async fn update_user(&mut self, user: Option<(String, String)>) -> Result<()> {
771 self.client_caller.update_user(user).await
772 }
773}
774
775#[derive(Debug, Default, Clone)]
777pub struct ConnectOptions {
778 user: Option<(String, String)>,
780 keep_alive: Option<(Duration, Duration)>,
782 keep_alive_while_idle: bool,
784 timeout: Option<Duration>,
786 connect_timeout: Option<Duration>,
788 tcp_keepalive: Option<Duration>,
790 #[cfg(feature = "_tls")]
791 tls: Option<TlsOptions>,
792 #[cfg(feature = "tls-openssl")]
793 otls: Option<OpenSslResult<OpenSslConnector>>,
794 require_leader: bool,
796 refresh_expired_token: bool,
798}
799
800impl ConnectOptions {
801 #[inline]
803 pub fn with_user(mut self, name: impl Into<String>, password: impl Into<String>) -> Self {
804 self.user = Some((name.into(), password.into()));
805 self
806 }
807
808 #[cfg_attr(docsrs, doc(cfg(any(feature = "tls-ring", feature = "tls-aws-lc"))))]
812 #[cfg(feature = "_tls")]
813 #[inline]
814 pub fn with_tls(mut self, tls: TlsOptions) -> Self {
815 self.tls = Some(tls);
816 self
817 }
818
819 #[cfg_attr(docsrs, doc(cfg(feature = "tls-openssl")))]
821 #[cfg(feature = "tls-openssl")]
822 #[inline]
823 pub fn with_openssl_tls(mut self, otls: OpenSslClientConfig) -> Self {
824 self.otls = Some(otls.build());
829 self
830 }
831
832 #[inline]
834 pub fn with_keep_alive(mut self, interval: Duration, timeout: Duration) -> Self {
835 self.keep_alive = Some((interval, timeout));
836 self
837 }
838
839 #[inline]
841 pub fn with_timeout(mut self, timeout: Duration) -> Self {
842 self.timeout = Some(timeout);
843 self
844 }
845
846 #[inline]
848 pub fn with_connect_timeout(mut self, timeout: Duration) -> Self {
849 self.connect_timeout = Some(timeout);
850 self
851 }
852
853 #[inline]
855 pub fn with_tcp_keepalive(mut self, tcp_keepalive: Duration) -> Self {
856 self.tcp_keepalive = Some(tcp_keepalive);
857 self
858 }
859
860 #[inline]
866 pub fn with_keep_alive_while_idle(mut self, enabled: bool) -> Self {
867 self.keep_alive_while_idle = enabled;
868 self
869 }
870
871 #[inline]
873 pub fn with_require_leader(mut self, require_leader: bool) -> Self {
874 self.require_leader = require_leader;
875 self
876 }
877
878 pub fn with_auto_token_refresh(mut self, refresh_expired_token: bool) -> Self {
882 self.refresh_expired_token = refresh_expired_token;
883 self
884 }
885
886 #[inline]
888 pub const fn new() -> Self {
889 ConnectOptions {
890 user: None,
891 keep_alive: None,
892 keep_alive_while_idle: true,
893 timeout: None,
894 connect_timeout: None,
895 tcp_keepalive: None,
896 #[cfg(feature = "_tls")]
897 tls: None,
898 #[cfg(feature = "tls-openssl")]
899 otls: None,
900 require_leader: false,
901 refresh_expired_token: false,
902 }
903 }
904}
905
906impl From<&ConnectOptions> for CallOptions {
907 fn from(options: &ConnectOptions) -> Self {
908 Self {
909 creds: Arc::new(RwLock::new(options.user.clone())),
910 refresh_expired_token: options.refresh_expired_token,
911 }
912 }
913}