-
Notifications
You must be signed in to change notification settings - Fork 149
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: Lazy-started transactions #2017
feat: Lazy-started transactions #2017
Conversation
🤖 I detect that the PR title and the commit message differ and there's only one commit. To use the PR title for the commit history, you can use Github's automerge feature with squashing, or use -- conventional-commit-lint bot |
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.
Thank you for the quite large contribution. I prefer if the rollback optimization based on error code was moved to a separate PR. I am not convinced that this change is correct. Verifying will hold up this PR. The problem is with reads having created locks, that should be released. If we wait for timeout of transaction, that can create problems for retry and other clients working on same documents.
I am giving you some preliminary feedback, but will return to do a more thorough review.
I sent you a PR to change the tests. For readTime
, we do not need a transaction at all. This will eliminate the need to wait for first request to complete with transactionId, and this will also overcome potential transaction timeout.
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.
Overall, I really like your implementation. There are a few things I would like to see changed, but then I see no reason why this shouldn't be approved and merged.
Note, there will be a delay before we can merge since this has to fit into our upcoming release schedule. We should have this out by April.
There we go. With this last commit GitHub seems to have gotten itself unstuck. I've implemented all of those suggestions. You haven't seen the second-to-last commit |
@tom-andersen I ran this branch against a real Firestore backend and oops there were a few gotchas
Warrants another review sorry. |
dev/src/reference.ts
Outdated
): Promise<QuerySnapshot<AppModelType, DbModelType>> { | ||
return this._queryUtil._get(this, transactionIdOrReadTime) as Promise< | ||
async _get( | ||
transactionIdOrReadTime?: Uint8Array | Timestamp | api.ITransactionOptions |
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.
s/transactionIdOrReadTime
/transactionOrReadTime
dev/test/transaction.ts
Outdated
rollback('foo1'), | ||
query({newTransaction: {readWrite: {}}, error: serverError}), | ||
// No rollback because the lazy-start operation failed | ||
//rollback('foo1'), |
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 any value in keeping these //rollback('foo1')
?
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.
There is no transaction id yet, since that is part of the result from first query. So we can't rollback, even if we wanted to.
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.
yup. I'm just saying we should remove the commented code.
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.
Ahh. Good point! +1
dev/src/transaction.ts
Outdated
return this._transactionIdPromise.then(async opts => { | ||
const r = await resultFn.call(this, param, opts); | ||
return r.result; | ||
}); |
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: to make it more consistent with the rest of this function
return this._transactionIdPromise
.then(opts => resultFn.call(this, param, opts))
.then(r => r.result);
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.
This is fantastic. There are many nice code improvements, but it's also a significant community contribution. Thank you for your efforts.
I have a few additional comments for your consideration. But otherwise I think it looks good.
The only potential adverse affect would be if a customer is implementing parallel reads in a transaction using get()
, then this has a possibility to slow the transaction if the first read is slow/large-doc. But in many cases that could be mitigated with a call to getAll()
.
const docs: Array<QueryDocumentSnapshot<AppModelType, DbModelType>> = []; | ||
const output: Omit<QueryResponse<never>, 'result'> & { | ||
readTime?: Timestamp; | ||
} = {}; |
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: Instead of this complex type definition, it might be more readable code to just construct a new type, or single object definition. Or even just keep a few individual properties.
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.
Thanks for your contribution @brettwillis . LGTM -- only the remaining minor comments should be addressed.
Eliminates at least one round-trip network request for every transaction by the following
beginTransaction
request. All subsequent reads (and commit/rollback) are queued upon the first read operation of each transaction attempt.Eliminate superfluous rollback request for some types of commit errors (where the transaction is already aborted by the server)getResponse
API to theDocumentReader
,Query
andAggregateQuery
classes to expose the transaction ID in the response._stream()
APIs now emit a "transaction response" as the first element when appropriate.Other opportunistic improvements
Fixes #2015