Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: optimisticLock option for getTransaction method #2028

Merged
merged 25 commits into from
Apr 17, 2024
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
fcfe1ab
feat: add option for optimistic lock in getTransaction method
alkatrivedi Apr 4, 2024
b901522
feat: add option for optimistic lock in getTransaction method
alkatrivedi Apr 4, 2024
c8d7f40
add sample for read and write transaction
alkatrivedi Apr 5, 2024
b201049
add sample for read and write transaction
alkatrivedi Apr 5, 2024
5a638d7
chore: add integration test for the read/write query samples
alkatrivedi Apr 5, 2024
773ba9a
Merge branch 'googleapis:main' into get-transaction-method
alkatrivedi Apr 5, 2024
aeb1129
fix: presubmit error
alkatrivedi Apr 5, 2024
943bab4
🦉 Updates from OwlBot post-processor
gcf-owl-bot[bot] Apr 5, 2024
9038541
fix: presubmit error
alkatrivedi Apr 5, 2024
3b00ce1
refactor: sample doc
alkatrivedi Apr 5, 2024
aaa3575
refactor: sample doc
alkatrivedi Apr 5, 2024
ee47fe4
refator: getTransaction method
alkatrivedi Apr 10, 2024
c7fedbc
fix: lint errors
alkatrivedi Apr 10, 2024
37e9bb8
fix: lint errors
alkatrivedi Apr 10, 2024
fcabb63
refactor: remove logs
alkatrivedi Apr 15, 2024
b84750a
fix: presubmit error
alkatrivedi Apr 15, 2024
b856166
fix: lint errors
alkatrivedi Apr 15, 2024
e937ba8
test: add a unit test for getTransaction
alkatrivedi Apr 15, 2024
a063abd
tests: add integration and unit test for getTransaction options prope…
alkatrivedi Apr 16, 2024
3c46110
fix: lint errors
alkatrivedi Apr 16, 2024
c45ce29
🦉 Updates from OwlBot post-processor
gcf-owl-bot[bot] Apr 16, 2024
415057c
refactor: naming convention for varaible in getTransaction method
alkatrivedi Apr 16, 2024
ab6112f
refactor: naming convention for varaible in getTransaction method
alkatrivedi Apr 16, 2024
d12157a
fix: lint errors
alkatrivedi Apr 16, 2024
e8c5bce
fix: lint error
alkatrivedi Apr 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ system-test/*key.json
.DS_Store
package-lock.json
__pycache__
.vscode
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ Samples are in the [`samples/`](https://github.com/googleapis/nodejs-spanner/tre
| Reads data using an existing storing index. | [source code](https://github.com/googleapis/nodejs-spanner/blob/main/samples/index-read-data-with-storing.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/index-read-data-with-storing.js,samples/README.md) |
| Read data using an existing index. | [source code](https://github.com/googleapis/nodejs-spanner/blob/main/samples/index-read-data.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/index-read-data.js,samples/README.md) |
| Indexing | [source code](https://github.com/googleapis/nodejs-spanner/blob/main/samples/indexing.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/indexing.js,samples/README.md) |
| Calls a server side function on a Spanner PostgreSQL database. | [source code](https://github.com/googleapis/nodejs-spanner/blob/main/samples/insert-query-with-get-trasanction.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/insert-query-with-get-trasanction.js,samples/README.md) |
| Creates a user-managed instance configuration. | [source code](https://github.com/googleapis/nodejs-spanner/blob/main/samples/instance-config-create.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/instance-config-create.js,samples/README.md) |
| Deletes a user-managed instance configuration. | [source code](https://github.com/googleapis/nodejs-spanner/blob/main/samples/instance-config-delete.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/instance-config-delete.js,samples/README.md) |
| Lists the instance configuration operations. | [source code](https://github.com/googleapis/nodejs-spanner/blob/main/samples/instance-config-get-operations.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/instance-config-get-operations.js,samples/README.md) |
Expand Down Expand Up @@ -170,6 +171,7 @@ Samples are in the [`samples/`](https://github.com/googleapis/nodejs-spanner/tre
| Queryoptions | [source code](https://github.com/googleapis/nodejs-spanner/blob/main/samples/queryoptions.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/queryoptions.js,samples/README.md) |
| Quickstart | [source code](https://github.com/googleapis/nodejs-spanner/blob/main/samples/quickstart.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/quickstart.js,samples/README.md) |
| Read data with database role | [source code](https://github.com/googleapis/nodejs-spanner/blob/main/samples/read-data-with-database-role.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/read-data-with-database-role.js,samples/README.md) |
| Calls a server side function on a Spanner PostgreSQL database. | [source code](https://github.com/googleapis/nodejs-spanner/blob/main/samples/read-query-with-get-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/read-query-with-get-transaction.js,samples/README.md) |
| Sets a request tag for a single query | [source code](https://github.com/googleapis/nodejs-spanner/blob/main/samples/request-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/request-tag.js,samples/README.md) |
| Run Batch update with RPC priority | [source code](https://github.com/googleapis/nodejs-spanner/blob/main/samples/rpc-priority-batch-dml.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/rpc-priority-batch-dml.js,samples/README.md) |
| Run partitioned update with RPC priority | [source code](https://github.com/googleapis/nodejs-spanner/blob/main/samples/rpc-priority-partitioned-dml.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/rpc-priority-partitioned-dml.js,samples/README.md) |
Expand Down
36 changes: 36 additions & 0 deletions samples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ and automatic, synchronous replication for high availability.
* [Reads data using an existing storing index.](#reads-data-using-an-existing-storing-index.)
* [Read data using an existing index.](#read-data-using-an-existing-index.)
* [Indexing](#indexing)
* [Calls a server side function on a Spanner PostgreSQL database.](#calls-a-server-side-function-on-a-spanner-postgresql-database.)
* [Creates a user-managed instance configuration.](#creates-a-user-managed-instance-configuration.)
* [Deletes a user-managed instance configuration.](#deletes-a-user-managed-instance-configuration.)
* [Lists the instance configuration operations.](#lists-the-instance-configuration-operations.)
Expand Down Expand Up @@ -95,6 +96,7 @@ and automatic, synchronous replication for high availability.
* [Queryoptions](#queryoptions)
* [Quickstart](#quickstart)
* [Read data with database role](#read-data-with-database-role)
* [Calls a server side function on a Spanner PostgreSQL database.](#calls-a-server-side-function-on-a-spanner-postgresql-database.)
* [Sets a request tag for a single query](#sets-a-request-tag-for-a-single-query)
* [Run Batch update with RPC priority](#run-batch-update-with-rpc-priority)
* [Run partitioned update with RPC priority](#run-partitioned-update-with-rpc-priority)
Expand Down Expand Up @@ -775,6 +777,23 @@ __Usage:__



### Calls a server side function on a Spanner PostgreSQL database.

View the [source code](https://github.com/googleapis/nodejs-spanner/blob/main/samples/insert-query-with-get-trasanction.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/insert-query-with-get-trasanction.js,samples/README.md)

__Usage:__


`node insert-query-with-get-transaction.js <INSTANCE_ID> <DATABASE_ID> <PROJECT_ID>`


-----




### Creates a user-managed instance configuration.

View the [source code](https://github.com/googleapis/nodejs-spanner/blob/main/samples/instance-config-create.js).
Expand Down Expand Up @@ -1506,6 +1525,23 @@ __Usage:__



### Calls a server side function on a Spanner PostgreSQL database.

View the [source code](https://github.com/googleapis/nodejs-spanner/blob/main/samples/read-query-with-get-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/read-query-with-get-transaction.js,samples/README.md)

__Usage:__


`node insert-query-with-get-transaction.js <INSTANCE_ID> <DATABASE_ID> <PROJECT_ID>`


-----




### Sets a request tag for a single query

View the [source code](https://github.com/googleapis/nodejs-spanner/blob/main/samples/request-tag.js).
Expand Down
79 changes: 79 additions & 0 deletions samples/insert-query-with-get-trasanction.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Copyright 2024 Google LLC
alkatrivedi marked this conversation as resolved.
Show resolved Hide resolved
//
// 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: Perform a dml insert query using getTransaction method with optimisticLock
// usage: node insert-query-with-get-transaction.js <INSTANCE_ID> <DATABASE_ID> <PROJECT_ID>

async function main(instanceId, databaseId, projectId) {
// [START spanner_insert_query_with_get_transaction]
// Imports the Google Cloud client library.
const {Spanner, protos} = require('@google-cloud/spanner');
const Priority = protos.google.spanner.v1.RequestOptions.Priority;

/**
* TODO(developer): Uncomment the following lines before running the sample.
*/
// const projectId = 'my-project-id';
// const instanceId = 'my-instance';
// const databaseId = 'my-database';

