-
Notifications
You must be signed in to change notification settings - Fork 842
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Return PutResult
with an ETag from ObjectStore::put (#4934)
#4944
Changes from 4 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -59,7 +59,7 @@ use crate::multipart::{PartId, PutPart, WriteMultiPart}; | |
use crate::signer::Signer; | ||
use crate::{ | ||
ClientOptions, GetOptions, GetResult, ListResult, MultipartId, ObjectMeta, | ||
ObjectStore, Path, Result, RetryConfig, | ||
ObjectStore, Path, PutResult, Result, RetryConfig, | ||
}; | ||
|
||
mod checksum; | ||
|
@@ -109,12 +109,6 @@ enum Error { | |
#[snafu(display("Missing SecretAccessKey"))] | ||
MissingSecretAccessKey, | ||
|
||
#[snafu(display("ETag Header missing from response"))] | ||
MissingEtag, | ||
|
||
#[snafu(display("Received header containing non-ASCII data"))] | ||
BadHeader { source: reqwest::header::ToStrError }, | ||
|
||
#[snafu(display("Unable parse source url. Url: {}, Error: {}", url, source))] | ||
UnableToParseUrl { | ||
source: url::ParseError, | ||
|
@@ -273,9 +267,9 @@ impl Signer for AmazonS3 { | |
|
||
#[async_trait] | ||
impl ObjectStore for AmazonS3 { | ||
async fn put(&self, location: &Path, bytes: Bytes) -> Result<()> { | ||
self.client.put_request(location, bytes, &()).await?; | ||
Ok(()) | ||
async fn put(&self, location: &Path, bytes: Bytes) -> Result<PutResult> { | ||
let e_tag = self.client.put_request(location, bytes, &()).await?; | ||
Ok(PutResult { e_tag: Some(e_tag) }) | ||
} | ||
|
||
async fn put_multipart( | ||
|
@@ -365,10 +359,9 @@ struct S3MultiPartUpload { | |
#[async_trait] | ||
impl PutPart for S3MultiPartUpload { | ||
async fn put_part(&self, buf: Vec<u8>, part_idx: usize) -> Result<PartId> { | ||
use reqwest::header::ETAG; | ||
let part = (part_idx + 1).to_string(); | ||
|
||
let response = self | ||
let content_id = self | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is there a reason this is called There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's because PartId is used across multiple stores, and for some of them this isn't an etag but a part number |
||
.client | ||
.put_request( | ||
&self.location, | ||
|
@@ -377,13 +370,7 @@ impl PutPart for S3MultiPartUpload { | |
) | ||
.await?; | ||
|
||
let etag = response.headers().get(ETAG).context(MissingEtagSnafu)?; | ||
|
||
let etag = etag.to_str().context(BadHeaderSnafu)?; | ||
|
||
Ok(PartId { | ||
content_id: etag.to_string(), | ||
}) | ||
Ok(PartId { content_id }) | ||
} | ||
|
||
async fn complete(&self, completed_parts: Vec<PartId>) -> Result<()> { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,7 +31,7 @@ use crate::{ | |
multipart::{PartId, PutPart, WriteMultiPart}, | ||
path::Path, | ||
ClientOptions, GetOptions, GetResult, ListResult, MultipartId, ObjectMeta, | ||
ObjectStore, Result, RetryConfig, | ||
ObjectStore, PutResult, Result, RetryConfig, | ||
}; | ||
use async_trait::async_trait; | ||
use base64::prelude::BASE64_STANDARD; | ||
|
@@ -62,6 +62,7 @@ mod credential; | |
/// [`CredentialProvider`] for [`MicrosoftAzure`] | ||
pub type AzureCredentialProvider = | ||
Arc<dyn CredentialProvider<Credential = AzureCredential>>; | ||
use crate::client::header::get_etag; | ||
pub use credential::AzureCredential; | ||
|
||
const STORE: &str = "MicrosoftAzure"; | ||
|
@@ -81,9 +82,6 @@ const MSI_ENDPOINT_ENV_KEY: &str = "IDENTITY_ENDPOINT"; | |
#[derive(Debug, Snafu)] | ||
#[allow(missing_docs)] | ||
enum Error { | ||
#[snafu(display("Received header containing non-ASCII data"))] | ||
BadHeader { source: reqwest::header::ToStrError }, | ||
|
||
#[snafu(display("Unable parse source url. Url: {}, Error: {}", url, source))] | ||
UnableToParseUrl { | ||
source: url::ParseError, | ||
|
@@ -126,8 +124,10 @@ enum Error { | |
#[snafu(display("Configuration key: '{}' is not known.", key))] | ||
UnknownConfigurationKey { key: String }, | ||
|
||
#[snafu(display("ETag Header missing from response"))] | ||
MissingEtag, | ||
#[snafu(display("Unable to extract metadata from headers: {}", source))] | ||
Metadata { | ||
source: crate::client::header::Error, | ||
}, | ||
} | ||
|
||
impl From<Error> for super::Error { | ||
|
@@ -170,11 +170,13 @@ impl std::fmt::Display for MicrosoftAzure { | |
|
||
#[async_trait] | ||
impl ObjectStore for MicrosoftAzure { | ||
async fn put(&self, location: &Path, bytes: Bytes) -> Result<()> { | ||
self.client | ||
async fn put(&self, location: &Path, bytes: Bytes) -> Result<PutResult> { | ||
let response = self | ||
.client | ||
.put_request(location, Some(bytes), false, &()) | ||
.await?; | ||
Ok(()) | ||
let e_tag = Some(get_etag(response.headers()).context(MetadataSnafu)?); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it guaranteed that these services (and their emulators, etc) all return an ETag? I wonder if this should be an error, or if the etag isn't present in the response, this should return There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The actual object stores guarantee it is present, the same is technically true of WebDav, but given HTTPStore gets used for more than that I opted to not make it so strict |
||
Ok(PutResult { e_tag }) | ||
} | ||
|
||
async fn put_multipart( | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this structure (
S3Client
) is not public, so this is not a breaking API change in case anyone else was wondering