diff --git a/samples/concepts.js b/samples/concepts.js index e77c2a799..c96a7e53f 100644 --- a/samples/concepts.js +++ b/samples/concepts.js @@ -1102,7 +1102,7 @@ class Transaction extends TestHelper { const [task] = await transaction.get(taskKey); if (task) { // The task entity already exists. - transaction.rollback(); + await transaction.rollback(); } else { // Create the task entity. transaction.save(taskEntity); @@ -1110,7 +1110,7 @@ class Transaction extends TestHelper { } return taskEntity; } catch (err) { - transaction.rollback(); + await transaction.rollback(); } } // [END datastore_transactional_get_or_create] diff --git a/samples/tasks.js b/samples/tasks.js index c15a0d745..e31c82958 100644 --- a/samples/tasks.js +++ b/samples/tasks.js @@ -112,7 +112,7 @@ async function markDone(taskId) { await transaction.commit(); console.log(`Task ${taskId} updated successfully.`); } catch (err) { - transaction.rollback(); + await transaction.rollback(); } } // [END datastore_update_entity] diff --git a/samples/tasks.markdone.js b/samples/tasks.markdone.js index 8fb6d0c99..ed6491050 100644 --- a/samples/tasks.markdone.js +++ b/samples/tasks.markdone.js @@ -44,7 +44,7 @@ async function main(taskId) { await transaction.commit(); console.log(`Task ${taskId} updated successfully.`); } catch (err) { - transaction.rollback(); + await transaction.rollback(); throw err; } } diff --git a/src/request.ts b/src/request.ts index b284ec36c..643c76420 100644 --- a/src/request.ts +++ b/src/request.ts @@ -1301,7 +1301,13 @@ class DatastoreRequest { const transaction = this.datastore.transaction(); transaction.run(async err => { if (err) { - transaction.rollback(); + try { + await transaction.rollback(); + } catch (error) { + // Provide the error & API response from the failed run to the user. + // Even a failed rollback should be transparent. + // RE: https://github.com/GoogleCloudPlatform/gcloud-node/pull/1369#discussion_r66833976 + } callback!(err); return; } @@ -1321,7 +1327,13 @@ class DatastoreRequest { const [response] = await transaction.commit(); callback!(null, response); } catch (err) { - transaction.rollback(); + try { + await transaction.rollback(); + } catch (error) { + // Provide the error & API response from the failed commit to the user. + // Even a failed rollback should be transparent. + // RE: https://github.com/GoogleCloudPlatform/gcloud-node/pull/1369#discussion_r66833976 + } callback!(err); } }); diff --git a/test/request.ts b/test/request.ts index f3adf1978..a2567f633 100644 --- a/test/request.ts +++ b/test/request.ts @@ -2251,6 +2251,38 @@ describe('Request', () => { done(); }); }); + + it('should avoid the rollback exception in transaction.run', done => { + sandbox + .stub(transaction, 'run') + .callsFake((gaxOption, callback?: Function) => { + callback = typeof gaxOption === 'function' ? gaxOption : callback!; + callback(new Error('Error.')); + }); + + sandbox + .stub(transaction, 'rollback') + .rejects(new Error('Rollback Error.')); + + request.merge({key, data: null}, (err: Error) => { + assert.strictEqual(err.message, 'Error.'); + done(); + }); + }); + + it('should avoid the rollback exception in transaction.get/commit', done => { + sandbox.restore(); + sandbox.stub(transaction, 'get').rejects(new Error('Error.')); + + sandbox + .stub(transaction, 'rollback') + .rejects(new Error('Rollback Error.')); + + request.merge({key, data: null}, (err: Error) => { + assert.strictEqual(err.message, 'Error.'); + done(); + }); + }); }); describe('request_', () => {