Skip to content

Commit 7011508

Browse files
authored
Merge branch 'main' into storagebatchoperations-samples
2 parents f664754 + 3a7ad1c commit 7011508

26 files changed

+4446
-56
lines changed

spanner/batch-write.js

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
/**
2+
* Copyright 2024 Google LLC
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
// sample-metadata:
17+
// title: Batch Write
18+
// usage: node batch-write.js <INSTANCE_ID> <DATABASE_ID> <PROJECT_ID>
19+
20+
'use strict';
21+
22+
async function main(
23+
instanceId = 'my-instance',
24+
databaseId = 'my-database',
25+
projectId = 'my-project-id'
26+
) {
27+
// [START spanner_batch_write_at_least_once]
28+
29+
// Imports the Google Cloud client library
30+
const {Spanner, MutationGroup} = require('@google-cloud/spanner');
31+
32+
/**
33+
* TODO(developer): Uncomment the following lines before running the sample.
34+
*/
35+
// const instanceId = 'my-instance';
36+
// const databaseId = 'my-database';
37+
// const projectId = 'my-project-id';
38+
39+
// Creates a client
40+
const spanner = new Spanner({
41+
projectId: projectId,
42+
});
43+
44+
// Gets a reference to a Cloud Spanner instance and database
45+
const instance = spanner.instance(instanceId);
46+
const database = instance.database(databaseId);
47+
48+
// Create Mutation Groups
49+
/**
50+
* Related mutations should be placed in a group, such as insert mutations for both a parent and a child row.
51+
* A group must contain related mutations.
52+
* Please see {@link https://cloud.google.com/spanner/docs/reference/rpc/google.spanner.v1#google.spanner.v1.BatchWriteRequest.MutationGroup}
53+
* for more details and examples.
54+
*/
55+
const mutationGroup1 = new MutationGroup();
56+
mutationGroup1.insert('Singers', {
57+
SingerId: 1,
58+
FirstName: 'Scarlet',
59+
LastName: 'Terry',
60+
});
61+
62+
const mutationGroup2 = new MutationGroup();
63+
mutationGroup2.insert('Singers', {
64+
SingerId: 2,
65+
FirstName: 'Marc',
66+
});
67+
mutationGroup2.insert('Singers', {
68+
SingerId: 3,
69+
FirstName: 'Catalina',
70+
LastName: 'Smith',
71+
});
72+
mutationGroup2.insert('Albums', {
73+
AlbumId: 1,
74+
SingerId: 2,
75+
AlbumTitle: 'Total Junk',
76+
});
77+
mutationGroup2.insert('Albums', {
78+
AlbumId: 2,
79+
SingerId: 3,
80+
AlbumTitle: 'Go, Go, Go',
81+
});
82+
83+
const options = {
84+
transactionTag: 'batch-write-tag',
85+
};
86+
87+
try {
88+
await new Promise((resolve, reject) => {
89+
database
90+
.batchWriteAtLeastOnce([mutationGroup1, mutationGroup2], options)
91+
.on('error', err => {
92+
reject(err);
93+
})
94+
.on('data', response => {
95+
// Check the response code of each response to determine whether the mutation group(s) were applied successfully.
96+
if (response.status.code === 0) {
97+
console.log(
98+
`Mutation group indexes ${
99+
response.indexes
100+
}, have been applied with commit timestamp ${Spanner.timestamp(
101+
response.commitTimestamp
102+
).toJSON()}`
103+
);
104+
}
105+
// Mutation groups that fail to commit trigger a response with a non-zero status code.
106+
else {
107+
console.log(
108+
`Mutation group indexes ${response.indexes}, could not be applied with error code ${response.status.code}, and error message ${response.status.message}`
109+
);
110+
}
111+
})
112+
.on('end', () => {
113+
console.log('Request completed successfully');
114+
resolve();
115+
});
116+
});
117+
} catch (err) {
118+
console.log(err);
119+
} finally {
120+
await database.close();
121+
}
122+
// [END spanner_batch_write_at_least_once]
123+
}
124+
125+
main(...process.argv.slice(2));

