opendal_core/docs/internals/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
18//! Implementing a service.
19//!
20//! Every OpenDAL backend implements the raw [`Service`] trait. A service owns
21//! protocol-specific request construction and response handling. The operator
22//! owns path normalization, option validation, layer composition, and
23//! dispatch.
24//!
25//! Service crates live under `core/services/<name>/`. Their public builder and
26//! configuration types construct a typed backend; the backend then implements
27//! [`Service`].
28//!
29//! # Service identity and capabilities
30//!
31//! [`Service::info`] returns immutable identity such as the scheme, root, and
32//! namespace name. Runtime resources do not belong in [`ServiceInfo`];
33//! services read them from [`OperationContext`].
34//!
35//! [`Service::capability`] reports the behavior implemented by that service
36//! stack. Set an operation or option capability only when the implementation
37//! satisfies the corresponding public contract. Operators reject options whose
38//! required capability is absent.
39//!
40//! # Operation body types
41//!
42//! [`Service`] uses associated types for operation bodies:
43//!
44//! ```text
45//! type Reader: oio::Read;
46//! type Writer: oio::Write;
47//! type Lister: oio::List;
48//! type Deleter: oio::Delete;
49//! type Copier: oio::Copy;
50//! ```
51//!
52//! A backend returns concrete body types so its implementation and typed
53//! wrappers do not pay for dynamic dispatch. Use `()` for an unsupported body
54//! type and return [`ErrorKind::Unsupported`] from the corresponding operation
55//! entry point.
56//!
57//! OpenDAL erases these types once, at [`ServiceDyn`]. [`Servicer`] is
58//! `Arc<dyn ServiceDyn>` and is the handle used by operators and runtime layer
59//! composition. A wrapper that receives a [`Servicer`] may forward erased
60//! `oio::*` bodies, but a backend should keep its own bodies concrete.
61//!
62//! # Operation methods
63//!
64//! Each operation method receives normalized paths, an [`OperationContext`],
65//! and operation-specific arguments. The context supplies layer-composed
66//! runtime resources such as the HTTP transport and executor. Options such as
67//! ranges, versions, conditions, and concurrency remain in the operation
68//! arguments.
69//!
70//! An implementation must:
71//!
72//! - Map every advertised option to the native request without silently
73//! dropping it.
74//! - Preserve the operation's public success, error, and atomicity contract.
75//! - Return structured OpenDAL errors with the correct [`ErrorKind`] and
76//! useful context.
77//! - Keep credentials and other secrets out of `Debug` output and errors.
78//! - Forward cancellation and cleanup to protocol-specific readers, writers,
79//! deleters, and copiers.
80//!
81//! # Adding or changing a service
82//!
83//! Keep configuration, request construction, operation bodies, and error
84//! parsing at their existing service boundaries. Update the facade feature and
85//! service registration when the service must be available through the
86//! `opendal` crate.
87//!
88//! Before advertising new behavior, reproduce it against the actual service
89//! and run the matching capability-gated behavior tests. Protocol
90//! documentation, emulators, and fabricated responses can explain an
91//! implementation, but they do not establish real-service conformance.
92//!
93//! [`Service`]: crate::raw::Service
94//! [`Service::info`]: crate::raw::Service::info
95//! [`Service::capability`]: crate::raw::Service::capability
96//! [`ServiceInfo`]: crate::raw::ServiceInfo
97//! [`ServiceDyn`]: crate::raw::ServiceDyn
98//! [`Servicer`]: crate::raw::Servicer
99//! [`OperationContext`]: crate::OperationContext
100//! [`ErrorKind`]: crate::ErrorKind
101//! [`ErrorKind::Unsupported`]: crate::ErrorKind::Unsupported