Skip to main content

opendal_core/raw/
accessor.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18use std::fmt::Debug;
19use std::future::ready;
20use std::hash::Hash;
21use std::hash::Hasher;
22use std::mem;
23use std::sync::Arc;
24
25use futures::Future;
26
27use crate::raw::*;
28use crate::*;
29
30/// Underlying trait of all backends for implementers.
31///
32/// The actual data access of storage service happens in Accessor layer.
33/// Every storage supported by OpenDAL must implement [`Access`] but not all
34/// methods of [`Access`] will be implemented according to how the storage service is.
35///
36/// For example, user can not modify the content from one HTTP file server directly.
37/// So [`Http`][crate::services::Http] implements and provides only read related actions.
38///
39/// [`Access`] gives default implementation for all methods which will raise [`ErrorKind::Unsupported`] error.
40/// And what action this [`Access`] supports will be pointed out in [`AccessorInfo`].
41///
42/// # Note
43///
44/// Visit [`internals`][crate::docs::internals] for more tutorials.
45///
46/// # Operations
47///
48/// - Path in args will all be normalized into the same style, services
49///   should handle them based on services' requirement.
50///   - Path that ends with `/` means it's Dir, otherwise, it's File.
51///   - Root dir is `/`
52///   - Path will never be empty.
53/// - Operations without capability requirement like `metadata`, `create` are
54///   basic operations.
55///   - All services must implement them.
56///   - Use `unimplemented!()` if not implemented or can't implement.
57/// - Operations with capability requirement like `presign` are optional operations.
58///   - Services can implement them based on services capabilities.
59///   - The default implementation should return [`ErrorKind::Unsupported`].
60pub trait Access: Send + Sync + Debug + Unpin + 'static {
61    /// Reader is the associated reader returned in `read` operation.
62    type Reader: oio::Read;
63    /// Writer is the associated writer returned in `write` operation.
64    type Writer: oio::Write;
65    /// Lister is the associated lister returned in `list` operation.
66    type Lister: oio::List;
67    /// Deleter is the associated deleter returned in `delete` operation.
68    type Deleter: oio::Delete;
69    /// Copier is the associated copier returned in `copy` operation.
70    type Copier: oio::Copy;
71
72    /// Invoke the `info` operation to get metadata of accessor.
73    ///
74    /// # Notes
75    ///
76    /// This function is required to be implemented.
77    ///
78    /// By returning AccessorInfo, underlying services can declare
79    /// some useful information about itself.
80    ///
81    /// - scheme: declare the scheme of backend.
82    /// - capabilities: declare the capabilities of current backend.
83    fn info(&self) -> Arc<AccessorInfo>;
84
85    /// Invoke the `create` operation on the specified path
86    ///
87    /// Require [`Capability::create_dir`]
88    ///
89    /// # Behavior
90    ///
91    /// - Input path MUST match with EntryMode, DON'T NEED to check mode.
92    /// - Create on existing dir SHOULD succeed.
93    fn create_dir(
94        &self,
95        path: &str,
96        args: OpCreateDir,
97    ) -> impl Future<Output = Result<RpCreateDir>> + MaybeSend {
98        let (_, _) = (path, args);
99
100        ready(Err(Error::new(
101            ErrorKind::Unsupported,
102            "operation is not supported",
103        )))
104    }
105
106    /// Invoke the `stat` operation on the specified path.
107    ///
108    /// Require [`Capability::stat`]
109    ///
110    /// # Behavior
111    ///
112    /// - `stat` empty path means stat backend's root path.
113    /// - `stat` a path endswith "/" means stating a dir.
114    /// - `mode` and `content_length` must be set.
115    fn stat(&self, path: &str, args: OpStat) -> impl Future<Output = Result<RpStat>> + MaybeSend {
116        let (_, _) = (path, args);
117
118        ready(Err(Error::new(
119            ErrorKind::Unsupported,
120            "operation is not supported",
121        )))
122    }
123
124    /// Invoke the `read` operation on the specified path, returns a raw
125    /// reader if operate successful.
126    ///
127    /// Require [`Capability::read`]
128    ///
129    /// # Behavior
130    ///
131    /// - Input path MUST be file path, DON'T NEED to check mode.
132    /// - Range I/O is selected by the returned reader's `open` or `read`
133    ///   operation.
134    fn read(
135        &self,
136        path: &str,
137        args: OpRead,
138    ) -> impl Future<Output = Result<(RpRead, Self::Reader)>> + MaybeSend {
139        let (_, _) = (path, args);
140
141        ready(Err(Error::new(
142            ErrorKind::Unsupported,
143            "operation is not supported",
144        )))
145    }
146
147    /// Invoke the `write` operation on the specified path, returns a
148    /// written size if operate successful.
149    ///
150    /// Require [`Capability::write`]
151    ///
152    /// # Behavior
153    ///
154    /// - Input path MUST be file path, DON'T NEED to check mode.
155    fn write(
156        &self,
157        path: &str,
158        args: OpWrite,
159    ) -> impl Future<Output = Result<(RpWrite, Self::Writer)>> + MaybeSend {
160        let (_, _) = (path, args);
161
162        ready(Err(Error::new(
163            ErrorKind::Unsupported,
164            "operation is not supported",
165        )))
166    }
167
168    /// Invoke the `delete` operation on the specified path.
169    ///
170    /// Require [`Capability::delete`]
171    ///
172    /// # Behavior
173    ///
174    /// - `delete` is an idempotent operation, it's safe to call `Delete` on the same path multiple times.
175    /// - `delete` SHOULD return `Ok(())` if the path is deleted successfully or not exist.
176    fn delete(&self) -> impl Future<Output = Result<(RpDelete, Self::Deleter)>> + MaybeSend {
177        ready(Err(Error::new(
178            ErrorKind::Unsupported,
179            "operation is not supported",
180        )))
181    }
182
183    /// Invoke the `list` operation on the specified path.
184    ///
185    /// Require [`Capability::list`]
186    ///
187    /// # Behavior
188    ///
189    /// - Input path MUST be dir path, DON'T NEED to check mode.
190    /// - List non-exist dir should return Empty.
191    fn list(
192        &self,
193        path: &str,
194        args: OpList,
195    ) -> impl Future<Output = Result<(RpList, Self::Lister)>> + MaybeSend {
196        let (_, _) = (path, args);
197
198        ready(Err(Error::new(
199            ErrorKind::Unsupported,
200            "operation is not supported",
201        )))
202    }
203
204    /// Invoke the `copy` operation on the specified `from` path and `to` path.
205    ///
206    /// Require [Capability::copy]
207    ///
208    /// # Behaviour
209    ///
210    /// - `from` and `to` MUST be file path, DON'T NEED to check mode.
211    /// - Copy on existing file SHOULD succeed.
212    /// - Copy on existing file SHOULD overwrite and truncate.
213    fn copy(
214        &self,
215        from: &str,
216        to: &str,
217        args: OpCopy,
218        opts: OpCopier,
219    ) -> impl Future<Output = Result<(RpCopy, Self::Copier)>> + MaybeSend {
220        let (_, _, _, _) = (from, to, args, opts);
221
222        ready(Err(Error::new(
223            ErrorKind::Unsupported,
224            "operation is not supported",
225        )))
226    }
227
228    /// Invoke the `rename` operation on the specified `from` path and `to` path.
229    ///
230    /// Require [Capability::rename]
231    fn rename(
232        &self,
233        from: &str,
234        to: &str,
235        args: OpRename,
236    ) -> impl Future<Output = Result<RpRename>> + MaybeSend {
237        let (_, _, _) = (from, to, args);
238
239        ready(Err(Error::new(
240            ErrorKind::Unsupported,
241            "operation is not supported",
242        )))
243    }
244
245    /// Invoke the `presign` operation on the specified path.
246    ///
247    /// Require [`Capability::presign`]
248    ///
249    /// # Behavior
250    ///
251    /// - This API is optional, return [`std::io::ErrorKind::Unsupported`] if not supported.
252    fn presign(
253        &self,
254        path: &str,
255        args: OpPresign,
256    ) -> impl Future<Output = Result<RpPresign>> + MaybeSend {
257        let (_, _) = (path, args);
258
259        ready(Err(Error::new(
260            ErrorKind::Unsupported,
261            "operation is not supported",
262        )))
263    }
264}
265
266/// `AccessDyn` is the dyn version of [`Access`] make it possible to use as
267/// `Box<dyn AccessDyn>`.
268pub trait AccessDyn: Send + Sync + Debug + Unpin {
269    /// Dyn version of [`Accessor::info`]
270    fn info_dyn(&self) -> Arc<AccessorInfo>;
271    /// Dyn version of [`Accessor::create_dir`]
272    fn create_dir_dyn<'a>(
273        &'a self,
274        path: &'a str,
275        args: OpCreateDir,
276    ) -> BoxedFuture<'a, Result<RpCreateDir>>;
277    /// Dyn version of [`Accessor::stat`]
278    fn stat_dyn<'a>(&'a self, path: &'a str, args: OpStat) -> BoxedFuture<'a, Result<RpStat>>;
279    /// Dyn version of [`Accessor::read`]
280    fn read_dyn<'a>(
281        &'a self,
282        path: &'a str,
283        args: OpRead,
284    ) -> BoxedFuture<'a, Result<(RpRead, oio::Reader)>>;
285    /// Dyn version of [`Accessor::write`]
286    fn write_dyn<'a>(
287        &'a self,
288        path: &'a str,
289        args: OpWrite,
290    ) -> BoxedFuture<'a, Result<(RpWrite, oio::Writer)>>;
291    /// Dyn version of [`Accessor::delete`]
292    fn delete_dyn(&self) -> BoxedFuture<'_, Result<(RpDelete, oio::Deleter)>>;
293    /// Dyn version of [`Accessor::list`]
294    fn list_dyn<'a>(
295        &'a self,
296        path: &'a str,
297        args: OpList,
298    ) -> BoxedFuture<'a, Result<(RpList, oio::Lister)>>;
299    /// Dyn version of [`Accessor::copy`]
300    fn copy_dyn<'a>(
301        &'a self,
302        from: &'a str,
303        to: &'a str,
304        args: OpCopy,
305        opts: OpCopier,
306    ) -> BoxedFuture<'a, Result<(RpCopy, oio::Copier)>>;
307    /// Dyn version of [`Accessor::rename`]
308    fn rename_dyn<'a>(
309        &'a self,
310        from: &'a str,
311        to: &'a str,
312        args: OpRename,
313    ) -> BoxedFuture<'a, Result<RpRename>>;
314    /// Dyn version of [`Accessor::presign`]
315    fn presign_dyn<'a>(
316        &'a self,
317        path: &'a str,
318        args: OpPresign,
319    ) -> BoxedFuture<'a, Result<RpPresign>>;
320}
321
322impl<A: ?Sized> AccessDyn for A
323where
324    A: Access<
325            Reader = oio::Reader,
326            Writer = oio::Writer,
327            Lister = oio::Lister,
328            Deleter = oio::Deleter,
329            Copier = oio::Copier,
330        >,
331{
332    fn info_dyn(&self) -> Arc<AccessorInfo> {
333        self.info()
334    }
335
336    fn create_dir_dyn<'a>(
337        &'a self,
338        path: &'a str,
339        args: OpCreateDir,
340    ) -> BoxedFuture<'a, Result<RpCreateDir>> {
341        Box::pin(self.create_dir(path, args))
342    }
343
344    fn stat_dyn<'a>(&'a self, path: &'a str, args: OpStat) -> BoxedFuture<'a, Result<RpStat>> {
345        Box::pin(self.stat(path, args))
346    }
347
348    fn read_dyn<'a>(
349        &'a self,
350        path: &'a str,
351        args: OpRead,
352    ) -> BoxedFuture<'a, Result<(RpRead, oio::Reader)>> {
353        Box::pin(self.read(path, args))
354    }
355
356    fn write_dyn<'a>(
357        &'a self,
358        path: &'a str,
359        args: OpWrite,
360    ) -> BoxedFuture<'a, Result<(RpWrite, oio::Writer)>> {
361        Box::pin(self.write(path, args))
362    }
363
364    fn delete_dyn(&self) -> BoxedFuture<'_, Result<(RpDelete, oio::Deleter)>> {
365        Box::pin(self.delete())
366    }
367
368    fn list_dyn<'a>(
369        &'a self,
370        path: &'a str,
371        args: OpList,
372    ) -> BoxedFuture<'a, Result<(RpList, oio::Lister)>> {
373        Box::pin(self.list(path, args))
374    }
375
376    fn copy_dyn<'a>(
377        &'a self,
378        from: &'a str,
379        to: &'a str,
380        args: OpCopy,
381        opts: OpCopier,
382    ) -> BoxedFuture<'a, Result<(RpCopy, oio::Copier)>> {
383        Box::pin(self.copy(from, to, args, opts))
384    }
385
386    fn rename_dyn<'a>(
387        &'a self,
388        from: &'a str,
389        to: &'a str,
390        args: OpRename,
391    ) -> BoxedFuture<'a, Result<RpRename>> {
392        Box::pin(self.rename(from, to, args))
393    }
394
395    fn presign_dyn<'a>(
396        &'a self,
397        path: &'a str,
398        args: OpPresign,
399    ) -> BoxedFuture<'a, Result<RpPresign>> {
400        Box::pin(self.presign(path, args))
401    }
402}
403
404impl Access for dyn AccessDyn {
405    type Reader = oio::Reader;
406    type Writer = oio::Writer;
407    type Deleter = oio::Deleter;
408    type Lister = oio::Lister;
409    type Copier = oio::Copier;
410
411    fn info(&self) -> Arc<AccessorInfo> {
412        self.info_dyn()
413    }
414
415    async fn create_dir(&self, path: &str, args: OpCreateDir) -> Result<RpCreateDir> {
416        self.create_dir_dyn(path, args).await
417    }
418
419    async fn stat(&self, path: &str, args: OpStat) -> Result<RpStat> {
420        self.stat_dyn(path, args).await
421    }
422
423    async fn read(&self, path: &str, args: OpRead) -> Result<(RpRead, Self::Reader)> {
424        self.read_dyn(path, args).await
425    }
426
427    async fn write(&self, path: &str, args: OpWrite) -> Result<(RpWrite, Self::Writer)> {
428        self.write_dyn(path, args).await
429    }
430
431    async fn delete(&self) -> Result<(RpDelete, Self::Deleter)> {
432        self.delete_dyn().await
433    }
434
435    async fn list(&self, path: &str, args: OpList) -> Result<(RpList, Self::Lister)> {
436        self.list_dyn(path, args).await
437    }
438
439    async fn copy(
440        &self,
441        from: &str,
442        to: &str,
443        args: OpCopy,
444        opts: OpCopier,
445    ) -> Result<(RpCopy, Self::Copier)> {
446        self.copy_dyn(from, to, args, opts).await
447    }
448
449    async fn rename(&self, from: &str, to: &str, args: OpRename) -> Result<RpRename> {
450        self.rename_dyn(from, to, args).await
451    }
452
453    async fn presign(&self, path: &str, args: OpPresign) -> Result<RpPresign> {
454        self.presign_dyn(path, args).await
455    }
456}
457
458/// Dummy implementation of accessor.
459impl Access for () {
460    type Reader = ();
461    type Writer = ();
462    type Lister = ();
463    type Deleter = ();
464    type Copier = ();
465
466    fn info(&self) -> Arc<AccessorInfo> {
467        let ai = AccessorInfo::default();
468        ai.set_scheme("dummy")
469            .set_root("")
470            .set_name("dummy")
471            .set_native_capability(Capability::default());
472        ai.into()
473    }
474}
475
476/// All functions in `Accessor` only requires `&self`, so it's safe to implement
477/// `Accessor` for `Arc<impl Access>`.
478// If we use async fn directly, some weird higher rank trait bound error (`Send`/`Accessor` impl not general enough) will happen.
479// Probably related to https://github.com/rust-lang/rust/issues/96865
480#[allow(clippy::manual_async_fn)]
481impl<T: Access + ?Sized> Access for Arc<T> {
482    type Reader = T::Reader;
483    type Writer = T::Writer;
484    type Lister = T::Lister;
485    type Deleter = T::Deleter;
486    type Copier = T::Copier;
487
488    fn info(&self) -> Arc<AccessorInfo> {
489        self.as_ref().info()
490    }
491
492    fn create_dir(
493        &self,
494        path: &str,
495        args: OpCreateDir,
496    ) -> impl Future<Output = Result<RpCreateDir>> + MaybeSend {
497        async move { self.as_ref().create_dir(path, args).await }
498    }
499
500    fn stat(&self, path: &str, args: OpStat) -> impl Future<Output = Result<RpStat>> + MaybeSend {
501        async move { self.as_ref().stat(path, args).await }
502    }
503
504    fn read(
505        &self,
506        path: &str,
507        args: OpRead,
508    ) -> impl Future<Output = Result<(RpRead, Self::Reader)>> + MaybeSend {
509        async move { self.as_ref().read(path, args).await }
510    }
511
512    fn write(
513        &self,
514        path: &str,
515        args: OpWrite,
516    ) -> impl Future<Output = Result<(RpWrite, Self::Writer)>> + MaybeSend {
517        async move { self.as_ref().write(path, args).await }
518    }
519
520    fn delete(&self) -> impl Future<Output = Result<(RpDelete, Self::Deleter)>> + MaybeSend {
521        async move { self.as_ref().delete().await }
522    }
523
524    fn list(
525        &self,
526        path: &str,
527        args: OpList,
528    ) -> impl Future<Output = Result<(RpList, Self::Lister)>> + MaybeSend {
529        async move { self.as_ref().list(path, args).await }
530    }
531
532    fn copy(
533        &self,
534        from: &str,
535        to: &str,
536        args: OpCopy,
537        opts: OpCopier,
538    ) -> impl Future<Output = Result<(RpCopy, Self::Copier)>> + MaybeSend {
539        async move { self.as_ref().copy(from, to, args, opts).await }
540    }
541
542    fn rename(
543        &self,
544        from: &str,
545        to: &str,
546        args: OpRename,
547    ) -> impl Future<Output = Result<RpRename>> + MaybeSend {
548        async move { self.as_ref().rename(from, to, args).await }
549    }
550
551    fn presign(
552        &self,
553        path: &str,
554        args: OpPresign,
555    ) -> impl Future<Output = Result<RpPresign>> + MaybeSend {
556        async move { self.as_ref().presign(path, args).await }
557    }
558}
559
560/// Accessor is the type erased accessor with `Arc<dyn Accessor>`.
561pub type Accessor = Arc<dyn AccessDyn>;
562
563#[derive(Debug)]
564struct AccessorInfoInner {
565    scheme: &'static str,
566    root: Arc<str>,
567    name: Arc<str>,
568
569    native_capability: Capability,
570    full_capability: Capability,
571
572    http_client: HttpClient,
573    executor: Executor,
574}
575
576impl Default for AccessorInfoInner {
577    fn default() -> Self {
578        Self {
579            scheme: "unknown",
580            root: Arc::from(""),
581            name: Arc::from(""),
582            native_capability: Capability::default(),
583            full_capability: Capability::default(),
584            http_client: HttpClient::default(),
585            executor: Executor::default(),
586        }
587    }
588}
589
590/// Info for the accessor. Users can use this struct to retrieve information about the underlying backend.
591///
592/// This struct is intentionally not implemented with `Clone` to ensure that all accesses
593/// within the same operator, access layers, and services use the same instance of `AccessorInfo`.
594/// This is especially important for `HttpClient` and `Executor`.
595///
596/// ## Panic Safety
597///
598/// All methods provided by `AccessorInfo` will safely handle lock poisoning scenarios.
599/// If the inner `RwLock` is poisoned (which happens when another thread panicked while holding
600/// the write lock), this method will gracefully continue execution.
601///
602/// - For read operations, the method will return the current state.
603/// - For write operations, the method will do nothing.
604///
605/// ## Maintain Notes
606///
607/// We are using `std::sync::RwLock` to provide thread-safe access to the inner data.
608///
609/// I have performed [the bench across different arc-swap alike crates](https://github.com/krdln/arc-swap-benches):
610///
611/// ```txt
612/// test arcswap                    ... bench:          14.85 ns/iter (+/- 0.33)
613/// test arcswap_full               ... bench:         128.27 ns/iter (+/- 4.30)
614/// test baseline                   ... bench:          11.33 ns/iter (+/- 0.76)
615/// test mutex_4                    ... bench:         296.73 ns/iter (+/- 49.96)
616/// test mutex_unconteded           ... bench:          13.26 ns/iter (+/- 0.56)
617/// test rwlock_fast_4              ... bench:         201.60 ns/iter (+/- 7.47)
618/// test rwlock_fast_uncontended    ... bench:          12.77 ns/iter (+/- 0.37)
619/// test rwlock_parking_4           ... bench:         232.02 ns/iter (+/- 11.14)
620/// test rwlock_parking_uncontended ... bench:          13.18 ns/iter (+/- 0.39)
621/// test rwlock_std_4               ... bench:         219.56 ns/iter (+/- 5.56)
622/// test rwlock_std_uncontended     ... bench:          13.55 ns/iter (+/- 0.33)
623/// ```
624///
625/// The results show that as long as there aren't too many uncontended accesses, `RwLock` is the
626/// best choice, allowing for fast access and the ability to modify partial data without cloning
627/// everything.
628///
629/// And it's true: we only update and modify the internal data in a few instances, such as when
630/// building an operator or applying new layers.
631#[derive(Debug, Default)]
632pub struct AccessorInfo {
633    inner: std::sync::RwLock<AccessorInfoInner>,
634}
635
636impl PartialEq for AccessorInfo {
637    fn eq(&self, other: &Self) -> bool {
638        self.scheme() == other.scheme()
639            && self.root() == other.root()
640            && self.name() == other.name()
641    }
642}
643
644impl Eq for AccessorInfo {}
645
646impl Hash for AccessorInfo {
647    fn hash<H: Hasher>(&self, state: &mut H) {
648        self.scheme().hash(state);
649        self.root().hash(state);
650        self.name().hash(state);
651    }
652}
653
654impl AccessorInfo {
655    /// Scheme of backend.
656    ///
657    /// # Panic Safety
658    ///
659    /// This method safely handles lock poisoning scenarios. If the inner `RwLock` is poisoned,
660    /// this method will gracefully continue execution by simply returning the current scheme.
661    pub fn scheme(&self) -> &'static str {
662        match self.inner.read() {
663            Ok(v) => v.scheme,
664            Err(err) => err.get_ref().scheme,
665        }
666    }
667
668    /// Set scheme for backend.
669    ///
670    /// # Panic Safety
671    ///
672    /// This method safely handles lock poisoning scenarios. If the inner `RwLock` is poisoned,
673    /// this method will gracefully continue execution by simply skipping the update operation
674    /// rather than propagating the panic.
675    pub fn set_scheme(&self, scheme: &'static str) -> &Self {
676        if let Ok(mut v) = self.inner.write() {
677            v.scheme = scheme;
678        }
679
680        self
681    }
682
683    /// Root of backend, will be in format like `/path/to/dir/`
684    ///
685    /// # Panic Safety
686    ///
687    /// This method safely handles lock poisoning scenarios. If the inner `RwLock` is poisoned,
688    /// this method will gracefully continue execution by simply returning the current root.
689    pub fn root(&self) -> Arc<str> {
690        match self.inner.read() {
691            Ok(v) => v.root.clone(),
692            Err(err) => err.get_ref().root.clone(),
693        }
694    }
695
696    /// Set root for backend.
697    ///
698    /// Note: input root must be normalized.
699    ///
700    /// # Panic Safety
701    ///
702    /// This method safely handles lock poisoning scenarios. If the inner `RwLock` is poisoned,
703    /// this method will gracefully continue execution by simply skipping the update operation
704    /// rather than propagating the panic.
705    pub fn set_root(&self, root: &str) -> &Self {
706        if let Ok(mut v) = self.inner.write() {
707            v.root = Arc::from(root);
708        }
709
710        self
711    }
712
713    /// Name of backend, could be empty if underlying backend doesn't have namespace concept.
714    ///
715    /// For example:
716    ///
717    /// - `s3` => bucket name
718    /// - `azblob` => container name
719    /// - `azdfs` => filesystem name
720    /// - `azfile` => share name
721    ///
722    /// # Panic Safety
723    ///
724    /// This method safely handles lock poisoning scenarios. If the inner `RwLock` is poisoned,
725    /// this method will gracefully continue execution by simply returning the current scheme.
726    pub fn name(&self) -> Arc<str> {
727        match self.inner.read() {
728            Ok(v) => v.name.clone(),
729            Err(err) => err.get_ref().name.clone(),
730        }
731    }
732
733    /// Set name of this backend.
734    ///
735    /// # Panic Safety
736    ///
737    /// This method safely handles lock poisoning scenarios. If the inner `RwLock` is poisoned,
738    /// this method will gracefully continue execution by simply skipping the update operation
739    /// rather than propagating the panic.
740    pub fn set_name(&self, name: &str) -> &Self {
741        if let Ok(mut v) = self.inner.write() {
742            v.name = Arc::from(name)
743        }
744
745        self
746    }
747
748    /// Get backend's native capabilities.
749    ///
750    /// # Panic Safety
751    ///
752    /// This method safely handles lock poisoning scenarios. If the inner `RwLock` is poisoned,
753    /// this method will gracefully continue execution by simply returning the current native capability.
754    pub fn native_capability(&self) -> Capability {
755        match self.inner.read() {
756            Ok(v) => v.native_capability,
757            Err(err) => err.get_ref().native_capability,
758        }
759    }
760
761    /// Set native capabilities for service.
762    ///
763    /// # NOTES
764    ///
765    /// Set native capability will also flush the full capability. The only way to change
766    /// full_capability is via `update_full_capability`.
767    ///
768    /// # Panic Safety
769    ///
770    /// This method safely handles lock poisoning scenarios. If the inner `RwLock` is poisoned,
771    /// this method will gracefully continue execution by simply skipping the update operation
772    /// rather than propagating the panic.
773    pub fn set_native_capability(&self, capability: Capability) -> &Self {
774        if let Ok(mut v) = self.inner.write() {
775            v.native_capability = capability;
776            v.full_capability = capability;
777        }
778
779        self
780    }
781
782    /// Get service's full capabilities.
783    ///
784    /// # Panic Safety
785    ///
786    /// This method safely handles lock poisoning scenarios. If the inner `RwLock` is poisoned,
787    /// this method will gracefully continue execution by simply returning the current native capability.
788    pub fn full_capability(&self) -> Capability {
789        match self.inner.read() {
790            Ok(v) => v.full_capability,
791            Err(err) => err.get_ref().full_capability,
792        }
793    }
794
795    /// Update service's full capabilities.
796    ///
797    /// # Panic Safety
798    ///
799    /// This method safely handles lock poisoning scenarios. If the inner `RwLock` is poisoned,
800    /// this method will gracefully continue execution by simply skipping the update operation
801    /// rather than propagating the panic.
802    pub fn update_full_capability(&self, f: impl FnOnce(Capability) -> Capability) -> &Self {
803        if let Ok(mut v) = self.inner.write() {
804            v.full_capability = f(v.full_capability);
805        }
806
807        self
808    }
809
810    /// Get http client from the context.
811    ///
812    /// # Panic Safety
813    ///
814    /// This method safely handles lock poisoning scenarios. If the inner `RwLock` is poisoned,
815    /// this method will gracefully continue execution by simply returning the current http client.
816    pub fn http_client(&self) -> HttpClient {
817        match self.inner.read() {
818            Ok(v) => v.http_client.clone(),
819            Err(err) => err.get_ref().http_client.clone(),
820        }
821    }
822
823    /// Update http client for the context.
824    ///
825    /// # Note
826    ///
827    /// Requests must be forwarded to the old HTTP client after the update. Otherwise, features such as retry, tracing, and metrics may not function properly.
828    ///
829    /// # Panic Safety
830    ///
831    /// This method safely handles lock poisoning scenarios. If the inner `RwLock` is poisoned,
832    /// this method will gracefully continue execution by simply skipping the update operation.
833    pub fn update_http_client(&self, f: impl FnOnce(HttpClient) -> HttpClient) -> &Self {
834        if let Ok(mut v) = self.inner.write() {
835            let client = mem::take(&mut v.http_client);
836            v.http_client = f(client);
837        }
838
839        self
840    }
841
842    /// Get executor from the context.
843    ///
844    /// # Panic Safety
845    ///
846    /// This method safely handles lock poisoning scenarios. If the inner `RwLock` is poisoned,
847    /// this method will gracefully continue execution by simply returning the current executor.
848    pub fn executor(&self) -> Executor {
849        match self.inner.read() {
850            Ok(v) => v.executor.clone(),
851            Err(err) => err.get_ref().executor.clone(),
852        }
853    }
854
855    /// Update executor for the context.
856    ///
857    /// # Note
858    ///
859    /// Tasks must be forwarded to the old executor after the update. Otherwise, features such as retry, timeout, and metrics may not function properly.
860    ///
861    /// # Panic Safety
862    ///
863    /// This method safely handles lock poisoning scenarios. If the inner `RwLock` is poisoned,
864    /// this method will gracefully continue execution by simply skipping the update operation.
865    pub fn update_executor(&self, f: impl FnOnce(Executor) -> Executor) -> &Self {
866        if let Ok(mut v) = self.inner.write() {
867            let executor = mem::take(&mut v.executor);
868            v.executor = f(executor);
869        }
870
871        self
872    }
873}