Skip to content

Commit 989f36f

Browse files
feat: add soft delete feature (#2403)
* feat: add soft delete feature * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * add softDeleteTime and hardDeleteTime object fields * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * add new fields to field tests * clirr ignore * remove debug comments * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * add softdeletetime and harddeletetime to grpc codec * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * fix read mask test * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * fix style issues * updates to apiary library * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * fix read mask test * fix typo --------- Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
1 parent 8074fff commit 989f36f

22 files changed

+654
-11
lines changed

google-cloud-storage/clirr-ignored-differences.xml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,24 @@
2727
<method>com.google.cloud.storage.BlobInfo$Builder setRetention(com.google.cloud.storage.BlobInfo$Retention)</method>
2828
</difference>
2929

30+
<difference>
31+
<differenceType>7013</differenceType>
32+
<className>com/google/cloud/storage/BucketInfo$Builder</className>
33+
<method>com.google.cloud.storage.BucketInfo$Builder setSoftDeletePolicy(com.google.cloud.storage.BucketInfo$SoftDeletePolicy)</method>
34+
</difference>
35+
36+
<difference>
37+
<differenceType>7012</differenceType>
38+
<className>com/google/cloud/storage/Storage</className>
39+
<method>com.google.cloud.storage.Blob restore(com.google.cloud.storage.BlobId, com.google.cloud.storage.Storage$BlobRestoreOption[])</method>
40+
</difference>
41+
42+
<difference>
43+
<differenceType>7012</differenceType>
44+
<className>com/google/cloud/storage/spi/v1/StorageRpc</className>
45+
<method>com.google.api.services.storage.model.StorageObject restore(com.google.api.services.storage.model.StorageObject, java.util.Map)</method>
46+
</difference>
47+
3048
<!-- @BetaApi members -->
3149
<difference>
3250
<differenceType>7009</differenceType>

google-cloud-storage/src/main/java/com/google/cloud/storage/Blob.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,18 @@ Builder setRetentionExpirationTimeOffsetDateTime(OffsetDateTime retentionExpirat
526526
return this;
527527
}
528528

529+
@Override
530+
Builder setSoftDeleteTime(OffsetDateTime softDeleteTime) {
531+
infoBuilder.setSoftDeleteTime(softDeleteTime);
532+
return this;
533+
}
534+
535+
@Override
536+
Builder setHardDeleteTime(OffsetDateTime hardDeleteTime) {
537+
infoBuilder.setHardDeleteTime(hardDeleteTime);
538+
return this;
539+
}
540+
529541
@Override
530542
public Builder setRetention(Retention retention) {
531543
infoBuilder.setRetention(retention);

google-cloud-storage/src/main/java/com/google/cloud/storage/BlobInfo.java

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ public class BlobInfo implements Serializable {
108108
private final Boolean temporaryHold;
109109
private final OffsetDateTime retentionExpirationTime;
110110
private final Retention retention;
111+
private final OffsetDateTime softDeleteTime;
112+
private final OffsetDateTime hardDeleteTime;
111113
private final transient ImmutableSet<NamedField> modifiedFields;
112114

113115
/** This class is meant for internal use only. Users are discouraged from using this class. */
@@ -525,6 +527,10 @@ Builder setRetentionExpirationTimeOffsetDateTime(OffsetDateTime retentionExpirat
525527
return setRetentionExpirationTime(millisOffsetDateTimeCodec.decode(retentionExpirationTime));
526528
}
527529

530+
abstract Builder setSoftDeleteTime(OffsetDateTime offsetDateTime);
531+
532+
abstract Builder setHardDeleteTime(OffsetDateTime hardDeleteTIme);
533+
528534
public abstract Builder setRetention(Retention retention);
529535

530536
/** Creates a {@code BlobInfo} object. */
@@ -626,6 +632,8 @@ static final class BuilderImpl extends Builder {
626632
private Boolean temporaryHold;
627633
private OffsetDateTime retentionExpirationTime;
628634
private Retention retention;
635+
private OffsetDateTime softDeleteTime;
636+
private OffsetDateTime hardDeleteTime;
629637
private final ImmutableSet.Builder<NamedField> modifiedFields = ImmutableSet.builder();
630638

631639
BuilderImpl(BlobId blobId) {
@@ -664,6 +672,8 @@ static final class BuilderImpl extends Builder {
664672
temporaryHold = blobInfo.temporaryHold;
665673
retentionExpirationTime = blobInfo.retentionExpirationTime;
666674
retention = blobInfo.retention;
675+
softDeleteTime = blobInfo.softDeleteTime;
676+
hardDeleteTime = blobInfo.hardDeleteTime;
667677
}
668678

669679
@Override
@@ -1037,6 +1047,24 @@ Builder setRetentionExpirationTimeOffsetDateTime(OffsetDateTime retentionExpirat
10371047
return this;
10381048
}
10391049

1050+
@Override
1051+
Builder setSoftDeleteTime(OffsetDateTime softDeleteTime) {
1052+
if (!Objects.equals(this.softDeleteTime, softDeleteTime)) {
1053+
modifiedFields.add(BlobField.SOFT_DELETE_TIME);
1054+
}
1055+
this.softDeleteTime = softDeleteTime;
1056+
return this;
1057+
}
1058+
1059+
@Override
1060+
Builder setHardDeleteTime(OffsetDateTime hardDeleteTime) {
1061+
if (!Objects.equals(this.hardDeleteTime, hardDeleteTime)) {
1062+
modifiedFields.add(BlobField.HARD_DELETE_TIME);
1063+
}
1064+
this.hardDeleteTime = hardDeleteTime;
1065+
return this;
1066+
}
1067+
10401068
@Override
10411069
public Builder setRetention(Retention retention) {
10421070
// todo: b/308194853
@@ -1269,6 +1297,8 @@ Builder clearRetentionExpirationTime() {
12691297
temporaryHold = builder.temporaryHold;
12701298
retentionExpirationTime = builder.retentionExpirationTime;
12711299
retention = builder.retention;
1300+
softDeleteTime = builder.softDeleteTime;
1301+
hardDeleteTime = builder.hardDeleteTime;
12721302
modifiedFields = builder.modifiedFields.build();
12731303
}
12741304

@@ -1662,6 +1692,18 @@ public OffsetDateTime getRetentionExpirationTimeOffsetDateTime() {
16621692
return retentionExpirationTime;
16631693
}
16641694

1695+
/** If this object has been soft-deleted, returns the time it was soft-deleted. */
1696+
public OffsetDateTime getSoftDeleteTime() {
1697+
return softDeleteTime;
1698+
}
1699+
1700+
/**
1701+
* If this object has been soft-deleted, returns the time at which it will be permanently deleted.
1702+
*/
1703+
public OffsetDateTime getHardDeleteTime() {
1704+
return hardDeleteTime;
1705+
}
1706+
16651707
/** Returns the object's Retention policy. */
16661708
public Retention getRetention() {
16671709
return retention;
@@ -1717,7 +1759,9 @@ public int hashCode() {
17171759
eventBasedHold,
17181760
temporaryHold,
17191761
retention,
1720-
retentionExpirationTime);
1762+
retentionExpirationTime,
1763+
softDeleteTime,
1764+
hardDeleteTime);
17211765
}
17221766

17231767
@Override
@@ -1759,7 +1803,9 @@ public boolean equals(Object o) {
17591803
&& Objects.equals(eventBasedHold, blobInfo.eventBasedHold)
17601804
&& Objects.equals(temporaryHold, blobInfo.temporaryHold)
17611805
&& Objects.equals(retentionExpirationTime, blobInfo.retentionExpirationTime)
1762-
&& Objects.equals(retention, blobInfo.retention);
1806+
&& Objects.equals(retention, blobInfo.retention)
1807+
&& Objects.equals(softDeleteTime, blobInfo.softDeleteTime)
1808+
&& Objects.equals(hardDeleteTime, blobInfo.hardDeleteTime);
17631809
}
17641810

17651811
ImmutableSet<NamedField> getModifiedFields() {

google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -748,6 +748,12 @@ Builder setObjectRetention(ObjectRetention objectRetention) {
748748
return this;
749749
}
750750

751+
@Override
752+
public Builder setSoftDeletePolicy(SoftDeletePolicy softDeletePolicy) {
753+
infoBuilder.setSoftDeletePolicy(softDeletePolicy);
754+
return this;
755+
}
756+
751757
@Override
752758
public Builder setHierarchicalNamespace(HierarchicalNamespace hierarchicalNamespace) {
753759
infoBuilder.setHierarchicalNamespace(hierarchicalNamespace);
@@ -1089,6 +1095,28 @@ public Blob get(String blob, BlobGetOption... options) {
10891095
return storage.get(BlobId.of(getName(), blob), options);
10901096
}
10911097

1098+
/**
1099+
* Returns the requested blob in this bucket of a specific generation or {@code null} if not
1100+
* found.
1101+
*
1102+
* <p>Example of getting a blob of a specific in the bucket.
1103+
*
1104+
* <pre>{@code
1105+
* String blobName = "my_blob_name";
1106+
* long generation = 42;
1107+
* Blob blob = bucket.get(blobName, generation);
1108+
* }</pre>
1109+
*
1110+
* @param blob name of the requested blob
1111+
* @param generation the generation to get
1112+
* @param options blob search options
1113+
* @throws StorageException upon failure
1114+
*/
1115+
@TransportCompatibility({Transport.HTTP, Transport.GRPC})
1116+
public Blob get(String blob, Long generation, BlobGetOption... options) {
1117+
return storage.get(BlobId.of(getName(), blob, generation), options);
1118+
}
1119+
10921120
/**
10931121
* Returns a list of requested blobs in this bucket. Blobs that do not exist are null.
10941122
*

google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ public class BucketInfo implements Serializable {
120120
private final ObjectRetention objectRetention;
121121
private final HierarchicalNamespace hierarchicalNamespace;
122122

123+
private final SoftDeletePolicy softDeletePolicy;
124+
123125
private final transient ImmutableSet<NamedField> modifiedFields;
124126

125127
/**
@@ -350,6 +352,90 @@ public String toString() {
350352
}
351353
}
352354

355+
/**
356+
* The bucket's soft delete policy. If this policy is set, any deleted objects will be
357+
* soft-deleted according to the time specified in the policy
358+
*/
359+
public static class SoftDeletePolicy implements Serializable {
360+
361+
private static final long serialVersionUID = -8100190443052242908L;
362+
private Duration retentionDuration;
363+
private OffsetDateTime effectiveTime;
364+
365+
@Override
366+
public boolean equals(Object o) {
367+
if (this == o) {
368+
return true;
369+
}
370+
if (!(o instanceof SoftDeletePolicy)) {
371+
return false;
372+
}
373+
SoftDeletePolicy that = (SoftDeletePolicy) o;
374+
return Objects.equals(retentionDuration, that.retentionDuration)
375+
&& Objects.equals(effectiveTime, that.effectiveTime);
376+
}
377+
378+
@Override
379+
public int hashCode() {
380+
return Objects.hash(retentionDuration, effectiveTime);
381+
}
382+
383+
@Override
384+
public String toString() {
385+
return MoreObjects.toStringHelper(this)
386+
.add("retentionDuration", retentionDuration)
387+
.add("effectiveTime", effectiveTime)
388+
.toString();
389+
}
390+
391+
public static Builder newBuilder() {
392+
return new Builder();
393+
}
394+
395+
public Builder toBuilder() {
396+
return new Builder().setRetentionDuration(retentionDuration).setEffectiveTime(effectiveTime);
397+
}
398+
399+
private SoftDeletePolicy() {}
400+
401+
public SoftDeletePolicy(Builder builder) {
402+
this.retentionDuration = builder.retentionDuration;
403+
this.effectiveTime = builder.effectiveTime;
404+
}
405+
406+
public Duration getRetentionDuration() {
407+
return retentionDuration;
408+
}
409+
410+
public OffsetDateTime getEffectiveTime() {
411+
return effectiveTime;
412+
}
413+
414+
public static final class Builder {
415+
private Duration retentionDuration;
416+
private OffsetDateTime effectiveTime;
417+
418+
/** Sets the length of time to retain soft-deleted objects for, expressed as a Duration */
419+
public Builder setRetentionDuration(Duration retentionDuration) {
420+
this.retentionDuration = retentionDuration;
421+
return this;
422+
}
423+
424+
/**
425+
* Sets the time from which this soft-delete policy is effective. This is package-private
426+
* because it can only be set by the backend.
427+
*/
428+
Builder setEffectiveTime(OffsetDateTime effectiveTime) {
429+
this.effectiveTime = effectiveTime;
430+
return this;
431+
}
432+
433+
public SoftDeletePolicy build() {
434+
return new SoftDeletePolicy(this);
435+
}
436+
}
437+
}
438+
353439
/**
354440
* Configuration for the Autoclass settings of a bucket.
355441
*
@@ -1753,6 +1839,8 @@ public Builder setRetentionPeriodDuration(Duration retentionPeriod) {
17531839

17541840
abstract Builder setObjectRetention(ObjectRetention objectRetention);
17551841

1842+
public abstract Builder setSoftDeletePolicy(SoftDeletePolicy softDeletePolicy);
1843+
17561844
/** Creates a {@code BucketInfo} object. */
17571845
public abstract BucketInfo build();
17581846

@@ -1851,6 +1939,8 @@ static final class BuilderImpl extends Builder {
18511939
private Logging logging;
18521940
private CustomPlacementConfig customPlacementConfig;
18531941
private ObjectRetention objectRetention;
1942+
1943+
private SoftDeletePolicy softDeletePolicy;
18541944
private HierarchicalNamespace hierarchicalNamespace;
18551945
private final ImmutableSet.Builder<NamedField> modifiedFields = ImmutableSet.builder();
18561946

@@ -1891,6 +1981,7 @@ static final class BuilderImpl extends Builder {
18911981
logging = bucketInfo.logging;
18921982
customPlacementConfig = bucketInfo.customPlacementConfig;
18931983
objectRetention = bucketInfo.objectRetention;
1984+
softDeletePolicy = bucketInfo.softDeletePolicy;
18941985
hierarchicalNamespace = bucketInfo.hierarchicalNamespace;
18951986
}
18961987

@@ -2257,6 +2348,15 @@ Builder setObjectRetention(ObjectRetention objectRetention) {
22572348
return this;
22582349
}
22592350

2351+
@Override
2352+
public Builder setSoftDeletePolicy(SoftDeletePolicy softDeletePolicy) {
2353+
if (!Objects.equals(this.softDeletePolicy, softDeletePolicy)) {
2354+
modifiedFields.add(BucketField.SOFT_DELETE_POLICY);
2355+
}
2356+
this.softDeletePolicy = softDeletePolicy;
2357+
return this;
2358+
}
2359+
22602360
@Override
22612361
public Builder setHierarchicalNamespace(HierarchicalNamespace hierarchicalNamespace) {
22622362
if (!Objects.equals(this.hierarchicalNamespace, hierarchicalNamespace)) {
@@ -2507,6 +2607,7 @@ private Builder clearDeleteLifecycleRules() {
25072607
logging = builder.logging;
25082608
customPlacementConfig = builder.customPlacementConfig;
25092609
objectRetention = builder.objectRetention;
2610+
softDeletePolicy = builder.softDeletePolicy;
25102611
hierarchicalNamespace = builder.hierarchicalNamespace;
25112612
modifiedFields = builder.modifiedFields.build();
25122613
}
@@ -2848,6 +2949,11 @@ public ObjectRetention getObjectRetention() {
28482949
return objectRetention;
28492950
}
28502951

2952+
/** returns the Soft Delete policy */
2953+
public SoftDeletePolicy getSoftDeletePolicy() {
2954+
return softDeletePolicy;
2955+
}
2956+
28512957
/** Returns the Hierarchical Namespace (Folders) Configuration */
28522958
public HierarchicalNamespace getHierarchicalNamespace() {
28532959
return hierarchicalNamespace;
@@ -2890,6 +2996,7 @@ public int hashCode() {
28902996
autoclass,
28912997
locationType,
28922998
objectRetention,
2999+
softDeletePolicy,
28933000
hierarchicalNamespace,
28943001
logging);
28953002
}
@@ -2932,6 +3039,7 @@ public boolean equals(Object o) {
29323039
&& Objects.equals(autoclass, that.autoclass)
29333040
&& Objects.equals(locationType, that.locationType)
29343041
&& Objects.equals(objectRetention, that.objectRetention)
3042+
&& Objects.equals(softDeletePolicy, that.softDeletePolicy)
29353043
&& Objects.equals(hierarchicalNamespace, that.hierarchicalNamespace)
29363044
&& Objects.equals(logging, that.logging);
29373045
}

0 commit comments

Comments
 (0)