Skip to content

Commit 3473330

Browse files
committed
feat: extend configuration system
1 parent ec84132 commit 3473330

File tree

10 files changed

+524
-107
lines changed

10 files changed

+524
-107
lines changed

Cargo.lock

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
members = ["object-store"]
33

44
[patch.crates-io]
5-
object_store = { git = "https://github.com/apache/arrow-rs", rev = "2408bb274e82c785cca9b4596cd8f201ccc5d7c6" }
5+
object_store = { git = "https://github.com/apache/arrow-rs", rev = "1889e33da31218ee2c58ad874036b17b699538b9" }

object-store/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ bytes = "1.2.1"
1010
futures = "0.3"
1111
once_cell = "1.12.0"
1212
object_store = { version = "0.5.2", features = ["azure", "aws", "gcp"] }
13+
percent-encoding = "2"
1314
pyo3 = { version = "0.17.1", features = [
1415
"extension-module",
1516
"abi3",

object-store/src/builder.rs

Lines changed: 114 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -8,35 +8,96 @@ use object_store::local::LocalFileSystem;
88
use object_store::memory::InMemory;
99
use object_store::path::Path;
1010
use object_store::prefix::PrefixObjectStore;
11-
use object_store::{ClientOptions, DynObjectStore, Result as ObjectStoreResult};
11+
use object_store::{
12+
ClientOptions, DynObjectStore, Error as ObjectStoreError, Result as ObjectStoreResult,
13+
RetryConfig,
14+
};
1215
use url::Url;
1316

14-
use crate::settings::AzureConfig;
17+
use crate::config::{aws::S3Config, azure::AzureConfig, google::GoogleConfig};
1518

16-
pub enum ObjectStoreImpl {
19+
enum ObjectStoreKind {
20+
Local,
21+
InMemory,
22+
S3,
23+
Google,
24+
Azure,
25+
}
26+
27+
impl ObjectStoreKind {
28+
pub fn parse_url(url: &Url) -> ObjectStoreResult<Self> {
29+
match url.scheme() {
30+
"file" => Ok(ObjectStoreKind::Local),
31+
"memory" => Ok(ObjectStoreKind::InMemory),
32+
"az" | "abfs" | "abfss" | "azure" | "wasb" | "adl" => Ok(ObjectStoreKind::Azure),
33+
"s3" | "s3a" => Ok(ObjectStoreKind::S3),
34+
"gs" => Ok(ObjectStoreKind::Google),
35+
"https" => {
36+
let host = url.host_str().unwrap_or_default();
37+
if host.contains("amazonaws.com") {
38+
Ok(ObjectStoreKind::S3)
39+
} else if host.contains("dfs.core.windows.net")
40+
|| host.contains("blob.core.windows.net")
41+
{
42+
Ok(ObjectStoreKind::Azure)
43+
} else {
44+
Err(ObjectStoreError::NotImplemented)
45+
}
46+
}
47+
_ => Err(ObjectStoreError::NotImplemented),
48+
}
49+
}
50+
}
51+
52+
enum ObjectStoreImpl {
1753
Local(LocalFileSystem),
54+
InMemory(InMemory),
1855
Azrue(MicrosoftAzure),
1956
S3(AmazonS3),
2057
Gcp(GoogleCloudStorage),
21-
InMemory(InMemory),
2258
}
2359

24-
pub struct StorageBuilder {
60+
impl ObjectStoreImpl {
61+
pub fn into_prefix(self, prefix: Path) -> Arc<DynObjectStore> {
62+
match self {
63+
ObjectStoreImpl::Local(store) => Arc::new(PrefixObjectStore::new(store, prefix)),
64+
ObjectStoreImpl::InMemory(store) => Arc::new(PrefixObjectStore::new(store, prefix)),
65+
ObjectStoreImpl::Azrue(store) => Arc::new(PrefixObjectStore::new(store, prefix)),
66+
ObjectStoreImpl::S3(store) => Arc::new(PrefixObjectStore::new(store, prefix)),
67+
ObjectStoreImpl::Gcp(store) => Arc::new(PrefixObjectStore::new(store, prefix)),
68+
}
69+
}
70+
71+
pub fn into_store(self) -> Arc<DynObjectStore> {
72+
match self {
73+
ObjectStoreImpl::Local(store) => Arc::new(store),
74+
ObjectStoreImpl::InMemory(store) => Arc::new(store),
75+
ObjectStoreImpl::Azrue(store) => Arc::new(store),
76+
ObjectStoreImpl::S3(store) => Arc::new(store),
77+
ObjectStoreImpl::Gcp(store) => Arc::new(store),
78+
}
79+
}
80+
}
81+
82+
#[derive(Debug, Clone)]
83+
pub struct ObjectStoreBuilder {
2584
url: String,
2685
prefix: Option<Path>,
2786
path_as_prefix: bool,
2887
options: HashMap<String, String>,
29-
client_options: ClientOptions,
88+
client_options: Option<ClientOptions>,
89+
retry_config: Option<RetryConfig>,
3090
}
3191

32-
impl StorageBuilder {
92+
impl ObjectStoreBuilder {
3393
pub fn new(url: impl Into<String>) -> Self {
3494
Self {
3595
url: url.into(),
3696
prefix: None,
3797
path_as_prefix: false,
3898
options: Default::default(),
39-
client_options: Default::default(),
99+
client_options: None,
100+
retry_config: None,
40101
}
41102
}
42103

@@ -55,39 +116,60 @@ impl StorageBuilder {
55116
self
56117
}
57118

119+
pub fn with_path_as_prefix(mut self, path_as_prefix: bool) -> Self {
120+
self.path_as_prefix = path_as_prefix;
121+
self
122+
}
123+
124+
pub fn with_client_options(mut self, options: ClientOptions) -> Self {
125+
self.client_options = Some(options);
126+
self
127+
}
128+
129+
pub fn with_retry_config(mut self, retry_config: RetryConfig) -> Self {
130+
self.retry_config = Some(retry_config);
131+
self
132+
}
133+
58134
pub fn build(mut self) -> ObjectStoreResult<Arc<DynObjectStore>> {
59-
let url = Url::parse(&self.url).unwrap();
60-
let root_store = match url.scheme() {
61-
"file" => ObjectStoreImpl::Local(LocalFileSystem::new()),
62-
"memory" => ObjectStoreImpl::InMemory(InMemory::new()),
63-
"az" | "abfs" | "abfss" | "azure" | "wasb" | "adl" => {
64-
let mut builder = AzureConfig::get_builder(&url, &self.options)?;
65-
builder = builder.with_client_options(self.client_options);
135+
let url = Url::parse(&self.url).map_err(|err| ObjectStoreError::Generic {
136+
store: "Generic",
137+
source: Box::new(err),
138+
})?;
139+
let root_store = match ObjectStoreKind::parse_url(&url).unwrap() {
140+
ObjectStoreKind::Local => ObjectStoreImpl::Local(LocalFileSystem::new()),
141+
ObjectStoreKind::InMemory => ObjectStoreImpl::InMemory(InMemory::new()),
142+
ObjectStoreKind::Azure => {
143+
let mut builder = AzureConfig::get_builder(&self.url, &self.options)?;
144+
builder = builder
145+
.with_client_options(self.client_options.unwrap_or_default())
146+
.with_retry(self.retry_config.unwrap_or_default());
66147
ObjectStoreImpl::Azrue(builder.build()?)
67148
}
68-
"s3" | "s3a" => todo!(),
69-
"gs" => todo!(),
70-
"https" => todo!(),
71-
_ => todo!(),
149+
ObjectStoreKind::S3 => {
150+
let mut builder = S3Config::get_builder(&self.url, &self.options)?;
151+
builder = builder
152+
.with_client_options(self.client_options.unwrap_or_default())
153+
.with_retry(self.retry_config.unwrap_or_default());
154+
ObjectStoreImpl::S3(builder.build()?)
155+
}
156+
ObjectStoreKind::Google => {
157+
let mut builder = GoogleConfig::get_builder(&self.url, &self.options)?;
158+
builder = builder
159+
.with_client_options(self.client_options.unwrap_or_default())
160+
.with_retry(self.retry_config.unwrap_or_default());
161+
ObjectStoreImpl::Gcp(builder.build()?)
162+
}
72163
};
73164

74165
if self.path_as_prefix && !url.path().is_empty() && self.prefix.is_none() {
75166
self.prefix = Some(Path::from(url.path()))
76167
}
77168

78-
let store: Arc<DynObjectStore> = if let Some(prefix) = self.prefix {
79-
match root_store {
80-
ObjectStoreImpl::Local(store) => Arc::new(PrefixObjectStore::new(store, prefix)),
81-
ObjectStoreImpl::InMemory(store) => Arc::new(PrefixObjectStore::new(store, prefix)),
82-
_ => todo!(),
83-
}
169+
if let Some(prefix) = self.prefix {
170+
Ok(root_store.into_prefix(prefix))
84171
} else {
85-
match root_store {
86-
ObjectStoreImpl::Local(store) => Arc::new(store),
87-
ObjectStoreImpl::InMemory(store) => Arc::new(store),
88-
_ => todo!(),
89-
}
90-
};
91-
Ok(store)
172+
Ok(root_store.into_store())
173+
}
92174
}
93175
}

0 commit comments

Comments
 (0)