Skip to main content

Module concepts

Module concepts 

Source
Expand description

The core concepts of OpenDAL’s Rust API.

OpenDAL gives applications one storage API across services. Rust applications use four concepts: a service describes the storage backend, a builder configures it, an operator exposes operations, and layers add behavior around those operations.

For the language-independent model shared by every OpenDAL binding, see the OpenDAL concepts guide.

§Service and builder

A service is a storage backend such as S3, Google Cloud Storage, a local filesystem, or an in-memory store. Each service supports a different set of operations and optional features.

A Builder collects one service’s configuration and constructs its implementation. The services module exposes concrete builders, while Operator::new turns a builder into a ready-to-use operator.

configuration -> builder -> service -> operator
use opendal_core::Operator;
use opendal_core::services::Memory;

let builder = Memory::default();
let op = Operator::new(builder)?;

OpenDAL does not make every service support every operation. Applications can inspect the operator’s effective Capability before using an optional operation or option.

§Operator

An Operator is the public handle for one configured service and root. It normalizes paths, validates options against effective capabilities, runs the configured layers, and dispatches each operation to the service.

Operators are cheap to clone, contain no caller-visible lifetime or service type parameter, and can be shared across threads. A clone refers to the same composed service stack. Methods that add a layer or replace runtime resources return a new operator; existing clones and in-flight operations keep their current stack.

§Operation

Operations are storage actions such as read, write, stat, list, delete, copy, and rename. Convenience methods use default options, while the corresponding _with methods expose operation-specific options.

use opendal_core::Operator;
use opendal_core::services::Memory;

let op = Operator::new(Memory::default())?;
let bs = op.read("abc").await?;

OpenDAL normalizes every path relative to the operator’s root. / represents the root, a trailing / represents a directory, and any other normalized path represents a file. Operation documentation defines the observable behavior and errors. Specifications define portable contracts that span multiple operations and services.

§Layer and operation context

A Layer adds cross-cutting behavior such as retry, timeout, tracing, or metrics. Layers form an ordered stack around a service.

An OperationContext carries runtime resources such as the HTTP transport and executor from the operator to the service. Operation-specific values such as ranges, versions, conditions, and concurrency remain in that operation’s options.

Adding a layer with Operator::layer or replacing the base context with Operator::with_context rebuilds both the service stack and the composed context from the same ordered layer list:

base service -----+                    +-> composed service --+
                  +-> ordered layers --+                      +-> operation
base context -----+                    +-> composed context --+
use opendal_core::HttpTransporter;
use opendal_core::OperationContext;
use opendal_core::Operator;
use opendal_core::services::Memory;

let transport = HttpTransporter::default();
let op = Operator::new(Memory::default())?.with_context(
    OperationContext::new().with_http_transport(transport),
);

Most applications only need the public Operator API. Service and layer authors should continue with the internals guide.