// Creates a client
const spanner = new Spanner({
projectId: projectId,
});

async function writeTransaction() {
// Gets a reference to a Cloud Spanner instance and database
const instance = spanner.instance(instanceId);
const database = instance.database(databaseId);

const options = {
optimisticLock: true,
requestOptions: {
priority: Priority.PRIORITY_LOW,
},
};

const promise = await database.getTransaction(options);
const transaction = promise[0];

try {
const [rowCount] = await transaction.runUpdate({
sql: `INSERT Singers (SingerId, FirstName, LastName) VALUES
(1, 'Melissa', 'Garcia'),
(2, 'Russell', 'Morales'),
(3, 'Jacqueline', 'Long'),
(4, 'Dylan', 'Shaw')`,
});
console.log(
`Successfully inserted ${rowCount} records into the Singers table`
);
await transaction.commit();
} catch (err) {
console.error('ERROR:', err);
} finally {
// End the transaction
transaction.end();
}
}
writeTransaction();
// [END spanner_insert_query_with_get_transaction]
}

process.on('unhandledRejection', err => {
console.error(err.message);
process.exitCode = 1;
});
main(...process.argv.slice(2));
69 changes: 69 additions & 0 deletions samples/read-query-with-get-transaction.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// Copyright 2024 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: Perform a dml read query using getTransaction method with optimisticLock
// usage: node read-query-with-get-transaction.js <INSTANCE_ID> <DATABASE_ID> <PROJECT_ID>

