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: Support object soft delete #12060

Merged
merged 3 commits into from
Mar 25, 2024

Conversation

amanda-tarafa
Copy link
Contributor

No description provided.

@amanda-tarafa amanda-tarafa requested review from a team as code owners March 6, 2024 08:58
@amanda-tarafa amanda-tarafa added the do not merge Indicates a pull request not ready for merge, due to either quality or timing. label Mar 6, 2024
@amanda-tarafa
Copy link
Contributor Author

do not merge until the RestoreObjectRequest changes (remove the Object body) have been published in Google.Apis.Storage.v1.

Copy link
Collaborator

@jskeet jskeet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just comment nits and an observation about the underlying API.

Name = name,
Versioning = new Bucket.VersioningData { Enabled = multiVersion },
// The minimum allowed for soft delete is 7 days.
SoftDeletePolicy = softDelete ? new Bucket.SoftDeletePolicyData { RetentionDurationSeconds = 7*24*60*60 } : null,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: spaces between the 7*24*60*60 - or better, work that out earlier:

var sevenDaysInSeconds = (int) TimeSpan.FromDays(7).TotalSeconds;

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Or preferably NodaConstants.SecondsPerWeek, but hey... one day I'll justify a NodaTime dependency ;)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, using TimeSpan.

@@ -30,6 +30,11 @@ public sealed class GetObjectOptions
/// </summary>
public long? Generation { get; set; }

/// <summary>
/// If true, only soft-deleted object versions will be listed. The default is false.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're not listing, just getting, so this should probably be "only soft-deleted object versions will be retrieved" or similar.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, changing it. I did copied this verbatim from the API field docs.

public bool? CopySourceAcl { get; set; }

/// <summary>
/// The projection of the restored objct to return.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possibly make it clear that this doesn't affect what's actually restored?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, done.

/// there are no live versions of the object.
/// </summary>
/// <remarks>
/// Note that you specify the generation value when calling the one of the restore object operations.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should reword this remark to clarify the difference between the value of this property and the value specified on the RestoreObject call.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Done here and elsewhere.

/// Makes the operation conditional on whether the object's current
/// metageneration matches the given value.
/// </summary>
/// <remarks>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possibly remove the remark here and below as the metageneration and generation are different?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've reworded in a similar way as the above, but I'm happy to remove the remarks here entirely.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think with the change in the remarks, this makes a lot more sense to keep, thanks.

/// </summary>
/// <param name="bucket">The name of the bucket containing the object. Must not be null.</param>
/// <param name="objectName">The name of the object to restore. Must not be null.</param>
/// <param name="generation">The specific revision of the object to restore.</param>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does Storage use the term "revision"? Maybe we should use "generation" here instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The underlying docs read: "Selects a specific revision of this object." and the underlying parameter is named "generation" :(

