Skip to content
This repository was archived by the owner on Mar 4, 2026. It is now read-only.

fix: Optimize Transaction PITR#2002

Merged
tom-andersen merged 5 commits intomainfrom
tomandersen/transactionReadTimeOptimization
Feb 28, 2024
Merged

fix: Optimize Transaction PITR#2002
tom-andersen merged 5 commits intomainfrom
tomandersen/transactionReadTimeOptimization

Conversation

@tom-andersen
Copy link
Copy Markdown
Contributor

@tom-andersen tom-andersen commented Feb 23, 2024

For transactions with read time, the begin transaction and commit can be omitted, thereby decreasing latency.

b/324245706

@product-auto-label product-auto-label Bot added size: l Pull request size is large. api: firestore Issues related to the googleapis/nodejs-firestore API. labels Feb 23, 2024
@tom-andersen tom-andersen changed the title Optimize Transaction PITR fix: Optimize Transaction PITR Feb 23, 2024
@conventional-commit-lint-gcf
Copy link
Copy Markdown

conventional-commit-lint-gcf Bot commented Feb 23, 2024

🤖 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 automerge label. Good luck human!

-- conventional-commit-lint bot
https://conventionalcommits.org/

@tom-andersen tom-andersen marked this pull request as ready for review February 23, 2024 23:38
@tom-andersen tom-andersen requested review from a team February 23, 2024 23:38
Comment thread dev/src/transaction.ts
requestTag: this._requestTag,
})
.then(() => {});
async commit(): Promise<void> {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is purely a refactor to use async syntax.

Comment thread dev/src/transaction.ts
.then(resp => {
this._transactionId = resp.transaction!;
});
const resp = await this._firestore.request<
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is purely a refactor to use async syntax.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. Nice improvement.

expect(snapshot.exists).to.be.true;
expect(snapshot.get('foo')).to.equal(1);
});

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added client side exceptions to attempting write on readonly transaction, so this integration test is no longer valid.

@MarkDuckworth MarkDuckworth self-assigned this Feb 28, 2024
Copy link
Copy Markdown
Contributor

@MarkDuckworth MarkDuckworth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Direction looks good. There are a few comments for your consideration.

Comment thread dev/src/transaction.ts
): Transaction {
if (this._readOnly) {
throw new Error(READ_ONLY_WRITE_ERROR_MSG);
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There has been a recent movement in the SDKs to leave runtime validation up to the server. In this case, I think performing the validation in the client is acceptable because a read-only transaction should never be writable, that will not change. Calling this out for your consideration.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For ReadTime transactions, we don't call commit which would normally be when backend could respond. So this is less preference, and more technical requirement.

Comment thread dev/src/transaction.ts
.then(resp => {
this._transactionId = resp.transaction!;
});
const resp = await this._firestore.request<
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. Nice improvement.

Comment thread dev/src/transaction.ts
})
.then(() => {});
async commit(): Promise<void> {
if (this._readTime) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to check if the _readOnly flag is set instead of _readTime. The type safety will not guarantee runTransaction will be called for a readOnly transaction without readTime being set.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ReadOnly but without ReadTime are still transactions that have BeginTransaction and Commit request. That is why I have to use _readTime, since only in the subset of cases where the transaction if ReadOnly AND with ReadTime can we do the optimization.

However, this is also a little weird of a check that I added, since this will only occur if there is a bug in SDK. The customer never has an opportunity to call commit() on transactions. Calling commit() is done implicitly when update lambda completes. So this should never happen so long as our SDK logic is correct.

Comment thread dev/src/transaction.ts
async runTransactionOnce<T>(
updateFunction: (transaction: Transaction) => Promise<T>
): Promise<T> {
if (!this._readTime) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment with respect to using _readOnly vs _readTime

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again this optimization only works for the subset of ReadOnly transaction that have ReadTime.

Comment thread dev/src/transaction.ts
);
}
const result = await promise;
if (!this._readTime) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dido

@tom-andersen tom-andersen merged commit 2f08612 into main Feb 28, 2024
@tom-andersen tom-andersen deleted the tomandersen/transactionReadTimeOptimization branch February 28, 2024 19:29
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

api: firestore Issues related to the googleapis/nodejs-firestore API. size: l Pull request size is large.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants