Module opendal::docs::concepts

source ·
Expand description

The core concepts of OpenDAL’s public API.

OpenDAL provides a unified abstraction for all storage services.

There are three core concepts in OpenDAL:

  • Builder: Build an instance of underlying services.
  • Operator: A bridge between underlying implementation detail and unified abstraction.

If you are interested in internal implementation details, please have a look at internals.

Builder

Let’s start with Builder.

A Builder is a trait that is implemented by the underlying services. We can use a Builder to configure and create a service. Builder is the only public API provided by services, and the detailed implementation is hidden.

┌───────────┐                 ┌───────────┐
│           │     build()     │           │
│  Builder  ├────────────────►│  Service  │
│           │                 │           │
└───────────┘                 └───────────┘

All Builder provided by OpenDAL is under services, we can refer to them like opendal::services::S3.

For example:

use opendal::services::S3;

let mut builder = S3::default();
builder.bucket("example");
builder.root("/path/to/file");

Operator

The Operator is a bridge between the underlying implementation details and the unified abstraction. OpenDAL will erase all generic types and higher abstraction around it.

┌───────────┐           ┌───────────┐              ┌─────────────────┐
│           │  build()  │           │  type erase  │                 │
│  Builder  ├──────────►│  Service  ├─────────────►│     Operator    │
│           │           │           │              │                 │
└───────────┘           └───────────┘              └─────────────────┘

Operator can be built from Builder:

use opendal::services::S3;
use opendal::Operator;

let mut builder = S3::default();
builder.bucket("example");
builder.root("/path/to/file");

let op = Operator::new(builder)?.finish();
  • Operator has it’s internal Arc, so it’s cheap to clone it.
  • Operator doesn’t have generic parameters or lifetimes, so it’s easy to use it everywhere.
  • Operator implements Send and Sync, so it’s safe to send it between threads.

After get an Operator, we can do operations on different paths.

                           ┌──────────────┐
                 ┌────────►│ read("abc")  │
                 │         └──────────────┘
┌───────────┐    │
│ Operator  │    │         ┌──────────────┐
│ ┌───────┐ ├────┼────────►│ write("def") │
│ │Service│ │    │         └──────────────┘
└─┴───────┴─┘    │
                 │         ┌──────────────┐
                 └────────►│ list("ghi/") │
                           └──────────────┘

We can read data with given path in this way:

use opendal::services::S3;
use opendal::Operator;

let mut builder = S3::default();
builder.bucket("example");
builder.root("/path/to/file");

let op = Operator::new(builder)?.finish();
let bs: Vec<u8> = op.read("abc").await?;