They may be used interchangeably by Storage? I'm happy yo change to generation if you think it better?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's stick with the underlying docs for consistency with them (even if they're inconsistent themselves).

/// <param name="generation">The specific revision of the object to restore.</param>
/// <param name="options">Additional options for the restore operation. May be null, in which case appropriate
/// defaults will be used.</param>
/// <returns>The <see cref="Object"/> representation restored Storage object.</returns>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add "of the" between "representation" and "restored".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Contributor Author

@amanda-tarafa amanda-tarafa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jskeet all comments addressed in a new commit prefixed review:, PTAL.

Name = name,
Versioning = new Bucket.VersioningData { Enabled = multiVersion },
// The minimum allowed for soft delete is 7 days.
SoftDeletePolicy = softDelete ? new Bucket.SoftDeletePolicyData { RetentionDurationSeconds = 7*24*60*60 } : null,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, using TimeSpan.

@@ -30,6 +30,11 @@ public sealed class GetObjectOptions
/// </summary>
public long? Generation { get; set; }

/// <summary>
/// If true, only soft-deleted object versions will be listed. The default is false.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, changing it. I did copied this verbatim from the API field docs.

public bool? CopySourceAcl { get; set; }

/// <summary>
/// The projection of the restored objct to return.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, done.

/// there are no live versions of the object.
/// </summary>
/// <remarks>
/// Note that you specify the generation value when calling the one of the restore object operations.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Done here and elsewhere.

/// Makes the operation conditional on whether the object's current
/// metageneration matches the given value.
/// </summary>
/// <remarks>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've reworded in a similar way as the above, but I'm happy to remove the remarks here entirely.

/// </summary>
/// <param name="bucket">The name of the bucket containing the object. Must not be null.</param>
/// <param name="objectName">The name of the object to restore. Must not be null.</param>
/// <param name="generation">The specific revision of the object to restore.</param>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The underlying docs read: "Selects a specific revision of this object." and the underlying parameter is named "generation" :(

They may be used interchangeably by Storage? I'm happy yo change to generation if you think it better?

/// <param name="generation">The specific revision of the object to restore.</param>
/// <param name="options">Additional options for the restore operation. May be null, in which case appropriate
/// defaults will be used.</param>
/// <returns>The <see cref="Object"/> representation restored Storage object.</returns>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

/// <remarks>
/// Note that the generation value passed to the restore operations (a) specifies the exact generation
/// that should be restored, whereas this value (b) is a constraint on the current generation of the object
/// for the oepration to succeed. Basically, restore version a if current generation is not b.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oepration => operation

And I'd possibly parenthesize a and b in the final sentence again, to match the previous sentence. Possibly rephrase the final sentence to:

Effectively, this means "restore version (a) if the current generation is not (b)".

(There's something about "basically" which doesn't sit quite right with me...)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All done, here and in the others.

/// Makes the operation conditional on whether the object's current
/// metageneration matches the given value.
/// </summary>
/// <remarks>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think with the change in the remarks, this makes a lot more sense to keep, thanks.

/// </summary>
/// <param name="bucket">The name of the bucket containing the object. Must not be null.</param>
/// <param name="objectName">The name of the object to restore. Must not be null.</param>
/// <param name="generation">The specific revision of the object to restore.</param>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's stick with the underlying docs for consistency with them (even if they're inconsistent themselves).

Copy link
Contributor Author

@amanda-tarafa amanda-tarafa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Latest review addressed in last commit.
And now we wait.

/// <remarks>
/// Note that the generation value passed to the restore operations (a) specifies the exact generation
/// that should be restored, whereas this value (b) is a constraint on the current generation of the object
/// for the oepration to succeed. Basically, restore version a if current generation is not b.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All done, here and in the others.

@amanda-tarafa
Copy link
Contributor Author

@jskeet this can now be merged. Last commit are the changes required because of the Discovery based breaking changes. PTAL.

@amanda-tarafa amanda-tarafa removed the do not merge Indicates a pull request not ready for merge, due to either quality or timing. label Mar 25, 2024
Copy link
Collaborator

@jskeet jskeet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few nits, but that's all.

@@ -0,0 +1,50 @@
// Copyright 2015 Google Inc. All Rights Reserved.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: 2024.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

public bool? CopySourceAcl { get; set; }

/// <summary>
/// The projection of the restored objct to return. Note the whole object will be restored,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: objct => object

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

/// <summary>
/// The projection of the restored objct to return. Note the whole object will be restored,
/// except for the object's access controls, see <see cref="CopySourceAcl"/> for that. This only affects
/// what information is returned when restoration is succesful.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: succesful => successful

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Prefixes are available through `PagedEnumerable<Objects, Object>.AsRawResponses()` it's not ideal but it's not awful either. If we get actual user demand for ease of access we can reconsider.
Copy link
Contributor Author

@amanda-tarafa amanda-tarafa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All comments addressed. Will merge on green.

@@ -0,0 +1,50 @@
// Copyright 2015 Google Inc. All Rights Reserved.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

public bool? CopySourceAcl { get; set; }

/// <summary>
/// The projection of the restored objct to return. Note the whole object will be restored,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

/// <summary>
/// The projection of the restored objct to return. Note the whole object will be restored,
/// except for the object's access controls, see <see cref="CopySourceAcl"/> for that. This only affects
/// what information is returned when restoration is succesful.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@amanda-tarafa amanda-tarafa merged commit ae28cb4 into googleapis:main Mar 25, 2024
10 checks passed
@amanda-tarafa amanda-tarafa deleted the storage-soft-delete branch March 25, 2024 17:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants