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

Commit ac2de41

Browse files
shaffeeullahd-googrelease-please[bot]ddelgrosso1
authored
samples: add preconditions to storage.objects.rewrite, storage.objects.insert, storage.objects.patch, & storage.objects.delete samples (#2046)
* started copy sample * samples: add preconditions to storage.objects.rewrite & storage.objects.delete samples * linted files * samples: storage.objects.insert precondition samples * updated test * samples: storage.objects.insert precondition samples (#2047) * test: add retries (#2039) * refactor: remove unused `restart` private method (#2038) Co-authored-by: Sameena Shaffeeullah <shaffeeullah@google.com> * fix: Retry `EPIPE` Connection Errors + Attempt Retries in Resumable Upload Connection Errors (#2040) * feat: Add `epipe` as retryable error * fix: capture and retry potential connection errors * test: Add tests and remove logs * test: set `retryOptions` by copy rather than reference * fix: grammar * chore(main): release 6.4.1 (#2036) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> * test: add delay to bucket tests to reduce rate limiting errors (#2043) * samples: storage.objects.insert precondition samples * updated test Co-authored-by: Daniel Bankhead <danielbankhead@google.com> Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> Co-authored-by: Denis DelGrosso <85250797+ddelgrosso1@users.noreply.github.com> * Revert "samples: storage.objects.insert precondition samples (#2047)" (#2048) This reverts commit ca1b4b7. * storage.objects.patch sample updates * destinationGenerationMatchPrecondition * renamed variable Co-authored-by: Daniel Bankhead <danielbankhead@google.com> Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> Co-authored-by: Denis DelGrosso <85250797+ddelgrosso1@users.noreply.github.com>
1 parent e58ee0b commit ac2de41

20 files changed

Lines changed: 321 additions & 78 deletions

samples/changeFileCSEKToCMEK.js

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ function main(
2323
bucketName = 'my-bucket',
2424
fileName = 'test.txt',
2525
encryptionKey = 'my-encription-key',
26-
kmsKeyName = 'my-kms-key'
26+
kmsKeyName = 'my-kms-key',
27+
generationMatchPrecondition = 0
2728
) {
2829
// [START storage_object_csek_to_cmek]
2930
/**
@@ -49,13 +50,25 @@ function main(
4950
const storage = new Storage();
5051

5152
async function changeFileCSEKToCMEK() {
53+
const rotateEncryptionKeyOptions = {
54+
kmsKeyName,
55+
// Optional: set a generation-match precondition to avoid potential race
56+
// conditions and data corruptions. The request to upload is aborted if the
57+
// object's generation number does not match your precondition.
58+
preconditionOpts: {
59+
ifGenerationMatch: generationMatchPrecondition,
60+
},
61+
};
62+
63+
console.log(rotateEncryptionKeyOptions);
64+
5265
await storage
5366
.bucket(bucketName)
5467
.file(fileName, {
5568
encryptionKey: Buffer.from(encryptionKey, 'base64'),
5669
})
5770
.rotateEncryptionKey({
58-
kmsKeyName,
71+
rotateEncryptionKeyOptions,
5972
});
6073

6174
console.log(

samples/composeFile.js

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ function main(
2323
bucketName = 'my-bucket',
2424
firstFileName = 'file-one.txt',
2525
secondFileName = 'file-two.txt',
26-
destinationFileName = 'file-one-two.txt'
26+
destinationFileName = 'file-one-two.txt',
27+
destinationGenerationMatchPrecondition = 0
2728
) {
2829
// [START storage_compose_file]
2930
/**
@@ -51,7 +52,17 @@ function main(
5152
const bucket = storage.bucket(bucketName);
5253
const sources = [firstFileName, secondFileName];
5354

54-
await bucket.combine(sources, destinationFileName);
55+
// Optional:
56+
// Set a generation-match precondition to avoid potential race conditions
57+
// and data corruptions. The request to upload is aborted if the object's
58+
// generation number does not match your precondition. For a destination
59+
// object that does not yet exist, set the ifGenerationMatch precondition to 0
60+
// If the destination object already exists in your bucket, set instead a
61+
// generation-match precondition using its generation number.
62+
const combineOptions = {
63+
ifGenerationMatch: destinationGenerationMatchPrecondition,
64+
};
65+
await bucket.combine(sources, destinationFileName, combineOptions);
5566

5667
console.log(
5768
`New composite file ${destinationFileName} was created by combining ${firstFileName} and ${secondFileName}`

samples/copyFile.js

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ function main(
2424
srcBucketName = 'my-bucket',
2525
srcFilename = 'test2.txt',
2626
destBucketName = 'my-bucket',
27-
destFileName = 'test3.txt'
27+
destFileName = 'test3.txt',
28+
destinationGenerationMatchPrecondition = 0
2829
) {
2930
// [START storage_copy_file]
3031
/**
@@ -49,11 +50,26 @@ function main(
4950
const storage = new Storage();
5051

5152
async function copyFile() {
53+
const copyDestination = storage.bucket(destBucketName).file(destFileName);
54+
55+
// Optional:
56+
// Set a generation-match precondition to avoid potential race conditions
57+
// and data corruptions. The request to upload is aborted if the object's
58+
// generation number does not match your precondition. For a destination
59+
// object that does not yet exist, set the ifGenerationMatch precondition to 0
60+
// If the destination object already exists in your bucket, set instead a
61+
// generation-match precondition using its generation number.
62+
const copyOptions = {
63+
preconditionOpts: {
64+
ifGenerationMatch: destinationGenerationMatchPrecondition,
65+
},
66+
};
67+
5268
// Copies the file to the other bucket
5369
await storage
5470
.bucket(srcBucketName)
5571
.file(srcFilename)
56-
.copy(storage.bucket(destBucketName).file(destFileName));
72+
.copy(copyDestination, copyOptions);
5773

5874
console.log(
5975
`gs://${srcBucketName}/${srcFilename} copied to gs://${destBucketName}/${destFileName}`

samples/copyOldVersionOfFile.js

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ function main(
2424
srcFilename = 'test2.txt',
2525
destBucketName = 'my-bucket',
2626
destFileName = 'test3.txt',
27-
generation = 1
27+
generation = 1,
28+
destinationGenerationMatchPrecondition = 0
2829
) {
2930
// [START storage_copy_file_archived_generation]
3031
/**
@@ -53,12 +54,26 @@ function main(
5354

5455
async function copyOldVersionOfFile() {
5556
// Copies the file to the other bucket
57+
58+
// Optional:
59+
// Set a generation-match precondition to avoid potential race conditions
60+
// and data corruptions. The request to upload is aborted if the object's
61+
// generation number does not match your precondition. For a destination
62+
// object that does not yet exist, set the ifGenerationMatch precondition to 0
63+
// If the destination object already exists in your bucket, set instead a
64+
// generation-match precondition using its generation number.
65+
const copyOptions = {
66+
preconditionOpts: {
67+
ifGenerationMatch: destinationGenerationMatchPrecondition,
68+
},
69+
};
70+
5671
await storage
5772
.bucket(srcBucketName)
5873
.file(srcFilename, {
5974
generation,
6075
})
61-
.copy(storage.bucket(destBucketName).file(destFileName));
76+
.copy(storage.bucket(destBucketName).file(destFileName), copyOptions);
6277

6378
console.log(
6479
`Generation ${generation} of file ${srcFilename} in bucket ${srcBucketName} was copied to ${destFileName} in bucket ${destBucketName}`

samples/deleteFile.js

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@
2020
* at https://cloud.google.com/storage/docs.
2121
*/
2222

23-
function main(bucketName = 'my-bucket', fileName = 'test.txt') {
23+
function main(
24+
bucketName = 'my-bucket',
25+
fileName = 'test.txt',
26+
generationMatchPrecondition = 0
27+
) {
2428
// [START storage_delete_file]
2529
/**
2630
* TODO(developer): Uncomment the following lines before running the sample.
@@ -37,8 +41,18 @@ function main(bucketName = 'my-bucket', fileName = 'test.txt') {
3741
// Creates a client
3842
const storage = new Storage();
3943

44+
// Optional:
45+
// Set a generation-match precondition to avoid potential race conditions
46+
// and data corruptions. The request to upload is aborted if the object's
47+
// generation number does not match your precondition. For a destination
48+
// object that does not yet exist, set the ifGenerationMatch precondition to 0
49+
// If the destination object already exists in your bucket, set instead a
50+
// generation-match precondition using its generation number.
51+
const deleteOptions = {
52+
ifGenerationMatch: generationMatchPrecondition,
53+
};
4054
async function deleteFile() {
41-
await storage.bucket(bucketName).file(fileName).delete();
55+
await storage.bucket(bucketName).file(fileName).delete(deleteOptions);
4256

4357
console.log(`gs://${bucketName}/${fileName} deleted`);
4458
}

samples/fileChangeStorageClass.js

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222
function main(
2323
bucketName = 'my-bucket',
2424
fileName = 'file.txt',
25-
storageClass = 'standard'
25+
storageClass = 'standard',
26+
generationMatchPrecondition = 0
2627
) {
2728
// [START storage_change_file_storage_class]
2829
// Imports the Google Cloud client library
@@ -46,10 +47,21 @@ function main(
4647
// const storageClass = 'coldline';
4748

4849
async function fileChangeStorageClass() {
50+
// Optional:
51+
// Set a generation-match precondition to avoid potential race conditions
52+
// and data corruptions. The request to upload is aborted if the object's
53+
// generation number does not match your precondition. For a destination
54+
// object that does not yet exist, set the ifGenerationMatch precondition to 0
55+
// If the destination object already exists in your bucket, set instead a
56+
// generation-match precondition using its generation number.
57+
const setStorageClassOptions = {
58+
ifGenerationMatch: generationMatchPrecondition,
59+
};
60+
4961
await storage
5062
.bucket(bucketName)
5163
.file(fileName)
52-
.setStorageClass(storageClass);
64+
.setStorageClass(storageClass, setStorageClassOptions);
5365

5466
console.log(`${fileName} has been set to ${storageClass}`);
5567
}

samples/fileSetMetadata.js

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,11 @@
1919
// description: Set file metadata.
2020
// usage: node fileSetMetadata.js <BUCKET_NAME> <FILE_NAME>
2121

22-
function main(bucketName = 'my-bucket', fileName = 'file.txt') {
22+
function main(
23+
bucketName = 'my-bucket',
24+
fileName = 'file.txt',
25+
generationMatchPrecondition = 0
26+
) {
2327
// [START storage_set_metadata]
2428
// Imports the Google Cloud client library
2529
const {Storage} = require('@google-cloud/storage');
@@ -37,23 +41,34 @@ function main(bucketName = 'my-bucket', fileName = 'file.txt') {
3741
// const fileName = 'your-file-name';
3842

3943
async function setFileMetadata() {
44+
// Optional: set a generation-match precondition to avoid potential race
45+
// conditions and data corruptions. The request to upload is aborted if the
46+
// object's generation number does not match your precondition.
47+
const options = {
48+
ifGenerationMatch: generationMatchPrecondition,
49+
};
50+
4051
// Set file metadata.
4152
const [metadata] = await storage
4253
.bucket(bucketName)
4354
.file(fileName)
44-
.setMetadata({
45-
// Predefined metadata for server e.g. 'cacheControl', 'contentDisposition',
46-
// 'contentEncoding', 'contentLanguage', 'contentType'
47-
contentDisposition: 'attachment; filename*=utf-8\'\'"anotherImage.jpg"',
48-
contentType: 'image/jpeg',
55+
.setMetadata(
56+
{
57+
// Predefined metadata for server e.g. 'cacheControl', 'contentDisposition',
58+
// 'contentEncoding', 'contentLanguage', 'contentType'
59+
contentDisposition:
60+
'attachment; filename*=utf-8\'\'"anotherImage.jpg"',
61+
contentType: 'image/jpeg',
4962

50-
// A note or actionable items for user e.g. uniqueId, object description,
51-
// or other useful information.
52-
metadata: {
53-
description: 'file description...',
54-
modified: '1900-01-01',
63+
// A note or actionable items for user e.g. uniqueId, object description,
64+
// or other useful information.
65+
metadata: {
66+
description: 'file description...',
67+
modified: '1900-01-01',
68+
},
5569
},
56-
});
70+
options
71+
);
5772

5873
console.log(
5974
'Updated metadata for object',

samples/moveFile.js

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@
2323
function main(
2424
bucketName = 'my-bucket',
2525
srcFileName = 'test.txt',
26-
destFileName = 'test2.txt'
26+
destFileName = 'test2.txt',
27+
destinationGenerationMatchPrecondition = 0
2728
) {
2829
// [START storage_move_file]
2930
/**
@@ -45,8 +46,24 @@ function main(
4546
const storage = new Storage();
4647

4748
async function moveFile() {
49+
// Optional:
50+
// Set a generation-match precondition to avoid potential race conditions
51+
// and data corruptions. The request to upload is aborted if the object's
52+
// generation number does not match your precondition. For a destination
53+
// object that does not yet exist, set the ifGenerationMatch precondition to 0
54+
// If the destination object already exists in your bucket, set instead a
55+
// generation-match precondition using its generation number.
56+
const moveOptions = {
57+
preconditionOpts: {
58+
ifGenerationMatch: destinationGenerationMatchPrecondition,
59+
},
60+
};
61+
4862
// Moves the file within the bucket
49-
await storage.bucket(bucketName).file(srcFileName).move(destFileName);
63+
await storage
64+
.bucket(bucketName)
65+
.file(srcFileName)
66+
.move(destFileName, moveOptions);
5067

5168
console.log(
5269
`gs://${bucketName}/${srcFileName} moved to gs://${bucketName}/${destFileName}`

samples/releaseEventBasedHold.js

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@
2020
* at https://cloud.google.com/storage/docs/bucket-lock
2121
*/
2222

23-
function main(bucketName = 'my-bucket', fileName = 'test.txt') {
23+
function main(
24+
bucketName = 'my-bucket',
25+
fileName = 'test.txt',
26+
generationMatchPrecondition = 0
27+
) {
2428
// [START storage_release_event_based_hold]
2529
/**
2630
* TODO(developer): Uncomment the following lines before running the sample.
@@ -38,9 +42,19 @@ function main(bucketName = 'my-bucket', fileName = 'test.txt') {
3842
const storage = new Storage();
3943

4044
async function releaseEventBasedHold() {
41-
await storage.bucket(bucketName).file(fileName).setMetadata({
42-
eventBasedHold: false,
43-
});
45+
// Optional: set a generation-match precondition to avoid potential race
46+
// conditions and data corruptions. The request to upload is aborted if the
47+
// object's generation number does not match your precondition.
48+
const options = {
49+
ifGenerationMatch: generationMatchPrecondition,
50+
};
51+
52+
await storage.bucket(bucketName).file(fileName).setMetadata(
53+
{
54+
eventBasedHold: false,
55+
},
56+
options
57+
);
4458
console.log(`Event-based hold was released for ${fileName}.`);
4559
}
4660

samples/releaseTemporaryHold.js

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@
2020
* at https://cloud.google.com/storage/docs/bucket-lock
2121
*/
2222

23-
function main(bucketName = 'my-bucket', fileName = 'test.txt') {
23+
function main(
24+
bucketName = 'my-bucket',
25+
fileName = 'test.txt',
26+
generationMatchPrecondition = 0
27+
) {
2428
// [START storage_release_temporary_hold]
2529
/**
2630
* TODO(developer): Uncomment the following lines before running the sample.
@@ -38,9 +42,19 @@ function main(bucketName = 'my-bucket', fileName = 'test.txt') {
3842
const storage = new Storage();
3943

4044
async function releaseTemporaryHold() {
41-
await storage.bucket(bucketName).file(fileName).setMetadata({
42-
temporaryHold: false,
43-
});
45+
// Optional: set a generation-match precondition to avoid potential race
46+
// conditions and data corruptions. The request to upload is aborted if the
47+
// object's generation number does not match your precondition.
48+
const options = {
49+
ifGenerationMatch: generationMatchPrecondition,
50+
};
51+
52+
await storage.bucket(bucketName).file(fileName).setMetadata(
53+
{
54+
temporaryHold: false,
55+
},
56+
options
57+
);
4458
console.log(`Temporary hold was released for ${fileName}.`);
4559
}
4660

0 commit comments

Comments
 (0)