-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
Conversation
try: | ||
self._first_result = six.next(self._wrapped) | ||
self._stored_first_result = True | ||
except StopIteration: |
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.
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.
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.
Watch uses ResumableBidiRpc
and has its own way of managing recovery. This will have an effect on things like query
though.
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 would use only a single instance variable here, and arrange to set / clear it atomically.
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: |
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.
@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
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.