opendal_core/docs/internals/layer.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 layer.
19//!
20//! A [`Layer`] intercepts an operator's composed service, operation context,
21//! or both. Use a layer for behavior that applies across services, such as
22//! retry, timeout, tracing, metrics, or runtime resource replacement.
23//!
24//! # Two composition hooks
25//!
26//! [`Layer`] exposes two hooks:
27//!
28//! ```text
29//! fn apply_service(&self, service: Servicer) -> Servicer;
30//! fn apply_context(
31//! &self,
32//! service: Servicer,
33//! context: OperationContext,
34//! ) -> OperationContext;
35//! ```
36//!
37//! `apply_service` wraps storage operations. `apply_context` wraps or replaces
38//! runtime resources such as the HTTP transport and executor. Each hook
39//! returns its input unchanged by default, so a layer implements only the
40//! plane it owns.
41//!
42//! The operator first applies every service hook in insertion order. It then
43//! applies every context hook in the same order, passing the final service
44//! stack to each context hook. Adding a layer or replacing the base context
45//! replays the complete layer list, producing a service stack and context from
46//! the same ordering.
47//!
48//! # Operation layers
49//!
50//! An operation layer normally contains:
51//!
52//! - An `XxxLayer` that implements [`Layer::apply_service`].
53//! - An `XxxService` that stores the inner [`Servicer`] and implements
54//! [`Service`].
55//!
56//! The wrapper overrides only the operations it owns and forwards the rest to
57//! the inner service. It must also return capabilities that describe the
58//! behavior of the wrapped stack. The wrapper keeps its own operation body
59//! types concrete until OpenDAL erases it back into a [`Servicer`].
60//!
61//! # Resource layers
62//!
63//! A resource-only layer implements [`Layer::apply_context`]. It should
64//! preserve the previous resource when lower layers must remain effective. A
65//! layer that wraps an HTTP transport or executor must decide explicitly
66//! whether requests continue through the previous value or replace it
67//! entirely.
68//!
69//! Layers that coordinate policy across operation and I/O phases can implement
70//! both hooks. Shared mutable state requires interior mutability and must
71//! remain `Send` and `Sync`, because cloned operators can run operations
72//! concurrently.
73//!
74//! [`Layer`]: crate::raw::Layer
75//! [`Layer::apply_service`]: crate::raw::Layer::apply_service
76//! [`Layer::apply_context`]: crate::raw::Layer::apply_context
77//! [`Service`]: crate::raw::Service
78//! [`Servicer`]: crate::raw::Servicer