spanner/batch.js

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
// Copyright 2018 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
'use strict';
16+
17+
async function createAndExecuteQueryPartitions(
18+
instanceId,
19+
databaseId,
20+
projectId
21+
) {
22+
// [START spanner_batch_client]
23+
// Imports the Google Cloud client library
24+
const {Spanner} = require('@google-cloud/spanner');
25+
26+
/**
27+
* TODO(developer): Uncomment the following lines before running the sample.
28+
*/
29+
// const projectId = 'my-project-id';
30+
// const instanceId = 'my-instance';
31+
// const databaseId = 'my-database';
32+
33+
// Creates a client
34+
const spanner = new Spanner({
35+
projectId: projectId,
36+
});
37+
38+
// Gets a reference to a Cloud Spanner instance and database
39+
const instance = spanner.instance(instanceId);
40+
const database = instance.database(databaseId);
41+
42+
let transaction;
43+
44+
try {
45+
[transaction] = await database.createBatchTransaction();
46+
47+
const query = {
48+
sql: 'SELECT * FROM Singers',
49+
// DataBoost option is an optional parameter which can also be used for partition read
50+
// and query to execute the request via spanner independent compute resources.
51+
dataBoostEnabled: true,
52+
};
53+
54+
// A Partition object is serializable and can be used from a different process.
55+
const [partitions] = await transaction.createQueryPartitions(query);
56+
console.log(`Successfully created ${partitions.length} query partitions.`);
57+
58+
let rowCount = 0;
59+
const promises = partitions.map(partition =>
60+
transaction.execute(partition).then(results => {
61+
const rows = results[0].map(row => row.toJSON());
62+
rowCount += rows.length;
63+
})
64+
);
65+
await Promise.all(promises);
66+
console.log(`Successfully received ${rowCount} from executed partitions.`);
67+
} catch (err) {
68+
console.error('Error executing query partitions:', err);
69+
} finally {
70+
if (transaction) {
71+
transaction.close();
72+
}
73+
await database.close();
74+
}
75+
// [END spanner_batch_client]
76+
}
77+
78+
async function executePartition(
79+
instanceId,
80+
databaseId,
81+
identifier,
82+
partition,
83+
projectId
84+
) {
85+
// [START spanner_batch_execute_partitions]
86+
// Imports the Google Cloud client library
87+
const {Spanner} = require('@google-cloud/spanner');
88+
89+
/**
90+
* TODO(developer): Uncomment the following lines before running the sample.
91+
*/
92+
// const projectId = 'my-project-id';
93+
// const instanceId = 'my-instance';
94+
// const databaseId = 'my-database';
95+
// const identifier = {};
96+
// const partition = {};
97+
98+
// Creates a client
99+
const spanner = new Spanner({
100+
projectId: projectId,
101+
});
102+
103+
// Gets a reference to a Cloud Spanner instance and database
104+
const instance = spanner.instance(instanceId);
105+
const database = instance.database(databaseId);
106+
const transaction = database.batchTransaction(identifier);
107+
108+
const [rows] = await transaction.execute(partition);
109+
console.log(`Successfully received ${rows.length} from executed partition.`);
110+
// [END spanner_batch_execute_partitions]
111+
}
112+
113+
require('yargs')
114+
.demandCommand(1)
115+
.command(
116+
'create-and-execute-query-partitions <instanceName> <databaseName> <projectId>',
117+
'Creates query partitions and executes them.',
118+
{},
119+
opts =>
120+
createAndExecuteQueryPartitions(
121+
opts.instanceName,
122+
opts.databaseName,
123+
opts.projectId
124+
)
125+
)
126+
.command(
127+
'execute-partition <instanceName> <databaseName> <identifier> <partition> <projectId>',
128+
'Executes a partition.',
129+
{},
130+
opts =>
131+
executePartition(
132+
opts.instanceName,
133+
opts.databaseName,
134+
JSON.parse(opts.identifier),
135+
JSON.parse(opts.partition),
136+
opts.projectId
137+
)
138+
)
139+
.example(
140+
'node $0 create-and-execute-query-partitions "my-instance" "my-database" "my-project-id"'
141+
)
142+
.example(
143+
'node $0 execute-partition "my-instance" "my-database" "{}" "{}" "my-project-id"'
144+
)
145+
.wrap(120)
146+
.recommendCommands()
147+
.epilogue('For more information, see https://cloud.google.com/spanner/docs')
148+
.strict()
149+
.help().argv;

0 commit comments

Comments
 (0)