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

fix: consume part of StreamingResponseIterator to support failure while under a retry context #10206

Merged
merged 7 commits into from
Jan 30, 2020

Conversation

crwilcox
Copy link
Contributor

@crwilcox crwilcox commented Jan 24, 2020

In the Node.js SDK, there's code that explicitly waits until at least one result has been observed and retries the underlying stream until then. This doesn't handle the case where the connection is interrupted mid-stream but has been good enough to resolve this class of issues. https://github.com/googleapis/nodejs-firestore/blob/master/dev/src/index.ts#L1127

The Firestore Python SDK needs equivalent code to make it resilient to this class of failure.

This PR causes init of the streaming response iterator to consume the first result immediately which will cause the error to occur while under the retry context. Once the iterator is created it is returned and future access is no longer in a retry context.

@googlebot googlebot added the cla: yes This human has signed the Contributor License Agreement. label Jan 24, 2020
@crwilcox crwilcox added the do not merge Indicates a pull request not ready for merge, due to either quality or timing. label Jan 24, 2020
try:
self._first_result = six.next(self._wrapped)
self._stored_first_result = True
except StopIteration:

Choose a reason for hiding this comment

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

Will this work for the WatchStream? For Watch, the client has to send the first request. We will not receive a response until after this request has been processed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Watch uses ResumableBidiRpc and has its own way of managing recovery. This will have an effect on things like query though.

Copy link
Contributor

@tseaver tseaver left a comment

Choose a reason for hiding this comment

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

I would use only a single instance variable here, and arrange to set / clear it atomically.

@crwilcox
Copy link
Contributor Author

NOTE: 3 tests look to need refactoring, also should likely improve coverage given this new behavior.

# to retrieve the first result, in order to fail, in order to trigger a retry.
try:
self._stored_first_result = six.next(self._wrapped)
except TypeError:
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@tseaver Under test we have a non-iterable. While it is odd that you would call this without it does seem possible? So added a guard here

@crwilcox crwilcox changed the title fix: consume part of StreamingResponseIterator to support failure while under a retry context. fix: consume part of StreamingResponseIterator to support failure while under a retry context Jan 27, 2020
@crwilcox crwilcox removed the do not merge Indicates a pull request not ready for merge, due to either quality or timing. label Jan 27, 2020
This was referenced Feb 4, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api: core cla: yes This human has signed the Contributor License Agreement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants