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: make retry parameter public and added in other methods #331

Merged
merged 6 commits into from Dec 9, 2020
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
18 changes: 15 additions & 3 deletions google/cloud/storage/_helpers.py
Expand Up @@ -145,6 +145,7 @@ def reload(
if_generation_not_match=None,
if_metageneration_match=None,
if_metageneration_not_match=None,
retry=DEFAULT_RETRY,
):
"""Reload properties from Cloud Storage.

Expand Down Expand Up @@ -187,6 +188,9 @@ def reload(
:type if_metageneration_not_match: long
:param if_metageneration_not_match: (Optional) Make the operation conditional on whether the
blob's current metageneration does not match the given value.

:type retry: google.api_core.retry.Retry
Copy link
Contributor

Choose a reason for hiding this comment

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

Technically either google.api_core.retry.Retry or google.cloud.storage.retry.ConditionalRetryPolicy are supported here, and in some cases ConditionalRetryPolicy is the default so despite the complexity we should document it here.

:param retry: (Optional) How to retry the RPC.
Copy link
Contributor

Choose a reason for hiding this comment

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

In order for users to use this, they'll need an explanation of what kinds of objects to pass in and how to modify them. "See retry.py" might be enough if retry.py's comments and docstrings are comprehensive.

"""
client = self._require_client(client)
query_params = self._query_params
Expand All @@ -207,7 +211,7 @@ def reload(
headers=self._encryption_headers(),
_target_object=self,
timeout=timeout,
retry=DEFAULT_RETRY,
retry=retry,
)
self._set_properties(api_response)

Expand Down Expand Up @@ -247,6 +251,7 @@ def patch(
if_generation_not_match=None,
if_metageneration_match=None,
if_metageneration_not_match=None,
retry=DEFAULT_RETRY_IF_METAGENERATION_SPECIFIED,
):
"""Sends all changed properties in a PATCH request.

Expand Down Expand Up @@ -286,6 +291,9 @@ def patch(
:type if_metageneration_not_match: long
:param if_metageneration_not_match: (Optional) Make the operation conditional on whether the
blob's current metageneration does not match the given value.

:type retry: google.api_core.retry.Retry
:param retry: (Optional) How to retry the RPC.
"""
client = self._require_client(client)
query_params = self._query_params
Expand All @@ -309,7 +317,7 @@ def patch(
query_params=query_params,
_target_object=self,
timeout=timeout,
retry=DEFAULT_RETRY_IF_METAGENERATION_SPECIFIED,
retry=retry,
)
self._set_properties(api_response)

Expand All @@ -321,6 +329,7 @@ def update(
if_generation_not_match=None,
if_metageneration_match=None,
if_metageneration_not_match=None,
retry=DEFAULT_RETRY_IF_METAGENERATION_SPECIFIED,
):
"""Sends all properties in a PUT request.

Expand Down Expand Up @@ -360,6 +369,9 @@ def update(
:type if_metageneration_not_match: long
:param if_metageneration_not_match: (Optional) Make the operation conditional on whether the
blob's current metageneration does not match the given value.

:type retry: google.api_core.retry.Retry
:param retry: (Optional) How to retry the RPC.
"""
client = self._require_client(client)

Expand All @@ -380,7 +392,7 @@ def update(
query_params=query_params,
_target_object=self,
timeout=timeout,
retry=DEFAULT_RETRY_IF_METAGENERATION_SPECIFIED,
retry=retry,
)
self._set_properties(api_response)

Expand Down
45 changes: 36 additions & 9 deletions google/cloud/storage/acl.py
Expand Up @@ -85,6 +85,7 @@
"""

from google.cloud.storage.constants import _DEFAULT_TIMEOUT
from google.cloud.storage.retry import DEFAULT_RETRY


class _ACLEntity(object):
Expand Down Expand Up @@ -430,7 +431,7 @@ def _require_client(self, client):
client = self.client
return client

def reload(self, client=None, timeout=_DEFAULT_TIMEOUT):
def reload(self, client=None, timeout=_DEFAULT_TIMEOUT, retry=DEFAULT_RETRY):
Copy link
Contributor

Choose a reason for hiding this comment

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

Here in the ACL file you're not just exposing retries in the function signature but actually adding a new default, right? @frankyn ACL commands aren't in the consolidated retry strategy doc, do we want retries enabled on them?

Copy link
Member

Choose a reason for hiding this comment

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

ACLs don't have optimistic concurrency control, therefore we would need to update implementation to rely on storage.objects.patch and storage.buckets.patch instead of ACL specific APIs.

Let's remove ACL retries from this PR for now and open a tracking issue.

"""Reload the ACL data from Cloud Storage.

If :attr:`user_project` is set, bills the API request to that project.
Expand All @@ -445,6 +446,9 @@ def reload(self, client=None, timeout=_DEFAULT_TIMEOUT):

Can also be passed as a tuple (connect_timeout, read_timeout).
See :meth:`requests.Session.request` documentation for details.

:type retry: google.api_core.retry.Retry
:param retry: (Optional) How to retry the RPC.
"""
path = self.reload_path
client = self._require_client(client)
Expand All @@ -456,13 +460,19 @@ def reload(self, client=None, timeout=_DEFAULT_TIMEOUT):
self.entities.clear()

found = client._connection.api_request(
method="GET", path=path, query_params=query_params, timeout=timeout
method="GET",
path=path,
query_params=query_params,
timeout=timeout,
retry=retry,
)
self.loaded = True
for entry in found.get("items", ()):
self.add_entity(self.entity_from_dict(entry))

def _save(self, acl, predefined, client, timeout=_DEFAULT_TIMEOUT):
def _save(
Copy link
Contributor

Choose a reason for hiding this comment

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

We've investigated and found that ACL save retries don't support the concurrency control we'd need to have full faith in retries here. Please go ahead and remove them. Thanks!

self, acl, predefined, client, timeout=_DEFAULT_TIMEOUT, retry=DEFAULT_RETRY
):
"""Helper for :meth:`save` and :meth:`save_predefined`.

:type acl: :class:`google.cloud.storage.acl.ACL`, or a compatible list.
Expand All @@ -483,6 +493,9 @@ def _save(self, acl, predefined, client, timeout=_DEFAULT_TIMEOUT):

Can also be passed as a tuple (connect_timeout, read_timeout).
See :meth:`requests.Session.request` documentation for details.

:type retry: google.api_core.retry.Retry
:param retry: (Optional) How to retry the RPC.
"""
query_params = {"projection": "full"}
if predefined is not None:
Expand All @@ -501,13 +514,16 @@ def _save(self, acl, predefined, client, timeout=_DEFAULT_TIMEOUT):
data={self._URL_PATH_ELEM: list(acl)},
query_params=query_params,
timeout=timeout,
retry=retry,
)
self.entities.clear()
for entry in result.get(self._URL_PATH_ELEM, ()):
self.add_entity(self.entity_from_dict(entry))
self.loaded = True

def save(self, acl=None, client=None, timeout=_DEFAULT_TIMEOUT):
def save(
self, acl=None, client=None, timeout=_DEFAULT_TIMEOUT, retry=DEFAULT_RETRY
):
"""Save this ACL for the current bucket.

If :attr:`user_project` is set, bills the API request to that project.
Expand All @@ -526,6 +542,9 @@ def save(self, acl=None, client=None, timeout=_DEFAULT_TIMEOUT):

Can also be passed as a tuple (connect_timeout, read_timeout).
See :meth:`requests.Session.request` documentation for details.

:type retry: google.api_core.retry.Retry
:param retry: (Optional) How to retry the RPC.
"""
if acl is None:
acl = self
Expand All @@ -534,9 +553,11 @@ def save(self, acl=None, client=None, timeout=_DEFAULT_TIMEOUT):
save_to_backend = True

if save_to_backend:
self._save(acl, None, client, timeout=timeout)
self._save(acl, None, client, timeout=timeout, retry=retry)

def save_predefined(self, predefined, client=None, timeout=_DEFAULT_TIMEOUT):
def save_predefined(
self, predefined, client=None, timeout=_DEFAULT_TIMEOUT, retry=DEFAULT_RETRY
):
"""Save this ACL for the current bucket using a predefined ACL.

If :attr:`user_project` is set, bills the API request to that project.
Expand All @@ -558,11 +579,14 @@ def save_predefined(self, predefined, client=None, timeout=_DEFAULT_TIMEOUT):

Can also be passed as a tuple (connect_timeout, read_timeout).
See :meth:`requests.Session.request` documentation for details.

:type retry: google.api_core.retry.Retry
:param retry: (Optional) How to retry the RPC.
"""
predefined = self.validate_predefined(predefined)
self._save(None, predefined, client, timeout=timeout)
self._save(None, predefined, client, timeout=timeout, retry=retry)

def clear(self, client=None, timeout=_DEFAULT_TIMEOUT):
def clear(self, client=None, timeout=_DEFAULT_TIMEOUT, retry=DEFAULT_RETRY):
"""Remove all ACL entries.

If :attr:`user_project` is set, bills the API request to that project.
Expand All @@ -582,8 +606,11 @@ def clear(self, client=None, timeout=_DEFAULT_TIMEOUT):

Can also be passed as a tuple (connect_timeout, read_timeout).
See :meth:`requests.Session.request` documentation for details.

:type retry: google.api_core.retry.Retry
:param retry: (Optional) How to retry the RPC.
"""
self.save([], client=client, timeout=timeout)
self.save([], client=client, timeout=timeout, retry=retry)


class BucketACL(ACL):
Expand Down