Skip to content
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

feat(core): object versioning APIs #2614

Merged
merged 2 commits into from
Jul 11, 2023
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: 2 additions & 2 deletions core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@ mod tests {
#[test]
fn assert_size() {
assert_eq!(24, size_of::<Operator>());
assert_eq!(240, size_of::<Entry>());
assert_eq!(216, size_of::<Metadata>());
assert_eq!(264, size_of::<Entry>());
assert_eq!(240, size_of::<Metadata>());
assert_eq!(1, size_of::<EntryMode>());
assert_eq!(24, size_of::<Scheme>());
}
Expand Down
43 changes: 41 additions & 2 deletions core/src/raw/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,27 @@ impl OpCreateDir {
///
/// The path must be normalized.
#[derive(Debug, Clone, Default)]
pub struct OpDelete {}
pub struct OpDelete {
version: Option<String>,
}

impl OpDelete {
/// Create a new `OpDelete`.
pub fn new() -> Self {
Self {}
Self::default()
}
}

impl OpDelete {
/// Change the version of this delete operation.
pub fn with_version(mut self, version: &str) -> Self {
self.version = Some(version.into());
self
}

/// Get the version of this delete operation.
pub fn version(&self) -> Option<&str> {
self.version.as_deref()
}
}

Expand Down Expand Up @@ -229,6 +244,7 @@ pub struct OpRead {
if_none_match: Option<String>,
override_cache_control: Option<String>,
override_content_disposition: Option<String>,
version: Option<String>,
}

impl OpRead {
Expand Down Expand Up @@ -292,13 +308,25 @@ impl OpRead {
pub fn if_none_match(&self) -> Option<&str> {
self.if_none_match.as_deref()
}

/// Set the version of the option
pub fn with_version(mut self, version: &str) -> Self {
self.version = Some(version.to_string());
self
}

/// Get version from option
pub fn version(&self) -> Option<&str> {
self.version.as_deref()
}
}

/// Args for `stat` operation.
#[derive(Debug, Clone, Default)]
pub struct OpStat {
if_match: Option<String>,
if_none_match: Option<String>,
version: Option<String>,
}

impl OpStat {
Expand Down Expand Up @@ -328,6 +356,17 @@ impl OpStat {
pub fn if_none_match(&self) -> Option<&str> {
self.if_none_match.as_deref()
}

/// Set the version of the option
pub fn with_version(mut self, version: &str) -> Self {
self.version = Some(version.to_string());
self
}

/// Get version from option
pub fn version(&self) -> Option<&str> {
self.version.as_deref()
}
}

/// Args for `write` operation.
Expand Down
40 changes: 40 additions & 0 deletions core/src/types/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ pub struct Metadata {
content_type: Option<String>,
etag: Option<String>,
last_modified: Option<DateTime<Utc>>,
version: Option<String>,
}

impl Metadata {
Expand All @@ -69,6 +70,7 @@ impl Metadata {
last_modified: None,
etag: None,
content_disposition: None,
version: None,
}
}

Expand Down Expand Up @@ -418,6 +420,42 @@ impl Metadata {
self.bit |= Metakey::ContentDisposition;
self
}

/// Version of this entry.
///
/// Version is a string that can be used to identify the version of this entry.
///
/// This field may come out from the version control system, like object versioning in AWS S3.
pub fn version(&self) -> Option<&str> {
debug_assert!(
self.bit.contains(Metakey::Version) || self.bit.contains(Metakey::Complete),
"visiting not set metadata: version, maybe a bug"
);

self.version.as_deref()
}

/// Set version of this entry.
///
/// Version is a string that can be used to identify the version of this entry.
///
/// This field may come out from the version control system, like object versioning in AWS S3.
pub fn with_version(mut self, v: String) -> Self {
self.version = Some(v);
self.bit |= Metakey::Version;
self
}

/// Set version of this entry.
///
/// Version is a string that can be used to identify the version of this entry.
///
/// This field may come out from the version control system, like object versioning in AWS S3.
pub fn set_version(&mut self, v: &str) -> &mut Self {
self.version = Some(v.to_string());
self.bit |= Metakey::Version;
self
}
}

flags! {
Expand Down Expand Up @@ -457,5 +495,7 @@ flags! {
Etag,
/// Key for last last modified.
LastModified,
/// Key for version.
Version,
}
}
39 changes: 37 additions & 2 deletions core/src/types/operator/operator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1073,11 +1073,46 @@ impl Operator {
/// # }
/// ```
pub async fn delete(&self, path: &str) -> Result<()> {
self.delete_with(path).await
}

/// Delete the given path with extra options.
///
/// # Notes
///
/// - Deleting a file that does not exist won't return errors.
///
/// # Examples
///
/// ```
/// # use anyhow::Result;
/// # use futures::io;
/// # use opendal::Operator;
///
/// # #[tokio::main]
/// # async fn test(op: Operator) -> Result<()> {
/// op.delete_with("test").await?;
/// # Ok(())
/// # }
/// ```
pub fn delete_with(&self, path: &str) -> FutureDelete {
let path = normalize_path(path);

let _ = self.inner().delete(&path, OpDelete::new()).await?;
let fut = FutureDelete(OperatorFuture::new(
self.inner().clone(),
path,
OpDelete::default(),
|inner, path, args| {
let fut = async move {
let _ = inner.delete(&path, args).await?;
Ok(())
};

Ok(())
Box::pin(fut)
},
));

fut
}

///
Expand Down
33 changes: 33 additions & 0 deletions core/src/types/operator/operator_futures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,12 @@ impl FutureStat {
self.0 = self.0.map_args(|args| args.with_if_none_match(v));
self
}

/// Set the version for this operation.
pub fn version(mut self, v: &str) -> Self {
self.0 = self.0.map_args(|args| args.with_version(v));
self
}
}

impl Future for FutureStat {
Expand Down Expand Up @@ -357,6 +363,12 @@ impl FutureRead {
self.0 = self.0.map_args(|args| args.with_if_none_match(v));
self
}

/// Set the version for this operation.
pub fn version(mut self, v: &str) -> Self {
self.0 = self.0.map_args(|args| args.with_version(v));
self
}
}

impl Future for FutureRead {
Expand Down Expand Up @@ -508,6 +520,27 @@ impl Future for FutureWriter {
}
}

/// Future that generated by [`Operator::delete_with`].
///
/// Users can add more options by public functions provided by this struct.
pub struct FutureDelete(pub(crate) OperatorFuture<OpDelete, ()>);

impl FutureDelete {
/// Change the version of this delete operation.
pub fn version(mut self, v: &str) -> Self {
self.0 = self.0.map_args(|args| args.with_version(v));
self
}
}

impl Future for FutureDelete {
type Output = Result<()>;

fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
self.0.poll_unpin(cx)
}
}

/// Future that generated by [`Operator::list_with`].
///
/// Users can add more options by public functions provided by this struct.
Expand Down