Skip to content

feat: max expire time and referencing backup #1

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

Merged
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
25 changes: 25 additions & 0 deletions google-cloud-spanner/clirr-ignored-differences.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,29 @@
<className>com/google/cloud/spanner/connection/ConnectionOptions</className>
<method>com.google.cloud.spanner.Dialect getDialect()</method>
</difference>
<difference>
<differenceType>7013</differenceType>
<className>com/google/cloud/spanner/BackupInfo$Builder</className>
<method>com.google.cloud.spanner.BackupInfo$Builder setMaxExpireTime(com.google.cloud.Timestamp)</method>
</difference>
<difference>
<differenceType>7013</differenceType>
<className>com/google/cloud/spanner/BackupInfo$Builder</className>
<method>com.google.cloud.spanner.BackupInfo$Builder setReferencingBackup(com.google.protobuf.ProtocolStringList)</method>
</difference>
<difference>
<differenceType>7012</differenceType>
<className>com/google/cloud/spanner/DatabaseAdminClient</className>
<method>com.google.api.gax.longrunning.OperationFuture copyBackup(java.lang.String, java.lang.String, java.lang.String, com.google.cloud.Timestamp)</method>
</difference>
<difference>
<differenceType>7012</differenceType>
<className>com/google/cloud/spanner/DatabaseAdminClient</className>
<method>com.google.api.gax.longrunning.OperationFuture copyBackup(com.google.cloud.spanner.BackupId, com.google.cloud.spanner.Backup)</method>
</difference>
<difference>
<differenceType>7012</differenceType>
<className>com/google/cloud/spanner/spi/v1/SpannerRpc</className>
<method>com.google.api.gax.longrunning.OperationFuture copyBackUp(com.google.cloud.spanner.BackupId, com.google.cloud.spanner.Backup)</method>
</difference>
</differences>
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,8 @@ static Backup fromProto(
.setDatabase(DatabaseId.of(proto.getDatabase()))
.setEncryptionInfo(EncryptionInfo.fromProtoOrNull(proto.getEncryptionInfo()))
.setProto(proto)
.setMaxExpireTime(Timestamp.fromProto(proto.getMaxExpireTime()))
.setReferencingBackup(proto.getReferencingBackupsList())
.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import com.google.cloud.Timestamp;
import com.google.cloud.spanner.encryption.BackupEncryptionConfig;
import com.google.cloud.spanner.encryption.EncryptionInfo;
import com.google.protobuf.ProtocolStringList;
import com.google.spanner.admin.database.v1.Database;
import java.util.Objects;
import javax.annotation.Nullable;
Expand Down Expand Up @@ -84,6 +85,20 @@ public abstract static class Builder {

/** Builds the backup from this builder. */
public abstract Backup build();

/**
* Output Only.
*
* <p>Returns the max allowed expiration time of the backup, with microseconds granularity.
*/
protected abstract Builder setMaxExpireTime(Timestamp maxExpireTime);

/**
* Output Only.
*
* <p>Returns the names of the destination backups being created by copying this source backup.
*/
protected abstract Builder setReferencingBackup(ProtocolStringList referencingBackup);
}

abstract static class BuilderImpl extends Builder {
Expand All @@ -96,6 +111,8 @@ abstract static class BuilderImpl extends Builder {
private BackupEncryptionConfig encryptionConfig;
private EncryptionInfo encryptionInfo;
private com.google.spanner.admin.database.v1.Backup proto;
private Timestamp maxExpireTime;
private ProtocolStringList referencingBackup;

BuilderImpl(BackupId id) {
this.id = Preconditions.checkNotNull(id);
Expand All @@ -111,6 +128,8 @@ abstract static class BuilderImpl extends Builder {
this.encryptionConfig = other.encryptionConfig;
this.encryptionInfo = other.encryptionInfo;
this.proto = other.proto;
this.maxExpireTime = other.maxExpireTime;
this.referencingBackup = other.referencingBackup;
}

@Override
Expand Down Expand Up @@ -163,6 +182,18 @@ Builder setProto(@Nullable com.google.spanner.admin.database.v1.Backup proto) {
this.proto = proto;
return this;
}

@Override
public Builder setMaxExpireTime(Timestamp maxExpireTime) {
this.maxExpireTime = Preconditions.checkNotNull(maxExpireTime);
return this;
}

@Override
public Builder setReferencingBackup(ProtocolStringList referencingBackup) {
this.referencingBackup = Preconditions.checkNotNull(referencingBackup);
return this;
}
}

/** State of the backup. */
Expand All @@ -184,6 +215,8 @@ public enum State {
private final BackupEncryptionConfig encryptionConfig;
private final EncryptionInfo encryptionInfo;
private final com.google.spanner.admin.database.v1.Backup proto;
private final Timestamp maxExpireTime;
private final ProtocolStringList referencingBackup;

BackupInfo(BuilderImpl builder) {
this.id = builder.id;
Expand All @@ -195,6 +228,8 @@ public enum State {
this.versionTime = builder.versionTime;
this.database = builder.database;
this.proto = builder.proto;
this.maxExpireTime = builder.maxExpireTime;
this.referencingBackup = builder.referencingBackup;
}

/** Returns the backup id. */
Expand Down Expand Up @@ -253,6 +288,19 @@ public DatabaseId getDatabase() {
return proto;
}

/** Returns the max expire time of this {@link Backup}. */
public Timestamp getMaxExpireTime() {
return maxExpireTime;
}

/**
* Returns the names of the destination backups being created by copying this source backup {@link
* Backup}.
*/
public ProtocolStringList getReferencingBackup() {
return referencingBackup;
}

@Override
public boolean equals(Object o) {
if (this == o) {
Expand All @@ -269,26 +317,39 @@ public boolean equals(Object o) {
&& Objects.equals(encryptionInfo, that.encryptionInfo)
&& Objects.equals(expireTime, that.expireTime)
&& Objects.equals(versionTime, that.versionTime)
&& Objects.equals(database, that.database);
&& Objects.equals(database, that.database)
&& Objects.equals(maxExpireTime, that.maxExpireTime)
&& Objects.equals(referencingBackup, that.referencingBackup);
}

@Override
public int hashCode() {
return Objects.hash(
id, state, size, encryptionConfig, encryptionInfo, expireTime, versionTime, database);
id,
state,
size,
encryptionConfig,
encryptionInfo,
expireTime,
versionTime,
database,
maxExpireTime,
referencingBackup);
}

@Override
public String toString() {
return String.format(
"Backup[%s, %s, %d, %s, %s, %s, %s, %s]",
"Backup[%s, %s, %d, %s, %s, %s, %s, %s, %s, %s]",
id.getName(),
state,
size,
encryptionConfig,
encryptionInfo,
expireTime,
versionTime,
database);
database,
maxExpireTime,
referencingBackup);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1661,21 +1661,17 @@ static void cancelCreateBackup(
// [END spanner_cancel_backup_create]

// [START spanner_list_backup_operations]
static void listBackupOperations(InstanceAdminClient instanceAdminClient, DatabaseId databaseId) {
static void listBackupOperations(InstanceAdminClient instanceAdminClient, DatabaseId databaseId, BackupId backupId) {
Instance instance = instanceAdminClient.getInstance(databaseId.getInstanceId().getInstance());
// Get create backup operations for the sample database.
Timestamp last24Hours = Timestamp.ofTimeSecondsAndNanos(TimeUnit.SECONDS.convert(
TimeUnit.HOURS.convert(Timestamp.now().getSeconds(), TimeUnit.SECONDS) - 24,
TimeUnit.HOURS), 0);
String filter =
String.format(
"(metadata.database:%s) AND "
+ "(metadata.@type:type.googleapis.com/"
+ "google.spanner.admin.database.v1.CreateBackupMetadata) AND "
+ "(metadata.progress.start_time > \"%s\")",
databaseId.getName(), last24Hours);
Page<Operation> operations = instance.listBackupOperations(Options.filter(filter));
for (Operation op : operations.iterateAll()) {
"(metadata.@type:type.googleapis.com/google.spanner.admin.database.v1.CreateBackupMetadata) "
+ "AND (metadata.database:%s)",
databaseId.getName());
Page<Operation> createBackupOperations = instance.listBackupOperations(Options.filter(filter));
System.out.println("Create Backup Operations:");
for (Operation op : createBackupOperations.iterateAll()) {
try {
CreateBackupMetadata metadata = op.getMetadata().unpack(CreateBackupMetadata.class);
System.out.println(
Expand All @@ -1689,6 +1685,30 @@ static void listBackupOperations(InstanceAdminClient instanceAdminClient, Databa
System.err.println(e.getMessage());
}
}

// Get copy backup operations for the sample database.
filter =
String.format(
"(metadata.@type:type.googleapis.com/"
+ "google.spanner.admin.database.v1.CopyBackupMetadata) "
+ "AND (metadata.source_backup:%s)",
backupId.getName());
Page<Operation> copyBackupOperations = instance.listBackupOperations(Options.filter(filter));
System.out.println("Copy Backup Operations:");
for (Operation op : copyBackupOperations.iterateAll()) {
try {
CopyBackupMetadata copyBackupMetadata = op.getMetadata().unpack(CopyBackupMetadata.class);
System.out.println(
String.format(
"Copy Backup %s on backup %s pending: %d%% complete",
copyBackupMetadata.getName(),
copyBackupMetadata.getSourceBackup(),
copyBackupMetadata.getProgress().getProgressPercent()));
} catch (InvalidProtocolBufferException e) {
// The returned operation does not contain CopyBackupMetadata.
System.err.println(e.getMessage());
}
}
}
// [END spanner_list_backup_operations]

Expand Down Expand Up @@ -1842,6 +1862,8 @@ static void updateBackup(DatabaseAdminClient dbAdminClient, BackupId backupId) {
TimeUnit.SECONDS.toMicros(backup.getExpireTime().getSeconds())
+ TimeUnit.NANOSECONDS.toMicros(backup.getExpireTime().getNanos())
+ TimeUnit.DAYS.toMicros(30L));
// New Expire Time must be less than Max Expire Time
expireTime = expireTime.compareTo(backup.getMaxExpireTime())<0?expireTime:backup.getMaxExpireTime();
int timeDiff = expireTime.compareTo(backup.getExpireTime());
Timestamp newExpireTime = (timeDiff < 0) ? expireTime : backup.getExpireTime();

Expand Down Expand Up @@ -2053,7 +2075,7 @@ static void run(
BackupId.of(backup.getInstanceId(), backup.getBackup() + "_cancel"));
break;
case "listbackupoperations":
listBackupOperations(instanceAdminClient, database);
listBackupOperations(instanceAdminClient, database, backup);
break;
case "listdatabaseoperations":
listDatabaseOperations(instanceAdminClient, dbAdminClient, database.getInstanceId());
Expand Down Expand Up @@ -2149,14 +2171,14 @@ static void printUsageAndExit() {
System.err.println(" SpannerExample querywithqueryoptions my-instance example-db");
System.err.println(" SpannerExample createbackup my-instance example-db");
System.err.println(" SpannerExample listbackups my-instance example-db");
System.err.println(" SpannerExample listbackupoperations my-instance example-db");
System.err.println(" SpannerExample listbackupoperations my-instance example-db backup-id");
System.err.println(" SpannerExample listdatabaseoperations my-instance example-db");
System.err.println(" SpannerExample restorebackup my-instance example-db");
System.exit(1);
}

public static void main(String[] args) throws Exception {
if (args.length != 3) {
if (args.length != 3 && args.length != 4) {
printUsageAndExit();
}
// [START init_client]
Expand All @@ -2180,6 +2202,9 @@ public static void main(String[] args) throws Exception {
String.format(
"%s_%02d",
db.getDatabase(), LocalDate.now().get(ChronoField.ALIGNED_WEEK_OF_YEAR));
if( args.length == 4) {
backupName = args[3];
}
BackupId backup = BackupId.of(db.getInstanceId(), backupName);

// [START init_client]
Expand Down