Skip to content
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: retry BatchGetDocuments RPCs that fail with errors #1544

Merged
merged 9 commits into from
Jun 25, 2021

Conversation

schmidt-sebastian
Copy link
Contributor

This PR moves the existing logic for Firestore.getAll() to a new class and adds a new retry mechanism that is similar to the current Query RPC retry.

Fixes #1387

@schmidt-sebastian schmidt-sebastian requested review from a team as code owners June 24, 2021 18:15
@google-cla google-cla bot added the cla: yes This human has signed the Contributor License Agreement. label Jun 24, 2021
@product-auto-label product-auto-label bot added the api: firestore Issues related to the googleapis/nodejs-firestore API. label Jun 24, 2021
@schmidt-sebastian schmidt-sebastian force-pushed the mrschmidt/getall branch 2 times, most recently from 8baf0a9 to 207d054 Compare June 24, 2021 18:23
* as part of a transaction.
*
* @param firestore The Firestore instance to use.
* @param allDocuments The documents to receive.

Choose a reason for hiding this comment

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

documents to *get?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

/** An optional transaction ID to use for this read. */
transactionId?: Uint8Array;

private remainingDocuments = new Set<string>();

Choose a reason for hiding this comment

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

nit: something more specific like unfetchedDocuments or requestedDocuments?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Renamed to outstandingDocuments. Pretty outstanding, me thinks.

*
* @param requestTag A unique client-assigned identifier for this request.
*/
async get(requestTag: string): Promise<Array<DocumentSnapshot<T>>> {

Choose a reason for hiding this comment

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

If get() is only meant to be run once, the method should throw an error if it is run again

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is only meant to be run once, but it should work if run multiple times. It will return the same result without doing any work.

}

const path = document.ref.formattedName;
this.remainingDocuments.delete(path);

Choose a reason for hiding this comment

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

optional: add assert() to check that path is in the set.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Skipped for now.

);
throw err;
} else {
logger(

Choose a reason for hiding this comment

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

Is the maximum number of retries allowed capped?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No, I thought it would be better not to. But then I changed my mind. I rewrote this logic to only fetch more results if we made some progress, which should ensure that we never end up in a loop with just errors. This also removes the need to add backoff, which I otherwise should have done.

FYI - This rewrite was pretty complicated, so I ended up changing the implementation to use async iterators. I did this in steps in case you want to see more reasonable diffs.

Copy link

@thebrianchen thebrianchen left a comment

Choose a reason for hiding this comment

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

lgtm

private retrievedDocuments = new Map<string, DocumentSnapshot>();

/**
* Internal method to retrieve multiple documents from Firestore, optionally

Choose a reason for hiding this comment

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

nit: it seems weird to call the constructor an "internal method". Move this comment elsewhere?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh, that's an old comment. Updated.

@schmidt-sebastian schmidt-sebastian added the kokoro:force-run Add this label to force Kokoro to re-run the tests. label Jun 25, 2021
@yoshi-kokoro yoshi-kokoro removed the kokoro:force-run Add this label to force Kokoro to re-run the tests. label Jun 25, 2021
@schmidt-sebastian schmidt-sebastian merged commit b39dd3c into master Jun 25, 2021
@schmidt-sebastian schmidt-sebastian deleted the mrschmidt/getall branch June 25, 2021 22:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api: firestore Issues related to the googleapis/nodejs-firestore API. cla: yes This human has signed the Contributor License Agreement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Retry batchGet RESOURCE_EXHAUSTED
3 participants