-
Notifications
You must be signed in to change notification settings - Fork 108
feat: new transaction feature #1239
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: new transaction feature #1239
Conversation
Transaction state should move up to the super class
Add a method for building transaction options. Also add a method for detecting if a request is a transaction. Build new transaction options
Corrected getTransactionRequest. Build the request options properly.
When this system test isn’t set to be a readOnly transaction then the error occurs which says too much contention.
Change parseRunSuccess so that it can be used more universally.
parseRunSuccess should move up to the super class because it now needs to be used there.
This change saves the transaction id returned from the server for read calls
Read only tests are needed
Make sure that code using the new transaction option has better performance than code that doesn’t have it.
Use the MockedTransactionWrapper to test requests being passed into the Gapic layer.
Mock out begin transaction. Test for newTransaction consistency type. Mock out commit.
A transaction.run test is needed for lookup, lookup, put, commit.
Add a test for this sequence of operations and ensure it works properly.
Four operations that get all the results for running an aggregation query. Adding another test for these four operations.
Last test suite regarding new transaction unit tests.
Add a bunch of tests for the commit case. Check the commit gapic input.
Begin transaction should be called at least once. Add code here to increment the counter.
Remove commented code too.
Check for expired on most functions and write tests for the expired check.
…anieljbruce/nodejs-datastore into new-transaction-feature-branch
| } | ||
| } | ||
|
|
||
| it('should pass read time into runQuery for transactions', async () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that this test is no longer valid because transaction and read time are no longer compatible together as is the case in Python.
|
|
||
| /** | ||
| * Retrieve the entities as a readable object stream. | ||
| * |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: update L381 with new added errors?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure. Done.
| callback(new Error(transactionExpiredError)); | ||
| return; | ||
| } | ||
| if (this.state === TransactionState.NOT_STARTED) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just wondering what are the allowed states here? NOT_TRANSACTION and IN_PROGRESS?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NOT_TRANSACTION, NOT_STARTED, IN_PROGRESS, EXPIRED.
src/request.ts
Outdated
| if (this.state === TransactionState.EXPIRED) { | ||
| callback(new Error(transactionExpiredError)); | ||
| return; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to check readTimeAndConsistencyError here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No. That check is done further downstream in the call to runQueryStream. But I did spot some other cases where errors weren't bubbling up and fixed those bugs.
Fix the concurrency tests and move the error reporting outside of the stream, add two tests for the streams to make sure errors get reported.
This makes it so that it is reported in the streams.
daniel-sanche
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
| export function getTransactionRequest( | ||
| transaction: Transaction, | ||
| options: RunOptions | ||
| ): TransactionRequestOptions { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please add some comments
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
src/request.ts
Outdated
| if (id) { | ||
| reqOpts.readWrite = {previousTransaction: id}; | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is there a way to trim down this logic a bit? Seems a bit redundant
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I generated unit tests, corrected them and then reduced this function down to one ternary operation. Previously this was just copy pasted code from before. Search describe('getTransactionRequest', () => { to see how this function should behave.
I am going to rewrite the getTransactionRequest function so it is a good idea not to change how it works.
Fix the compiler error Change code so that when readOnly is specified then readwrite options are ignored. Fix the unit test to adopt this change.
Add comments, simplify logic in the function.
…anieljbruce/nodejs-datastore into new-transaction-feature-branch
Summary
This PR ensures that transaction read calls will use newTransaction options to begin transactions instead of making a separate
beginTransactiongrpc call.Source code changes
A
#blockWithMutexfunction is added and it is used for read calls instead of a#withBeginTransactionfunction. This makes it so that all read calls on Transaction will block on the mutex and then call the same method in their super class. Before this change, the read calls on Transaction would block on the mutex, make abeginTransactiongrpc call and then call the same method in their super class. So this change to using#blockWithMutexomits the extrabeginTransactioncall and instead expects the function it is calling to supply new transaction options.A function
getTransactionRequestis added which pulls out the code used for building transaction options for abeginTransactionrequest. That is because this code is also used to build the new transaction options.TransactionState is moved up to the super class
DatastoreRequestand a new state is added calledNOT_TRANSACTIONforDataRequeststhat are not transactions.parseTransactionResponseis moved up to the super classDatastoreRequestand is now used byrunQuery,runAggregationQueryandgetto save the transaction id.newTransactionoptions are now built ingetRequestOptionswhich is used byrunQuery,runAggregationQueryandgetto save the transaction id.stateis moved up to theDatastoreRequestsuper class because it now has to be used to decide whether or not to build newTransaction options.If a transaction is expired then an error will be thrown when the transaction is used.
ReadOptions are the options shared by Datastore read requests.
new_transaction is a consistency type in ReadOptions. When new_transaction is used in a read request, a new transaction is begun for the request.
System tests added
A system test is added to ensure using new transaction has better latency. System tests are added for runQuery, runAggregationQuery and get for readOnly transactions to ensure readOnly transactions work correctly whether
transaction.runis called or not.Unit tests added
Unit tests are added for various orders of transaction operations that ensure correct behaviour for when
transaction.runis used and whentransaction.runis omitted.lookup, lookup, put, commitis one order that is tested. The others arerunQuery, lookup, put, commit,runAggregationQuery, lookup, put, commit,put, put, lookup, commitandput, commit. A unit test is also corrected.Drawbacks
If the user uses
transaction.runQueryStreamor they usetransaction.createReadStreamthen the call will not block on a mutex. These methods are not async methods so they cannot wait for a#blockWithMutexcall to complete. If users are currently usingrunQueryStreamorcreateReadStreamconcurrently then these multiple read calls may be beginning multiple transactions at the same time using one transaction object which is not ideal.