GoogleAdsService doesn't properly apply retries when Retry is passed in
Original report: https://github.com/googleads/google-ads-python/issues/597 Directed to this project by @BenRKarl
Excerpt:
GoogleAdsServiceprovidessearch(), which accepts aretry: google.api_core.retry.Retry. The Retry decorator ends up only getting applied on the first request, making it effectively useless for large results with many pages.Subsequent requests are issued by
SearchPager, initialized a few lines down, whereretryis not passed in, thus making it unavailable at evocation, where everySearchPager._method()call is not retry-decorated.
See original report (above) for environment details, steps to reproduce, some context background, followup questions, etc.
~~I'd also opened fix PR https://github.com/googleads/google-ads-python/pull/598, but I'm told it's code generated from this library.~~ I've opened https://github.com/googleapis/gapic-generator-python/pull/1245 that fixes Retry() for search().
We're catching up on old bug reports. Is this still an issue?
Yeah, probably. I've made custom fixes in my usages that's been in place for a long time now:
I'm just going to give up on this, due to lack of support from Google. Luckily, this is Python, so it's possible to peer under the interface and develop a custom workaround.
If you're here reading this, takeaways so you can implement/workaround/fix yourself:
- The built-in retry & timeout mechanism for both
search_stream()andsearch()is broken & unreliable
search_stream()- completely broken, likely cannot be mitigated at the Python level
- retry only applies to "the returning of the non-materialized generator", i.e. useless
- timeout wraps the entire stream, so you'll need to know the result size ahead of time
search()- only applies retry & timeouts to the first paginated requestsearch()can be made resilient by applying retry and timeout to every request, not just the first
With the fix, search() is far more reliable than search_stream(), which doesn't even properly handle retries and timeouts in the first place, given its streaming nature and the naive retry and timeout semantics.