-
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
Add gateway timeout to pubsub pull #2576
Add gateway timeout to pubsub pull #2576
Conversation
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.
LGTM pending Travis
Rather than raising a 504, wouldn't we rather match the semantics of the JSON API and return an empty list? |
@tseaver could do that. How would the user know to retry in that case? |
@tseaver I am 👎 on swallowing exceptions. It's up to the API implementers to make sure the JSON and gRPC surface is sufficiently similar. |
A timeout exception due to no messages isn't really "exceptional." Long-running subscriber processes are going to be retrying anyway, inside a |
@tseaver, wouldn't the Or I guess I would think that if the deadline was exceeded then the user would need to take action on that information? |
We paper over lots of differences between the different API surfaces already: it has been an explicit goal that the user doesn't notice or care about them. @daspecster I'm arguing that users shouldn't need to care about this gRPC-only timeout exception at all: if we propagate it, then they have to catch it, but it doesn't "mean" anything to them beyond "there are no messages to process," which is exactly what returning an empty sequence tells them. |
@tseaver I'm not seeing where this is the same or different from the ackDeadline or other normal operations. It sounds like if there were no messages after the deadline then it would just return nothing and not throw an error?
https://cloud.google.com/pubsub/docs/reference/rpc/google.pubsub.v1#pullresponse |
@tseaver I'm not disputing that but this is an error being converted into a successful (empty) response. We don't even have a repro yet confirming this is intended / deterministic behavior. We should at least hear from someone on the API team / see official docs that confirm a gRPC 504 is equivalent to an empty result. |
|
@tmatsuo Can you chime in here? |
@tmatsuo could you check this out when you have a second? |
bd83972
to
2a078e0
Compare
2a078e0
to
ddc98d4
Compare
Bump |
@daspecster Can you give snippets / stacktraces of what happens for the exact same client code, but one with gRPC disabled and one with it enabled? |
Here is my test file. from google.cloud import pubsub
client = pubsub.Client()
topic = client.topic('test-padding')
if not topic.exists():
topic.create()
subscription = topic.subscription('test-padding')
if not subscription.exists():
subscription.create()
messages = subscription.pull()
print(messages) With gRPC: $ python test_pubsub_padding.py
Traceback (most recent call last):
File "test_pubsub_padding.py", line 18, in <module>
messages = subscription.pull()
File "/Users/daspecster/.virtualenvs/gct/lib/python2.7/site-packages/google/cloud/pubsub/subscription.py", line 328, in pull
self.full_name, return_immediately, max_messages)
File "/Users/daspecster/.virtualenvs/gct/lib/python2.7/site-packages/google/cloud/pubsub/_gax.py", line 414, in subscription_pull
return_immediately=return_immediately)
File "/Users/daspecster/.virtualenvs/gct/lib/python2.7/site-packages/google/cloud/gapic/pubsub/v1/subscriber_api.py", line 545, in pull
return self._pull(request, options)
File "/Users/daspecster/.virtualenvs/gct/lib/python2.7/site-packages/google/gax/api_callable.py", line 481, in inner
return api_caller(api_call, this_settings, request)
File "/Users/daspecster/.virtualenvs/gct/lib/python2.7/site-packages/google/gax/api_callable.py", line 469, in base_caller
return api_call(*args)
File "/Users/daspecster/.virtualenvs/gct/lib/python2.7/site-packages/google/gax/api_callable.py", line 434, in inner
errors.create_error('RPC failed', cause=exception))
File "/Users/daspecster/.virtualenvs/gct/lib/python2.7/site-packages/google/gax/api_callable.py", line 430, in inner
return a_func(*args, **kwargs)
File "/Users/daspecster/.virtualenvs/gct/lib/python2.7/site-packages/google/gax/api_callable.py", line 64, in inner
return a_func(*updated_args, **kwargs)
File "/Users/daspecster/.virtualenvs/gct/lib/python2.7/site-packages/grpc/_channel.py", line 481, in __call__
return _end_unary_response_blocking(state, False, deadline)
File "/Users/daspecster/.virtualenvs/gct/lib/python2.7/site-packages/grpc/_channel.py", line 432, in _end_unary_response_blocking
raise _Rendezvous(state, None, None, deadline)
google.gax.errors.GaxError: GaxError(RPC failed, caused by <_Rendezvous of RPC that terminated with (StatusCode.DEADLINE_EXCEEDED, Deadline Exceeded)>)
E1121 11:08:01.032859000 140736417121216 network_status_tracker.c:48] Memory leaked as all network endpoints were not shut down With gRPC disabled: $ GOOGLE_CLOUD_DISABLE_GRPC=true python test_pubsub_padding.py
[] |
I didn't want it to be true, so I stripped out our library and just made low(ish)-level requests with each transport: https://gist.github.com/dhermes/ac47b7b6eebfd46febbd9ee3d824436d Unfortunately it IS true. The HTTP surface returns a 200 and the gRPC surface returns with an error set to After confirming this sad "contradiction", I now agree with @tseaver that we should wrap the |
60s to wait for a timeout is a long time, but I feel like if we do make this assumption (i.e. that the surfaces differ), then we should bake that assumption into the system tests, so we can quickly fix it if the assumption ceases to be true. |
We found a Contributor License Agreement for you (the sender of this pull request) and all commit authors, but as best as we can tell these commits were authored by someone else. If that's the case, please add them to this pull request and have them confirm that they're okay with these commits being contributed to Google. If we're mistaken and you did author these commits, just reply here to confirm. |
84c04a4
to
724c428
Compare
CLAs look good, thanks! |
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.
You'll need an extra unit test to check the branch I added (i.e. we only suppress the DEADLINE_EXCEEDED if return immediately was false)
@@ -415,6 +415,8 @@ def subscription_pull(self, subscription_path, return_immediately=False, | |||
except GaxError as exc: | |||
if exc_to_code(exc.cause) == StatusCode.NOT_FOUND: | |||
raise NotFound(subscription_path) | |||
if exc_to_code(exc.cause) == StatusCode.DEADLINE_EXCEEDED: |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
f18e454
to
c9c00b7
Compare
Squashed! |
raise NotFound(subscription_path) | ||
elif exc_to_code(exc.cause) == StatusCode.DEADLINE_EXCEEDED: |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
c9c00b7
to
892e34e
Compare
…t-to-pubsub-pull Add gateway timeout to pubsub pull
Based from #2575.
Implement exception for pubsub subscription pull.
Fixes: #2574