Problem or motivation
Summary
Vortex currently has OpenDAL-backed object store support for Tencent Cloud COS (cos://) and Alibaba Cloud OSS (oss://) in vortex-cloud, but no support for Tencent Cloud GooseFS — a distributed caching file system that is widely used as a high-performance data layer for analytics workloads on top of on-prem or hybrid-cloud storage.
GooseFS exposes a HDFS-like gRPC API rather than a REST-style S3-compatible API, so it is not natively supported by the object_store crate. Users who store Vortex datasets on GooseFS clusters today have no way to read/write them through vortex.io.read_url(...) / vortex.io.write(...) or through the Registry-based URL resolution.
Use case
Several Vortex users (both in production and on the Lance ecosystem side) deploy datasets against GooseFS to get cache-accelerated reads without paying S3 egress. Without GooseFS support in vortex-cloud, those users either fall back to local caching or duplicate the dataset onto an S3-compatible store — both of which defeat GooseFS's positioning as the primary storage tier.
Concretely, we need:
- A
goosefs:// URL scheme that the Registry can resolve to a usable object_store::ObjectStore.
- A strongly-typed builder (mirroring
CosConfig / OssConfig) so Python callers and the JNI layer can construct a store from explicit configuration.
- Python bindings equivalent to
CosStore so vortex.io.read_url(url, store=goosefs_store) works.
Why now
OpenDAL already ships a stable opendal-service-goosefs backend that wraps the official goosefs-sdk gRPC client. The bridging work is entirely on the Vortex side and is structurally identical to the existing COS/OSS implementations, so this is a low-risk incremental addition rather than a new architectural piece.
Proposed solution
Implementation outline
Mirror the existing cos / oss implementation pattern in vortex-cloud (see vortex-cloud/src/opendal/{cos,oss}.rs):
- New
opendal feature subgroup goosefs in vortex-cloud/Cargo.toml that pulls in opendal, object_store_opendal, tracing, and opendal/services-goosefs.
- New
vortex-cloud/src/opendal/goosefs.rs module exposing:
GOOSEFS_SCHEME: &str = "goosefs"
GoosefsConfig { master_addr, root, block_size, chunk_size, write_type, auth_type, auth_username }
make_goosefs_store(config) -> Result<Arc<dyn ObjectStore>, OpenDALStoreError>
url_and_properties_to_config(url, properties, env_lookup) with master_addr resolved as: properties["master_addr"] → URL authority (host:port) → GOOSEFS_MASTER_ADDR env var.
- Wire
goosefs into the existing dispatch in vortex-cloud/src/opendal/mod.rs (SUPPORTED_SCHEMES, make_opendal_store_with_env match arm) and the Registry's OpenDAL cfg gates in vortex-cloud/src/registry/mod.rs.
- Python bindings in
vortex-python:
GoosefsStore pyclass (mirroring CosStore) with the same keyword-only options as GoosefsConfig.
- Extend
AnyVortexStore to accept GoosefsStore in read_url / write.
vortex.store._goosefs module with a graceful ImportError placeholder when the opendal feature is disabled.
- Add
GoosefsStore to the .pyi type stub and to vortex.store.ObjectStore union + __all__.
Behavior contract
goosefs://<master-addr>:<port>/<path> → master address from the URL authority, root prefix optional from properties["root"].
goosefs:///<path> with GOOSEFS_MASTER_ADDR=10.0.0.1:9200 in the environment → store built from the env var.
master_addr empty after all fallback layers → OpenDALStoreError::MissingConfig("master_addr") (deterministic regardless of the process environment, using a fixed env_lookup in tests).
- HA mode (
master_addr="host1:9200,host2:9200,host3:9200") is accepted and the OpenDAL client uses PollingMasterInquireClient to discover the primary master.
Testing
- Unit tests in
vortex-cloud/src/opendal/goosefs.rs covering: missing master_addr, URL-authority fallback, env-var fallback, property override precedence, HA build, and explicit-config build.
- Existing
supports_scheme_tracks_enabled_features and every_supported_scheme_dispatches tests extended to cover the goosefs feature.
- All 22 tests in
vortex-cloud (cos + oss + goosefs) must pass with cargo test -p vortex-cloud --features cos,oss,goosefs.
cargo clippy -p vortex-cloud --features cos,oss,goosefs and cargo +nightly fmt --check must pass.
Dependency notes
- No new direct workspace dependency required.
goosefs-sdk v0.1.8 is pulled transitively through opendal-service-goosefs v0.57.0, which is what we want — pinning goosefs-sdk directly in the workspace would force a second upgrade every time opendal-service-goosefs bumps.
- The PR targets
develop with opendal = "0.57.0" and object_store = "0.13.2" (datafusion 54 compatible). A follow-up to bump opendal to 0.58.1 is tracked separately and depends on datafusion moving to object_store 0.14.
Additional context
No response
Problem or motivation
Summary
Vortex currently has OpenDAL-backed object store support for Tencent Cloud COS (
cos://) and Alibaba Cloud OSS (oss://) invortex-cloud, but no support for Tencent Cloud GooseFS — a distributed caching file system that is widely used as a high-performance data layer for analytics workloads on top of on-prem or hybrid-cloud storage.GooseFS exposes a HDFS-like gRPC API rather than a REST-style S3-compatible API, so it is not natively supported by the
object_storecrate. Users who store Vortex datasets on GooseFS clusters today have no way to read/write them throughvortex.io.read_url(...)/vortex.io.write(...)or through theRegistry-based URL resolution.Use case
Several Vortex users (both in production and on the Lance ecosystem side) deploy datasets against GooseFS to get cache-accelerated reads without paying S3 egress. Without GooseFS support in
vortex-cloud, those users either fall back to local caching or duplicate the dataset onto an S3-compatible store — both of which defeat GooseFS's positioning as the primary storage tier.Concretely, we need:
goosefs://URL scheme that theRegistrycan resolve to a usableobject_store::ObjectStore.CosConfig/OssConfig) so Python callers and the JNI layer can construct a store from explicit configuration.CosStoresovortex.io.read_url(url, store=goosefs_store)works.Why now
OpenDAL already ships a stable
opendal-service-goosefsbackend that wraps the officialgoosefs-sdkgRPC client. The bridging work is entirely on the Vortex side and is structurally identical to the existing COS/OSS implementations, so this is a low-risk incremental addition rather than a new architectural piece.Proposed solution
Implementation outline
Mirror the existing
cos/ossimplementation pattern invortex-cloud(seevortex-cloud/src/opendal/{cos,oss}.rs):opendalfeature subgroupgoosefsinvortex-cloud/Cargo.tomlthat pulls inopendal,object_store_opendal,tracing, andopendal/services-goosefs.vortex-cloud/src/opendal/goosefs.rsmodule exposing:GOOSEFS_SCHEME: &str = "goosefs"GoosefsConfig { master_addr, root, block_size, chunk_size, write_type, auth_type, auth_username }make_goosefs_store(config) -> Result<Arc<dyn ObjectStore>, OpenDALStoreError>url_and_properties_to_config(url, properties, env_lookup)withmaster_addrresolved as:properties["master_addr"]→ URL authority (host:port) →GOOSEFS_MASTER_ADDRenv var.goosefsinto the existing dispatch invortex-cloud/src/opendal/mod.rs(SUPPORTED_SCHEMES,make_opendal_store_with_envmatch arm) and theRegistry's OpenDAL cfg gates invortex-cloud/src/registry/mod.rs.vortex-python:GoosefsStorepyclass (mirroringCosStore) with the same keyword-only options asGoosefsConfig.AnyVortexStoreto acceptGoosefsStoreinread_url/write.vortex.store._goosefsmodule with a gracefulImportErrorplaceholder when theopendalfeature is disabled.GoosefsStoreto the.pyitype stub and tovortex.store.ObjectStoreunion +__all__.Behavior contract
goosefs://<master-addr>:<port>/<path>→ master address from the URL authority, root prefix optional fromproperties["root"].goosefs:///<path>withGOOSEFS_MASTER_ADDR=10.0.0.1:9200in the environment → store built from the env var.master_addrempty after all fallback layers →OpenDALStoreError::MissingConfig("master_addr")(deterministic regardless of the process environment, using a fixedenv_lookupin tests).master_addr="host1:9200,host2:9200,host3:9200") is accepted and the OpenDAL client usesPollingMasterInquireClientto discover the primary master.Testing
vortex-cloud/src/opendal/goosefs.rscovering: missing master_addr, URL-authority fallback, env-var fallback, property override precedence, HA build, and explicit-config build.supports_scheme_tracks_enabled_featuresandevery_supported_scheme_dispatchestests extended to cover thegoosefsfeature.vortex-cloud(cos + oss + goosefs) must pass withcargo test -p vortex-cloud --features cos,oss,goosefs.cargo clippy -p vortex-cloud --features cos,oss,goosefsandcargo +nightly fmt --checkmust pass.Dependency notes
goosefs-sdk v0.1.8is pulled transitively throughopendal-service-goosefs v0.57.0, which is what we want — pinninggoosefs-sdkdirectly in the workspace would force a second upgrade every timeopendal-service-goosefsbumps.developwithopendal = "0.57.0"andobject_store = "0.13.2"(datafusion 54 compatible). A follow-up to bumpopendalto0.58.1is tracked separately and depends on datafusion moving toobject_store 0.14.Additional context
No response