Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ documentation in `docs/`, and benchmark tooling in `vortex-bench/` and `benchmar
Apache Arrow-style encodings.
- `encodings/*` contains more specialized compressed encodings.
- `vortex-file` implements file IO. It uses `LayoutReader` from `vortex-layout`.
- `vortex-io` holds the core async and blocking IO traits, plus the generic `object_store`
adapters that implement them.
- `vortex-cloud` holds the cloud object store integration: the URL-to-`ObjectStore` registry
and the OpenDAL-backed services (`cos://`, `oss://`). Every binding resolves URLs through it.
- `vortex-scan`, `vortex-session`, `vortex-datafusion`, and `vortex-duckdb` contain scan
and execution integrations.
- `vortex-python` contains Python bindings. RST-flavored project docs live in `docs/`.
Expand Down
95 changes: 80 additions & 15 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 8 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ members = [
"vortex-flatbuffers",
"vortex-metrics",
"vortex-io",
"vortex-object-store-opendal",
"vortex-cloud",
"vortex-proto",
"vortex-array",
"vortex-arrow",
Expand Down Expand Up @@ -95,7 +95,7 @@ rust-version = "1.91.0"
version = "0.1.0"

[workspace.dependencies]
anyhow = "1.0.97"
anyhow = "1.0.100"
arbitrary = "1.3.2"
arc-swap = "1.9"
arcref = "0.2.0"
Expand Down Expand Up @@ -173,7 +173,7 @@ indicatif = "0.18.0"
insta = "1.43"
inventory = "0.3.20"
itertools = "0.14.0"
jiff = "0.2.0"
jiff = "0.2.17"
jni = { version = "0.22.0" }
kanal = "0.1.1"
lasso = { version = "0.7", features = ["multi-threaded", "inline-more"] }
Expand All @@ -191,9 +191,11 @@ noodles-vcf = { version = "0.88.0", features = ["async"] }
num-traits = "0.2.19"
num_enum = { version = "0.7.3", default-features = false }
object_store = { version = "0.13.2", default-features = false }
object_store_opendal = "0.57.0"
once_cell = "1.21"
oneshot = { version = "0.2.0", features = ["async"] }
onpair = "0.1.1"
opendal = { version = "0.57.0", default-features = false }
opentelemetry = "0.32.0"
opentelemetry-otlp = "0.32.0"
opentelemetry_sdk = "0.32.0"
Expand Down Expand Up @@ -232,7 +234,7 @@ rstest = "0.26.1"
rstest_reuse = "0.7.0"
rustc-hash = "2.1.1"
rustix = { version = "1.1", features = ["fs"] }
serde = "1.0.220"
serde = "1.0.221"
serde_json = "1.0.138"
serde_test = "1.0.176"
sha2 = "0.11.0"
Expand Down Expand Up @@ -275,7 +277,7 @@ tracing-perfetto = "0.1.5"
tracing-subscriber = "0.3"
url = "2.5.7"
uuid = { version = "1.23", features = ["js"] }
wasm-bindgen-futures = "0.4.54"
wasm-bindgen-futures = "0.4.58"
wkb = "0.9.2"
xshell = "0.2.6"
zigzag = "0.1.0"
Expand All @@ -292,6 +294,7 @@ vortex-arrow = { version = "0.1.0", path = "./vortex-arrow", default-features =
vortex-btrblocks = { version = "0.1.0", path = "./vortex-btrblocks", default-features = false }
vortex-buffer = { version = "0.1.0", path = "./vortex-buffer", default-features = false }
vortex-bytebool = { version = "0.1.0", path = "./encodings/bytebool", default-features = false }
vortex-cloud = { version = "0.1.0", path = "./vortex-cloud", default-features = false }
vortex-compressor = { version = "0.1.0", path = "./vortex-compressor", default-features = false }
vortex-compute = { version = "0.1.0", path = "./vortex-compute", default-features = false }
vortex-datafusion = { version = "0.1.0", path = "./vortex-datafusion", default-features = false }
Expand Down
50 changes: 28 additions & 22 deletions docs/api/python/store/opendal.rst
Original file line number Diff line number Diff line change
@@ -1,13 +1,29 @@
=============
OpenDAL (COS)
=============
==================
OpenDAL (COS, OSS)
==================

Vortex can read from and write to Tencent Cloud COS through
Vortex can read from and write to Tencent Cloud COS and Alibaba Cloud OSS through
`OpenDAL <https://opendal.apache.org/>`_, which provides native service support.

This store is available only when Vortex is built with the ``opendal`` feature
These stores are available only when Vortex is built with the ``opendal`` feature
(e.g. ``maturin develop --features opendal`` or ``cargo build -p vortex-jni --features opendal``).

.. list-table::
:header-rows: 1

* - Scheme
- Service
- Endpoint variable
- Credential variables
* - ``cos://``
- Tencent Cloud COS
- ``COS_ENDPOINT``
- ``TENCENTCLOUD_SECRET_ID``, ``TENCENTCLOUD_SECRET_KEY``
* - ``oss://``
- Alibaba Cloud OSS
- ``OSS_ENDPOINT``
- ``ALIBABA_CLOUD_ACCESS_KEY_ID``, ``ALIBABA_CLOUD_ACCESS_KEY_SECRET``

:class:`vortex.store.CosStore`
==============================

Expand Down Expand Up @@ -63,25 +79,15 @@ Or configure explicitly with :class:`~vortex.store.CosStore` and pass it to
# bucket are not part of the path passed to read_url.
a = read_url("path/to/dataset.vortex", store=store)

Passing a store object directly
===============================
Reading from OSS
================

``CosStore`` is a concrete store object. You can build one once and pass it
directly to :func:`vortex.io.read_url` / :func:`vortex.io.write` via the ``store=`` argument,
exactly like the built-in S3/Azure/GCS stores:
Alibaba Cloud OSS is reachable by URL. There is no standalone ``OssStore`` class yet, so
configuration comes from the environment variables OpenDAL's OSS builder reads
(``ALIBABA_CLOUD_ACCESS_KEY_ID``, ``ALIBABA_CLOUD_ACCESS_KEY_SECRET`` and ``OSS_ENDPOINT``):

.. code-block:: python

from vortex.io import read_url
from vortex.store import CosStore

store = CosStore(
bucket="my-bucket",
endpoint="https://cos.ap-guangzhou.myqcloud.com",
secret_id="AKID...",
secret_key="...",
)
import vortex as vx

# When `store=` is supplied, the path is resolved as a key within the store, so the scheme
# and bucket are not part of the path passed to read_url.
a = read_url("path/to/dataset.vortex", store=store)
a = vx.io.read_url("oss://my-bucket/path/to/dataset.vortex")
59 changes: 59 additions & 0 deletions vortex-cloud/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
[package]
name = "vortex-cloud"
description = "Cloud object store integration for Vortex: URL resolution and OpenDAL-backed services"
version = { workspace = true }
homepage = { workspace = true }
repository = { workspace = true }
authors = { workspace = true }
license = { workspace = true }
keywords = { workspace = true }
include = { workspace = true }
edition = { workspace = true }
readme = { workspace = true }
rust-version = { workspace = true }
categories = { workspace = true }

[package.metadata.docs.rs]
all-features = true

[dependencies]
object_store = { workspace = true, features = ["fs"] }
object_store_opendal = { workspace = true, optional = true }
opendal = { workspace = true, optional = true }
parking_lot = { workspace = true, optional = true }
tracing = { workspace = true, optional = true }
url = { workspace = true }
vortex-utils = { workspace = true }

[features]
default = []
# The URL -> ObjectStore registry, plus the cloud backends it resolves URLs to. Kept optional so
# that a consumer needing only an OpenDAL store does not pull in the native cloud backends.
registry = [
"dep:parking_lot",
"object_store/aws",
"object_store/azure",
"object_store/gcp",
"object_store/http",
]
# Tencent Cloud COS, the `cos://` scheme.
cos = [
"dep:opendal",
"dep:object_store_opendal",
"dep:tracing",
"object_store/cloud",
"opendal/services-cos",
]
# Alibaba Cloud OSS, the `oss://` scheme.
oss = [
"dep:opendal",
"dep:object_store_opendal",
"dep:tracing",
"object_store/cloud",
"opendal/services-oss",
]
# Every OpenDAL-backed service.
opendal = ["cos", "oss"]

[lints]
workspace = true
Loading
Loading