Skip to content
This repository was archived by the owner on Mar 4, 2026. It is now read-only.

Commit b829530

Browse files
AVaksmanskuruppu
andauthored
chore: improve samples-test (#961)
Co-authored-by: skuruppu <skuruppu@google.com>
1 parent 6259895 commit b829530

File tree

2 files changed

+58
-109
lines changed

2 files changed

+58
-109
lines changed

samples/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
},
2121
"devDependencies": {
2222
"chai": "^4.2.0",
23-
"mocha": "^7.0.0"
23+
"mocha": "^7.0.0",
24+
"p-limit": "^2.3.0"
2425
}
2526
}

samples/system-test/spanner.test.js

Lines changed: 56 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ const {Spanner} = require('@google-cloud/spanner');
1818
const {assert} = require('chai');
1919
const {describe, it, before, after} = require('mocha');
2020
const cp = require('child_process');
21+
const pLimit = require('p-limit');
2122

2223
const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'});
2324

@@ -35,7 +36,8 @@ const backupsCmd = 'node backups.js';
3536

3637
const date = Date.now();
3738
const PROJECT_ID = process.env.GCLOUD_PROJECT;
38-
const INSTANCE_ID = process.env.SPANNERTEST_INSTANCE || `test-instance-${date}`;
39+
const PREFIX = 'test-instance';
40+
const INSTANCE_ID = process.env.SPANNERTEST_INSTANCE || `${PREFIX}-${date}`;
3941
const INSTANCE_ALREADY_EXISTS = !!process.env.SPANNERTEST_INSTANCE;
4042
const DATABASE_ID = `test-database-${date}`;
4143
const RESTORE_DATABASE_ID = `test-database-${date}-r`;
@@ -45,137 +47,83 @@ const CANCELLED_BACKUP_ID = `test-backup-${date}-c`;
4547
const spanner = new Spanner({
4648
projectId: PROJECT_ID,
4749
});
48-
49-
function deleteInstance(instance) {
50-
return new Promise((resolve, reject) => {
51-
// Backups must be deleted before an instance can be deleted.
52-
instance.request(
53-
{
54-
client: 'DatabaseAdminClient',
55-
method: 'listBackups',
56-
reqOpts: {
57-
parent: instance.formattedName_,
58-
},
59-
},
60-
async (err, backups) => {
61-
if (err) {
62-
reject(err);
63-
return;
64-
}
65-
66-
if (backups.length > 0) {
67-
try {
68-
await deleteInstanceBackups(instance, backups);
69-
} catch (e) {
70-
reject(err);
71-
return;
72-
}
73-
74-
deleteInstance(instance).then(resolve, reject);
75-
return;
76-
}
77-
78-
try {
79-
await instance.delete();
80-
} catch (e) {
81-
reject(e);
82-
return;
83-
}
84-
85-
resolve();
86-
}
87-
);
88-
});
50+
const LABEL = 'node-sample-tests';
51+
const CURRENT_TIME = Math.round(Date.now() / 1000).toString();
52+
53+
async function deleteStaleInstances() {
54+
const [instances] = await spanner.getInstances();
55+
const yesterday = new Date();
56+
yesterday.setHours(-24);
57+
const toDelete = instances.filter(
58+
instance =>
59+
instance.id.includes(PREFIX) &&
60+
instance.metadata.labels.created < yesterday.getTime()
61+
);
62+
63+
return deleteInstanceArray(toDelete);
8964
}
9065

91-
function deleteInstanceBackups(instance, instanceBackups) {
92-
const deleteInstanceBackupPromises = instanceBackups.map(instanceBackup => {
93-
return new Promise((resolve, reject) => {
94-
instance.request(
95-
{
96-
client: 'DatabaseAdminClient',
97-
method: 'deleteBackup',
98-
reqOpts: {name: instanceBackup.name},
99-
},
100-
err => {
101-
if (err) {
102-
reject(err);
103-
return;
104-
}
105-
resolve();
106-
}
107-
);
108-
});
109-
});
66+
function deleteInstanceArray(instanceArray) {
67+
/**
68+
* Delay to allow instance and its databases to fully clear.
69+
* Refer to "Soon afterwards"
70+
* @see {@link https://cloud.google.com/spanner/docs/reference/rpc/google.spanner.admin.instance.v1#google.spanner.admin.instance.v1.InstanceAdmin.DeleteInstance}
71+
*/
72+
const delay = 500;
73+
const limit = pLimit(5);
74+
return Promise.all(
75+
instanceArray.map(instance =>
76+
limit(() => setTimeout(deleteInstance, delay, instance))
77+
)
78+
);
79+
}
11080

111-
return Promise.all(deleteInstanceBackupPromises);
81+
async function deleteInstance(instance) {
82+
const [backups] = await instance.getBackups();
83+
await Promise.all(backups.map(backup => backup.delete()));
84+
return instance.delete();
11285
}
11386

11487
describe('Spanner', () => {
115-
before(async () => {
116-
const instance = spanner.instance(INSTANCE_ID);
117-
const database = instance.database(DATABASE_ID);
88+
const instance = spanner.instance(INSTANCE_ID);
11889

119-
if (!INSTANCE_ALREADY_EXISTS) {
120-
try {
121-
await instance.delete();
122-
} catch (err) {
123-
// Ignore error
124-
}
125-
}
126-
try {
127-
await database.delete();
128-
} catch (err) {
129-
// Ignore error
130-
}
90+
before(async () => {
91+
await deleteStaleInstances();
13192

13293
if (!INSTANCE_ALREADY_EXISTS) {
133-
const [instances] = await spanner.getInstances({
134-
filter: 'labels.gcloud-sample-tests:true',
135-
});
136-
137-
await Promise.all(
138-
instances.map(async instance => {
139-
const instanceName = instance.metadata.name;
140-
const res = await spanner.auth.request({
141-
url: `https://spanner.googleapis.com/v1/${instanceName}/operations`,
142-
});
143-
const operations = res.data.operations;
144-
await Promise.all(
145-
operations
146-
.filter(operation => {
147-
return operation.metadata['@type'].includes('CreateInstance');
148-
})
149-
.filter(operation => {
150-
const yesterday = new Date();
151-
yesterday.setHours(-24);
152-
const instanceCreated = new Date(operation.metadata.startTime);
153-
return instanceCreated < yesterday;
154-
})
155-
.map(() => deleteInstance(instance))
156-
);
157-
})
158-
);
159-
16094
const [, operation] = await instance.create({
16195
config: 'regional-us-central1',
16296
nodes: 1,
16397
labels: {
164-
'gcloud-sample-tests': 'true',
98+
[LABEL]: 'true',
99+
created: CURRENT_TIME,
165100
},
166101
});
167-
168102
await operation.promise();
103+
} else {
104+
console.log(
105+
`Not creating temp instance, using + ${instance.formattedName_}...`
106+
);
169107
}
170108
});
171109

172110
after(async () => {
173111
const instance = spanner.instance(INSTANCE_ID);
174-
const database = instance.database(DATABASE_ID);
175-
await database.delete();
176112

177113
if (!INSTANCE_ALREADY_EXISTS) {
114+
// Make sure all backups are deleted before an instance can be deleted.
115+
await Promise.all([
116+
instance.backup(BACKUP_ID).delete(),
117+
instance.backup(CANCELLED_BACKUP_ID).delete(),
118+
]);
178119
await instance.delete();
120+
} else {
121+
await Promise.all([
122+
instance.database(DATABASE_ID).delete(),
123+
instance.database(RESTORE_DATABASE_ID).delete(),
124+
instance.backup(BACKUP_ID).delete(),
125+
instance.backup(CANCELLED_BACKUP_ID).delete(),
126+
]);
179127
}
180128
});
181129

0 commit comments

Comments
 (0)