Skip to content

Commit dacf869

Browse files
feat: optimisticLock option for getTransaction method (#2028)
* feat: add option for optimistic lock in getTransaction method * feat: add option for optimistic lock in getTransaction method * add sample for read and write transaction * add sample for read and write transaction * chore: add integration test for the read/write query samples * fix: presubmit error * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * fix: presubmit error * refactor: sample doc * refactor: sample doc * refator: getTransaction method * fix: lint errors * fix: lint errors * refactor: remove logs * fix: presubmit error * fix: lint errors * test: add a unit test for getTransaction * tests: add integration and unit test for getTransaction options properties * fix: lint errors * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * refactor: naming convention for varaible in getTransaction method * refactor: naming convention for varaible in getTransaction method * fix: lint errors * fix: lint error --------- Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
1 parent 5292e03 commit dacf869

File tree

4 files changed

+71
-2
lines changed

4 files changed

+71
-2
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ system-test/*key.json
1212
.DS_Store
1313
package-lock.json
1414
__pycache__
15+
.vscode

src/database.ts

+29-2
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,13 @@ export interface GetIamPolicyOptions {
224224
gaxOptions?: CallOptions;
225225
}
226226

227+
/**
228+
* @typedef {object} GetTransactionOptions
229+
* * @property {boolean} [optimisticLock] The optimistic lock a
230+
* {@link Transaction} should use while running.
231+
*/
232+
export type GetTransactionOptions = Omit<RunTransactionOptions, 'timeout'>;
233+
227234
export type CreateSessionCallback = ResourceCallback<
228235
Session,
229236
spannerClient.spanner.v1.ISession
@@ -1989,16 +1996,36 @@ class Database extends common.GrpcServiceObject {
19891996
* });
19901997
* ```
19911998
*/
1992-
getTransaction(): Promise<[Transaction]>;
1999+
getTransaction(
2000+
optionsOrCallback?: GetTransactionOptions
2001+
): Promise<[Transaction]>;
19932002
getTransaction(callback: GetTransactionCallback): void;
19942003
getTransaction(
2004+
optionsOrCallback?: GetTransactionOptions | GetTransactionCallback,
19952005
callback?: GetTransactionCallback
19962006
): void | Promise<[Transaction]> {
2007+
const cb =
2008+
typeof optionsOrCallback === 'function'
2009+
? (optionsOrCallback as GetTransactionCallback)
2010+
: callback;
2011+
const options =
2012+
typeof optionsOrCallback === 'object' && optionsOrCallback
2013+
? (optionsOrCallback as GetTransactionOptions)
2014+
: {};
19972015
this.pool_.getSession((err, session, transaction) => {
2016+
if (options.requestOptions) {
2017+
transaction!.requestOptions = Object.assign(
2018+
transaction!.requestOptions || {},
2019+
options.requestOptions
2020+
);
2021+
}
2022+
if (options.optimisticLock) {
2023+
transaction!.useOptimisticLock();
2024+
}
19982025
if (!err) {
19992026
this._releaseOnEnd(session!, transaction!);
20002027
}
2001-
callback!(err as grpc.ServiceError | null, transaction);
2028+
cb!(err as grpc.ServiceError | null, transaction);
20022029
});
20032030
}
20042031

system-test/spanner.ts

+18
Original file line numberDiff line numberDiff line change
@@ -8894,6 +8894,24 @@ describe('Spanner', () => {
88948894
mismatchedColumnError(done, DATABASE, googleSqlTable);
88958895
});
88968896

8897+
it('GOOGLE_STANDARD_SQL should use getTransaction for executing sql', async () => {
8898+
const transaction = (
8899+
await DATABASE.getTransaction({optimisticLock: true})
8900+
)[0];
8901+
8902+
try {
8903+
const [rows] = await transaction!.run('SELECT * FROM TxnTable');
8904+
assert.strictEqual(rows.length, googleSqlRecords.length);
8905+
} catch (err) {
8906+
// flaky failures are acceptable here as long as the error is not due to a lock conflict
8907+
if ((err as grpc.ServiceError).code === grpc.status.ABORTED) {
8908+
assert.ok(err, 'Transaction is aborted');
8909+
}
8910+
} finally {
8911+
transaction.end();
8912+
}
8913+
});
8914+
88978915
it('POSTGRESQL should throw an error for mismatched columns', function (done) {
88988916
if (IS_EMULATOR_ENABLED) {
88998917
this.skip();

test/spanner.ts

+23
Original file line numberDiff line numberDiff line change
@@ -3286,6 +3286,29 @@ describe('Spanner with mock server', () => {
32863286
});
32873287
});
32883288

3289+
it('should use optimistic lock and transaction tag for getTransaction', async () => {
3290+
const database = newTestDatabase();
3291+
const promise = await database.getTransaction({
3292+
optimisticLock: true,
3293+
requestOptions: {transactionTag: 'transaction-tag'},
3294+
});
3295+
const transaction = promise[0];
3296+
await transaction.run('SELECT 1').then(results => {
3297+
const request = spannerMock.getRequests().find(val => {
3298+
return (val as v1.ExecuteSqlRequest).sql;
3299+
}) as v1.ExecuteSqlRequest;
3300+
assert.ok(request, 'no ExecuteSqlRequest found');
3301+
assert.strictEqual(
3302+
request.transaction!.begin!.readWrite!.readLockMode,
3303+
'OPTIMISTIC'
3304+
);
3305+
assert.strictEqual(
3306+
request.requestOptions?.transactionTag,
3307+
'transaction-tag'
3308+
);
3309+
});
3310+
});
3311+
32893312
it('should reuse a session for optimistic and pessimistic locks', async () => {
32903313
const database = newTestDatabase({min: 1, max: 1});
32913314
let session1;

0 commit comments

Comments
 (0)