async function main(instanceId, databaseId, projectId) {
// [START spanner_read_query_with_get_transaction]
// Imports the Google Cloud client library.
const {Spanner} = require('@google-cloud/spanner');

/**
* TODO(developer): Uncomment the following lines before running the sample.
*/
// const projectId = 'my-project-id';
// const instanceId = 'my-instance';
// const databaseId = 'my-database';

// Creates a client
const spanner = new Spanner({
projectId: projectId,
});

async function readTransaction() {
// Gets a reference to a Cloud Spanner instance and database
const instance = spanner.instance(instanceId);
const database = instance.database(databaseId);

const options = {
optimisticLock: true,
};

const promise = await database.getTransaction(options).then();
const transaction = promise[0];

try {
await transaction.run('SELECT * FROM Singers').then(results => {
const rows = results[0].map(row => row.toJSON());
console.log(rows);
});
} catch (err) {
console.error('ERROR:', err);
}

await transaction.commit();

transaction.end();
}
readTransaction();
// [END spanner_read_query_with_get_transaction]
}

process.on('unhandledRejection', err => {
console.error(err.message);
process.exitCode = 1;
});
main(...process.argv.slice(2));
19 changes: 19 additions & 0 deletions samples/system-test/spanner.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -825,6 +825,25 @@ describe('Autogenerated Admin Clients', () => {
);
});

// dml_standard_insert_transaction_using_getTransaction
it('should insert rows into an example table using getTransaction method', async () => {
const output = execSync(
`node insert-query-with-get-trasanction.js ${INSTANCE_ID} ${DATABASE_ID} ${PROJECT_ID}`
alkatrivedi marked this conversation as resolved.
Show resolved Hide resolved
);
assert.match(
output,
/Successfully inserted 4 records into the Singers table/
);
});

// dml_standard_read_transaction_using_getTransaction
it('should query rows from an example table using getTransaction method', async () => {
const output = execSync(
`node read-query-with-get-transaction.js ${INSTANCE_ID} ${DATABASE_ID} ${PROJECT_ID}`
);
assert.strictEqual(output.length, 4);
});

// dml_standard_insert
it('should insert rows into an example table using a DML statement', async () => {
const output = execSync(
Expand Down
32 changes: 30 additions & 2 deletions src/database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,14 @@ export interface GetIamPolicyOptions {
gaxOptions?: CallOptions;
}

/**
* @typedef {object} GetTransactionOptions
* * @property {boolean} [optimisticLock] The optimistic lock a
* {@link Transaction} should use while running.
*/

alkatrivedi marked this conversation as resolved.
Show resolved Hide resolved
export type GetTransactionOptions = Omit<RunTransactionOptions, 'timeout'>;

export type CreateSessionCallback = ResourceCallback<
Session,
spannerClient.spanner.v1.ISession
Expand Down Expand Up @@ -1989,16 +1997,36 @@ class Database extends common.GrpcServiceObject {
* });
* ```
*/
getTransaction(): Promise<[Transaction]>;
alkatrivedi marked this conversation as resolved.
Show resolved Hide resolved
getTransaction(
optionsOrCallback?: GetTransactionOptions
): Promise<[Transaction]>;
getTransaction(callback: GetTransactionCallback): void;
getTransaction(
optionsOrCallback?: GetTransactionOptions | GetTransactionCallback,
callback?: GetTransactionCallback
): void | Promise<[Transaction]> {
const runFn =
typeof optionsOrCallback === 'function'
? (optionsOrCallback as GetTransactionCallback)
: callback;
const options =
typeof optionsOrCallback === 'object' && optionsOrCallback
? (optionsOrCallback as GetTransactionOptions)
: {};
this.pool_.getSession((err, session, transaction) => {
if (options.requestOptions) {
transaction!.requestOptions = Object.assign(
transaction!.requestOptions || {},
options.requestOptions
);
}
if (options.optimisticLock) {
transaction!.useOptimisticLock();
alkatrivedi marked this conversation as resolved.
Show resolved Hide resolved
}
if (!err) {
this._releaseOnEnd(session!, transaction!);
}
callback!(err as grpc.ServiceError | null, transaction);
runFn!(err as grpc.ServiceError | null, transaction);
});
}

Expand Down