diff --git a/README.md b/README.md index ed4c06756..cff2046b8 100644 --- a/README.md +++ b/README.md @@ -208,6 +208,7 @@ Samples are in the [`samples/`](https://github.com/googleapis/nodejs-spanner/tre | Drops a foreign key constraint with delete cascade action | [source code](https://github.com/googleapis/nodejs-spanner/blob/main/samples/table-drop-foreign-key-constraint-delete-cascade.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-spanner&page=editor&open_in_editor=samples/table-drop-foreign-key-constraint-delete-cascade.js,samples/README.md) | | Timestamp | [source code](https://github.com/googleapis/nodejs-spanner/blob/main/samples/timestamp.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-spanner&page=editor&open_in_editor=samples/timestamp.js,samples/README.md) | | Executes a read/write transaction with transaction and request tags | [source code](https://github.com/googleapis/nodejs-spanner/blob/main/samples/transaction-tag.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-spanner&page=editor&open_in_editor=samples/transaction-tag.js,samples/README.md) | +| Executes a read/write transaction with transaction timeout | [source code](https://github.com/googleapis/nodejs-spanner/blob/main/samples/transaction-timeout.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-spanner&page=editor&open_in_editor=samples/transaction-timeout.js,samples/README.md) | | Transaction | [source code](https://github.com/googleapis/nodejs-spanner/blob/main/samples/transaction.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-spanner&page=editor&open_in_editor=samples/transaction.js,samples/README.md) | | Updates a backup schedule | [source code](https://github.com/googleapis/nodejs-spanner/blob/main/samples/update-backup-schedule.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-spanner&page=editor&open_in_editor=samples/update-backup-schedule.js,samples/README.md) | | Updates an instance. | [source code](https://github.com/googleapis/nodejs-spanner/blob/main/samples/update-instance-default-backup-schedule-type.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-spanner&page=editor&open_in_editor=samples/update-instance-default-backup-schedule-type.js,samples/README.md) | diff --git a/samples/README.md b/samples/README.md index bf09c546a..b91aad776 100644 --- a/samples/README.md +++ b/samples/README.md @@ -133,6 +133,7 @@ and automatic, synchronous replication for high availability. * [Drops a foreign key constraint with delete cascade action](#drops-a-foreign-key-constraint-with-delete-cascade-action) * [Timestamp](#timestamp) * [Executes a read/write transaction with transaction and request tags](#executes-a-read/write-transaction-with-transaction-and-request-tags) + * [Executes a read/write transaction with transaction timeout](#executes-a-read/write-transaction-with-transaction-timeout) * [Transaction](#transaction) * [Updates a backup schedule](#updates-a-backup-schedule) * [Updates an instance.](#updates-an-instance.) @@ -2175,6 +2176,23 @@ __Usage:__ +### Executes a read/write transaction with transaction timeout + +View the [source code](https://github.com/googleapis/nodejs-spanner/blob/main/samples/transaction-timeout.js). + +[![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-spanner&page=editor&open_in_editor=samples/transaction-timeout.js,samples/README.md) + +__Usage:__ + + +`node transaction-timeout.js ` + + +----- + + + + ### Transaction View the [source code](https://github.com/googleapis/nodejs-spanner/blob/main/samples/transaction.js). diff --git a/samples/system-test/spanner.test.js b/samples/system-test/spanner.test.js index a3fa9b558..ef54d3bba 100644 --- a/samples/system-test/spanner.test.js +++ b/samples/system-test/spanner.test.js @@ -36,6 +36,7 @@ const rpcPriorityQueryPartitionsCommand = 'node rpc-priority-query-partitions.js'; const transactionCmd = 'node transaction.js'; const transactionTagCommand = 'node transaction-tag.js'; +const transactionTimeoutCommand = 'node transaction-timeout.js'; const requestTagCommand = 'node request-tag.js'; const timestampCmd = 'node timestamp.js'; const structCmd = 'node struct.js'; @@ -1237,6 +1238,14 @@ describe('Autogenerated Admin Clients', () => { assert.include(output, 'Inserted new outdoor venue'); }); + // read_write_transaction with transaction timeout + it('should execute a read/write transaction with a transaction timeout of 60 seconds', async () => { + const output = execSync( + `${transactionTimeoutCommand} ${INSTANCE_ID} ${DATABASE_ID} ${PROJECT_ID}`, + ); + assert.include(output, '1 record inserted.'); + }); + // add_json_column it('should add a VenueDetails column to Venues example table', async () => { const output = execSync( diff --git a/samples/transaction-timeout.js b/samples/transaction-timeout.js new file mode 100644 index 000000000..e51c94113 --- /dev/null +++ b/samples/transaction-timeout.js @@ -0,0 +1,77 @@ +/** + * Copyright 2025 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: Executes a read/write transaction with transaction timeout +// usage: node transaction-timeout.js + +'use strict'; + +function main(instanceId, databaseId, projectId) { + // [START spanner_transaction_timeout] + /** + * TODO(developer): Uncomment the following lines before running the sample. + */ + // const projectId = 'my-project-id'; + // const instanceId = 'my-instance'; + // const databaseId = 'my-database'; + + // Imports the Google Cloud client library + const {Spanner} = require('@google-cloud/spanner'); + + // Creates a client + const spanner = new Spanner({ + projectId: projectId, + }); + + async function executeTransactionWithTimeout() { + // Gets a reference to a Cloud Spanner instance and database. + const instance = spanner.instance(instanceId); + const database = instance.database(databaseId); + + const options = { + timeout: 60000, // 60 seconds timeout + }; + + try { + await database.runTransactionAsync(options, async tx => { + const [results] = await tx.run( + 'SELECT SingerId, FirstName, LastName FROM Singers ORDER BY LastName, FirstName', + ); + results.forEach(result => { + console.log( + `${result[0].name}: ${result[0].value.value}, ${result[1].name}: ${result[1].value}, ${result[2].name}: ${result[2].value}`, + ); + }); + const sql = + "INSERT INTO Singers (SingerId, FirstName, LastName) VALUES (100, 'George', 'Washington')"; + const [rowCount] = await tx.runUpdate(sql); + console.log(`${rowCount} record inserted.`); + await tx.commit(); + }); + } catch (err) { + console.error('ERROR:', err); + } finally { + await database.close(); + } + } + executeTransactionWithTimeout(); + // [END spanner_transaction_timeout] +} +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); +main(...process.argv.slice(2));