Skip to content

Commit

Permalink
feat: adding support for Cross Region Backups
Browse files Browse the repository at this point in the history
  • Loading branch information
asthamohta committed Dec 24, 2021
1 parent 832ca0c commit f200a1c
Show file tree
Hide file tree
Showing 7 changed files with 356 additions and 57 deletions.
103 changes: 103 additions & 0 deletions samples/backups-copy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// sample-metadata:
// title: Read data using an existing index.
// usage: node spannerCopyBackup <INSTANCE_ID> <DATABASE_ID> <PROJECT_ID>

'use strict';

function main(
instanceId = 'my-instance',
databaseId = 'my-database',
backupId = 'my-backup',
sourceBackupId = 'my-source-backup',
projectId = 'my-project-id'
) {
// [START spanner_copy_backup]
/**
* TODO(developer): Uncomment these variables before running the sample.
*/
// const instanceId = 'my-instance';
// const databaseId = 'my-database';
// const backupId = 'my-backup',
// sourceBackupId = 'my-source-backup',
// const projectId = 'my-project-id';

// Imports the Google Cloud Spanner client library
const {Spanner} = require('@google-cloud/spanner');
const {PreciseDate} = require('@google-cloud/precise-date');

// Instantiates a client
const spanner = new Spanner({
projectId: projectId,
apiEndpoint: 'staging-wrenchworks.sandbox.googleapis.com',
});

async function spannerCopyBackup() {
// Gets a reference to a Cloud Spanner instance, database and backup
const instance = spanner.instance(instanceId);
const database = instance.database(databaseId);
const sourceBackup = instance.backup(sourceBackupId);

// Expire source and copy backup 14 days in the future
const expireTime = Spanner.timestamp(
Date.now() + 1000 * 60 * 60 * 24 * 14
).toStruct();

// Copy the backup of the database
try {
console.log(
`Creating copy of the source backup ${sourceBackup.formattedName_}.`
);
const [, operation] = await instance.copyBackup(
sourceBackup.formattedName_,
backupId,
{
expireTime: expireTime,
}
);

console.log(
`Waiting for backup copy${instance.backup(backupId)} to complete...`
);
await operation.promise();

// Verify the copy backup is ready
const copyBackup = instance.backup(backupId);
const [copyBackupInfo] = await copyBackup.getMetadata();
if (copyBackupInfo.state === 'READY') {
console.log(
`Backup copy ${copyBackupInfo.name} of size ` +
`${copyBackupInfo.sizeBytes} bytes was created at ` +
`${new PreciseDate(copyBackupInfo.createTime).toISOString()}`
);
} else {
console.error('ERROR: Copy of backup is not ready.');
}
} catch (err) {
console.error('ERROR:', err);
} finally {
// Close the database when finished.
await database.close();
}
}
spannerCopyBackup();
// [END spanner_copy_backup]
}
process.on('unhandledRejection', err => {
console.error(err.message);
process.exitCode = 1;
});
main(...process.argv.slice(2));
11 changes: 9 additions & 2 deletions samples/backups-update.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ async function updateBackup(instanceId, backupId, projectId) {
// Creates a client
const spanner = new Spanner({
projectId: projectId,
apiEndpoint: 'staging-wrenchworks.sandbox.googleapis.com',
});

// Gets a reference to a Cloud Spanner instance and backup
Expand All @@ -40,8 +41,13 @@ async function updateBackup(instanceId, backupId, projectId) {
// Read backup metadata and update expiry time
try {
const currentExpireTime = await backup.getExpireTime();
const newExpireTime = new PreciseDate(currentExpireTime);
newExpireTime.setDate(newExpireTime.getDate() + 30);
const maxExpireTime = await backup.getMaxExpireTime();
const wantExpireTime = new PreciseDate(currentExpireTime);
wantExpireTime.setDate(wantExpireTime.getDate() + 1);
// New expire time should be less than the max expire time
const min = (currentExpireTime, maxExpireTime) =>
currentExpireTime < maxExpireTime ? currentExpireTime : maxExpireTime;
const newExpireTime = new PreciseDate(min(wantExpireTime, maxExpireTime));
console.log(
`Backup ${backupId} current expire time: ${currentExpireTime.toISOString()}`
);
Expand All @@ -55,3 +61,4 @@ async function updateBackup(instanceId, backupId, projectId) {
}

module.exports.updateBackup = updateBackup;
//updateBackup('test-cross-region', 'backup123', 'appdev-soda-spanner-staging');
15 changes: 15 additions & 0 deletions samples/system-test/spanner.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ const VERSION_RETENTION_DATABASE_ID = `test-database-${CURRENT_TIME}-v`;
const ENCRYPTED_DATABASE_ID = `test-database-${CURRENT_TIME}-enc`;
const DEFAULT_LEADER_DATABASE_ID = `test-database-${CURRENT_TIME}-dl`;
const BACKUP_ID = `test-backup-${CURRENT_TIME}`;
const COPY_BACKUP_ID = `test-copy-backup-${CURRENT_TIME}`;
const ENCRYPTED_BACKUP_ID = `test-backup-${CURRENT_TIME}-enc`;
const CANCELLED_BACKUP_ID = `test-backup-${CURRENT_TIME}-c`;
const LOCATION_ID = 'regional-us-central1';
Expand All @@ -63,6 +64,7 @@ const DEFAULT_LEADER_2 = 'us-east1';

const spanner = new Spanner({
projectId: PROJECT_ID,
apiEndpoint: 'staging-wrenchworks.sandbox.googleapis.com',
});
const LABEL = 'node-sample-tests';
const GAX_OPTIONS = {
Expand Down Expand Up @@ -214,6 +216,7 @@ describe('Spanner', () => {
await Promise.all([
instance.backup(BACKUP_ID).delete(GAX_OPTIONS),
instance.backup(ENCRYPTED_BACKUP_ID).delete(GAX_OPTIONS),
instance.backup(COPY_BACKUP_ID).delete(GAX_OPTIONS),
instance.backup(CANCELLED_BACKUP_ID).delete(GAX_OPTIONS),
]);
await instance.delete(GAX_OPTIONS);
Expand All @@ -223,6 +226,7 @@ describe('Spanner', () => {
instance.database(RESTORE_DATABASE_ID).delete(),
instance.database(ENCRYPTED_RESTORE_DATABASE_ID).delete(),
instance.backup(BACKUP_ID).delete(GAX_OPTIONS),
instance.backup(COPY_BACKUP_ID).delete(GAX_OPTIONS),
instance.backup(ENCRYPTED_BACKUP_ID).delete(GAX_OPTIONS),
instance.backup(CANCELLED_BACKUP_ID).delete(GAX_OPTIONS),
]);
Expand Down Expand Up @@ -1021,6 +1025,17 @@ describe('Spanner', () => {
assert.include(output, `using encryption key ${key.name}`);
});

// copy_backup
it('should create a copy of a backup', async () => {
const output = execSync(
`node backups-copy.js ${INSTANCE_ID} ${DATABASE_ID} ${COPY_BACKUP_ID} ${BACKUP_ID} ${PROJECT_ID}`
);
assert.match(
output,
new RegExp(`(.*)Backup copy(.*)${COPY_BACKUP_ID} of size(.*)`)
);
});

// cancel_backup
it('should cancel a backup of the database', async () => {
const output = execSync(
Expand Down
Loading

0 comments on commit f200a1c

Please sign in to comment.